<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">

<channel>
	<title>Planet Python</title>
	<link>http://planetpython.org/</link>
	<language>en</language>
	<description>Planet Python - http://planetpython.org/</description>

<item>
	<title>PyCharm</title>
	<guid></guid>
	<link></link>
	<description>&lt;p&gt;Every developer has tools they rely on daily. The workflows they&amp;#8217;ve built around them, the ways they&amp;#8217;ve learned to move faster, debug smarter, and write better code – that kind of hands-on experience can be hard to put into words.&lt;/p&gt;



&lt;p&gt;We’re collaborating with LinkedIn to make it easier for you to showcase your expertise with JetBrains IDEs on the world’s largest professional network. You can now connect your IDE to LinkedIn and let your real tool usage speak for itself.&lt;/p&gt;



&lt;p align=&quot;center&quot;&gt;&lt;a class=&quot;jb-download-button&quot; href=&quot;https://plugins.jetbrains.com/plugin/32011-linkedin-connected-apps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;i class=&quot;download-icon&quot;&gt;&lt;/i&gt;Connect your IDE&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, Rider, GoLand, CLion, RustRover, and RubyMine are already supported via a free plugin, while support for DataGrip is coming soon.&lt;/p&gt;



&lt;p&gt;In this blog post, we’ll explain what LinkedIn connected apps are, what they mean for your profile, and how to get started.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;What this is about&lt;/h2&gt;



&lt;p&gt;Building on early &lt;a href=&quot;https://www.linkedin.com/pulse/title-newways-stand-out-verify-skills-unlock-new-hari-srinivasan-zhtvc/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;collaboration&lt;/a&gt; with Descript, Duolingo, Lovable, Relay.app, and Replit, LinkedIn is expanding the range of apps you can feature on your LinkedIn profile, turning real-world product usage into a credible, visible signal of practical tool experience. We’re glad to join forces with them to bring this to JetBrains IDE users.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote&quot;&gt;
&lt;p&gt;&lt;/p&gt;
&lt;cite&gt;“We&amp;#8217;re building new ways for members to show real, credible proof of what they&amp;#8217;re capable of, right on their LinkedIn profile. And for the brands behind these tools, there&amp;#8217;s no better endorsement than a customer who&amp;#8217;s actively using and loving your product.”&lt;br /&gt;– Dan Shapero, CEO of LinkedIn&lt;/cite&gt;&lt;/blockquote&gt;



&lt;p&gt;Connected apps let you link the tools you use in your daily work directly to your LinkedIn profile, where they appear prominently, helping you stand out to your professional network. Once connected, each app generates a simple statement based on how you actually use it. Unlike manually added skills, this is based on real usage and updates automatically as your experience evolves.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/06/In-LinkedIn-4.png&quot; alt=&quot;&quot; class=&quot;wp-image-713887&quot; /&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;How to get started&lt;/h2&gt;



&lt;p&gt;Open your JetBrains IDE, go to &lt;em&gt;Settings | Plugins&lt;/em&gt;, search for the &lt;em&gt;LinkedIn Connected Apps&lt;/em&gt; plugin under the &lt;em&gt;Marketplace&lt;/em&gt; tab, and install it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Once installed, the plugin starts collecting data locally about how you use your IDE. Depending on your usage history, you may receive an initial statement right away, which will then be updated once the plugin has collected enough data to better reflect your real IDE expertise.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/06/LinkedIn-integration-in-JetBrains-IDEs-example-1.png&quot; alt=&quot;LinkedIn-integration-in-JetBrains-IDEs-example &quot; class=&quot;wp-image-713131&quot; /&gt;



&lt;p&gt;&lt;strong&gt;Your IDE usage data stays on your machine&lt;/strong&gt;. When you are ready, you can connect your LinkedIn account and share your IDE expertise badge there. If you keep the plugin installed, your badge will update automatically as your IDE usage evolves.&lt;/p&gt;



&lt;p&gt;The plugin is free for all JetBrains IDE users.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;What’s included in this release&lt;/h2&gt;



&lt;p&gt;This is the first version of the integration, delivered as a standalone plugin rather than being built directly into the IDE. It covers IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RustRover, and RubyMine; DataGrip is not yet supported.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Usage is detected within the IDE itself, so if you use AI features via an external tool or terminal, those won&amp;#8217;t be reflected yet.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;How your IDE expertise is determined&lt;/h2&gt;



&lt;p&gt;The model is intentionally simple for now. It is designed to represent your practical use of JetBrains tools, &lt;em&gt;not &lt;/em&gt;to rank developers or certify skill levels. Our goal was to provide a solid starting point, but we know there&amp;#8217;s more to capture about how developers work with their IDEs.&lt;/p&gt;



&lt;p&gt;Statements map to different levels of experience and are generated based on how you interact with your IDE – from writing and editing code using basic features to working with debugging tools, version control, and AI-assisted workflows. For more information, see &lt;a href=&quot;https://www.jetbrains.com/help/idea/linkedin-connected-apps.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;our documentation&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;What’s coming next&lt;/h2&gt;



&lt;p&gt;We’re already working on the next version, planned for later this year. We’ll focus on improving how IDE usage, including AI feature usage, is represented, expanding support to DataGrip, and making the overall experience feel more integrated.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;FAQ&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Which JetBrains IDEs are supported?&lt;/h3&gt;



&lt;p&gt;IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RustRover, and RubyMine. Support for DataGrip is coming soon.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Why isn’t DataGrip supported yet?&lt;/h3&gt;



&lt;p&gt;DataGrip is designed for working with databases and includes workflows that differ from our other IDEs. We plan to support it soon.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Can I connect multiple IDEs?&lt;/h3&gt;



&lt;p&gt;Yes, if you use multiple supported JetBrains IDEs, you can connect each of them. You’ll get a badge for all connected IDEs.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you use multiple JetBrains accounts across different IDE instances but link them all to the same LinkedIn profile, IDE usage statements from each account will be displayed on that LinkedIn profile.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Do I need to keep the plugin installed after connecting?&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;You can share your IDE usage statement once and then remove the plugin, but note that it must remain installed if you want to track your ongoing progress and have any changes reflected on LinkedIn.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Is this feature free?&lt;/h3&gt;



&lt;p&gt;Yes, it’s available to all JetBrains IDE users at no cost.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Is this a certification?&lt;/h3&gt;



&lt;p&gt;Connected apps reflect real IDE usage and are designed to showcase applied experience, not to act as a formal certification or skill ranking. Certifications, degrees, and licenses remain important markers of professional achievement. Connected apps on LinkedIn add a different kind of signal: partner-validated tool usage that reflects practical work and can update over time.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;What data is shared with LinkedIn and JetBrains?&lt;/h3&gt;



&lt;p&gt;Only the information required to represent your connected account and IDE usage statement.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Will this help me get hired?&lt;/h3&gt;



&lt;p&gt;Having connected apps on your LinkedIn profile is extra proof of your practical experience with leading tools. While connected apps make your expertise visible, they are just one part of your profile. Think of it as a way to let your tooling speak for itself.&lt;/p&gt;



&lt;p&gt;Give it a try and let us know what you think in the comments below. We&amp;#8217;re continuing to develop this integration, and your feedback will help shape what comes next.&lt;/p&gt;</description>
	<pubDate>Wed, 17 Jun 2026 16:40:41 +0000</pubDate>
</item>
<item>
	<title>Talk Python to Me: #552: Astral joins OpenAI</title>
	<guid>https://talkpython.fm/episodes/show/552/astral-joins-openai</guid>
	<link>https://talkpython.fm/episodes/show/552/astral-joins-openai</link>
	<description>OpenAI just acquired Astral, the company behind uv, Ruff, and ty. And if your first thought was &quot;wait, is uv toast?&quot;, you are not alone. But here's the twist Charlie Marsh shared with me: he thinks they may ship more open source at OpenAI than they ever did at Astral. On this episode, we get into the acquisition, the mixed feelings, the future of your favorite Python tools, and what it's like to build right at the center of the AI universe.&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode sponsors&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;a href='https://talkpython.fm/sentry'&amp;gt;Sentry Error Monitoring, Code talkpython26&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href='https://talkpython.fm/training'&amp;gt;Talk Python Courses&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;h2 class=&quot;links-heading mb-4&quot;&amp;gt;Links from the show&amp;lt;/h2&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Guest&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Charlie Marsh&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/charliermarsh?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;The announcement&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://astral.sh/blog/openai?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;astral.sh&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;OpenAI&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://openai.com/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;openai.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;uv&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/astral-sh/uv?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;ty&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/astral-sh/ty?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Ruff&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/astral-sh/ruff?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;pyx&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://astral.sh/pyx?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;astral.sh&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Codex team&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://openai.com/codex/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;openai.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Anthropic did something similar by acquiring Bun&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.anthropic.com/news/anthropic-acquires-bun-as-claude-code-reaches-usd1b-milestone?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;www.anthropic.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Daily Stars Explorer&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://emanuelef.github.io/daily-stars-explorer/#/astral-sh/uv&quot; target=&quot;_blank&quot; &amp;gt;emanuelef.github.io&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Agentic AI Programming for Python&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://training.talkpython.fm/courses/agentic-ai-programming-for-python&quot; target=&quot;_blank&quot; &amp;gt;training.talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Python Web Security: OWASP Top 10 with Agentic AI&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://training.talkpython.fm/courses/agentic-ai-python-security&quot; target=&quot;_blank&quot; &amp;gt;training.talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode #552 deep-dive&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/episodes/show/552/astral-joins-openai#takeaways-anchor&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm/552&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode transcripts&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/episodes/transcript/552/astral-joins-openai&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Theme Song: Developer Rap&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;🥁 Served in a Flask 🎸&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/flasksong&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm/flasksong&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;---==  Don't be a stranger  ==---&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;YouTube&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/youtube&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-youtube&quot;&amp;gt;&amp;lt;/i&amp;gt; youtube.com/@talkpython&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Bluesky&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://bsky.app/profile/talkpython.fm&quot; target=&quot;_blank&quot; &amp;gt;@talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Mastodon&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://fosstodon.org/web/@talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-mastodon&quot;&amp;gt;&amp;lt;/i&amp;gt; @talkpython@fosstodon.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;X.com&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://x.com/talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-twitter&quot;&amp;gt;&amp;lt;/i&amp;gt; @talkpython&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on Bluesky&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://bsky.app/profile/mkennedy.codes?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;@mkennedy.codes&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on Mastodon&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://fosstodon.org/web/@mkennedy&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-mastodon&quot;&amp;gt;&amp;lt;/i&amp;gt; @mkennedy@fosstodon.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on X.com&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://x.com/mkennedy?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-twitter&quot;&amp;gt;&amp;lt;/i&amp;gt; @mkennedy&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;</description>
	<pubDate>Wed, 17 Jun 2026 15:20:03 +0000</pubDate>
</item>
<item>
	<title>PyCharm: Your JetBrains IDE Expertise, Now on LinkedIn</title>
	<guid>https://blog.jetbrains.com/blog/2026/06/17/your-jetbrains-ide-expertise-now-on-linkedin/</guid>
	<link>https://blog.jetbrains.com/blog/2026/06/17/your-jetbrains-ide-expertise-now-on-linkedin/</link>
	<pubDate>Wed, 17 Jun 2026 13:11:02 +0000</pubDate>
</item>
<item>
	<title>Django Weblog: Announcing the Search for a DSF Executive Director</title>
	<guid>https://www.djangoproject.com/weblog/2026/jun/17/announcing-the-search-for-a-dsf-executive-director/</guid>
	<link>https://www.djangoproject.com/weblog/2026/jun/17/announcing-the-search-for-a-dsf-executive-director/</link>
	<description>&lt;p&gt;The Django Software Foundation is hiring its first Executive Director, and we have the Django community to thank for making it possible.&lt;/p&gt;
&lt;p&gt;Six Django web development agencies have jointly pledged $47,500 to help fund the Executive Director's first year: Caktus Group, Lincoln Loop, Six Feet Up, Cuttlesoft, OddBird, and Two Rock. This is the financial foundation we needed to move from &quot;we should hire an ED someday&quot; to &quot;we are hiring an ED now.&quot;&lt;/p&gt;
&lt;h2 id=&quot;s-why-this-role-matters&quot;&gt;Why This Role Matters&lt;/h2&gt;
&lt;p&gt;The DSF has grown significantly over the past several years. We fund multiple &lt;a href=&quot;https://www.djangoproject.com/fundraising/#fellowship-program&quot;&gt;Django Fellows&lt;/a&gt;, distribute grants to events around the world, manage corporate and individual memberships, oversee working groups, and handle the legal and operational responsibilities of a 501(c)(3) nonprofit. For years, volunteer board members have carried this operational load alongside their regular jobs. That dedication has carried us far, but there are real limits to what a volunteer board can do.&lt;/p&gt;
&lt;p&gt;An Executive Director changes that. This person would handle day-to-day operations and administration, sponsorship development and partner relationships, community outreach and communications, coordination with the Django Fellows and working groups, and grant management and financial reporting.&lt;/p&gt;
&lt;p&gt;It is a paid position, part-time or full-time depending on the candidate, for someone who understands open source communities and is genuinely excited about helping Django thrive as both a framework and a foundation.&lt;/p&gt;
&lt;p&gt;&quot;For years our board has run the DSF on volunteer time, and we've hit the limits of what that can do. An Executive Director lets us actually grow the work, more support for Django Fellows, better fundraising, and the operational help we've needed for a long time,&quot; said Jeff Triplett, DSF Board President. &quot;We've talked about this hire for years, and funding was always what held us back. Six agencies who compete with each other decided to put money in together so we could finally do it. That tells you how much this community cares about Django's future.&quot;&lt;/p&gt;
&lt;h2 id=&quot;s-the-agencies-who-made-this-possible&quot;&gt;The Agencies Who Made This Possible&lt;/h2&gt;
&lt;p&gt;These six agencies compete for the same clients, but they share a foundation: Django. That shared reliance drove them to collaborate on this pledge, and we want to recognize each of them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.caktusgroup.com/&quot;&gt;Caktus Group&lt;/a&gt;&lt;/strong&gt; ($12,500), the Durham, NC consultancy founded in 2007 and known for data-intensive Django work with clients like UNICEF and the University of Chicago, put it directly. CEO Tobias McNulty said: &quot;Django is the bedrock of our business, and as a smaller team, contributing is a significant investment. We hope this coordinated action from six agencies sends a clear signal to the rest of the industry: it's time to contribute to the core technology that makes our businesses possible.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://lincolnloop.com/&quot;&gt;Lincoln Loop&lt;/a&gt;&lt;/strong&gt; ($10,000), the remote-first Python consultancy that has built platforms for Planned Parenthood, Wharton, Mozilla, and PBS, framed it as a question of sustainability. Founder Peter Baumgartner said: &quot;We've seen the Django community thrive under volunteer leadership, but we've reached a ceiling. The Executive Director role is about sustainability, providing the leadership and structure needed to scale the DSF's impact and protect Django's long-term future.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.sixfeetup.com/&quot;&gt;Six Feet Up&lt;/a&gt;&lt;/strong&gt; ($10,000), the woman-owned consultancy founded in 1999 with clients including Capital One, Purdue University, and UNEP, focused on what this means for enterprise confidence in Django. CEO Gabrielle Hendryx-Parker said: &quot;Tech leaders stake their roadmaps on the long-term viability of their technology stack. A full-time Executive Director de-risks the framework's future, protecting the robust and lasting systems we build for our clients and ensuring Django remains a bankable, innovative choice.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://cuttlesoft.com/&quot;&gt;Cuttlesoft&lt;/a&gt;&lt;/strong&gt; ($10,000), the product agency based in Tallahassee and Denver that has been building with Django since 2014, sees the hire as an investment in the whole ecosystem. Co-founder Frank Valcarcel said: &quot;Investing in a dedicated Executive Director is a proactive step toward ensuring Django's continued evolution. We believe this role will unlock new opportunities for growth and collaboration within the community, benefiting all who rely on this incredible framework.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.oddbird.net/&quot;&gt;OddBird&lt;/a&gt;&lt;/strong&gt; ($2,500), the remote boutique agency co-founded by Django core developer Jonny Gerig Meyer, has been contributing to both the framework and the community for more than 17 years. Jonny said: &quot;Adding a dedicated Executive Director helps the DSF ensure Django's long-term sustainability, giving developers and enterprise clients peace of mind choosing the Django ecosystem. This investment is a no-brainer, and we're thrilled to partner with other peer agencies to help make it a reality.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://tworock.io/&quot;&gt;Two Rock Software&lt;/a&gt;&lt;/strong&gt; ($2,500), the Django-focused custom development shop with deep roots in the Django events community, rounded out the pledge. Co-founder Peter Grandstaff, who serves as President of Django Events Foundation North America and helps run DjangoCon US, said: &quot;As President of Django Events Foundation North America, I know how hard it is for a volunteer board to run an effective organization. I feel strongly that Django is at a point where an Executive Director is the right step into the future.&quot;&lt;/p&gt;
&lt;h2 id=&quot;s-we-need-your-help-too&quot;&gt;We Need Your Help Too&lt;/h2&gt;
&lt;p&gt;This $47,500 pledge is a launchpad, not the finish line.&lt;/p&gt;
&lt;p&gt;Hiring an Executive Director means taking on a recurring cost that our current fundraising levels cannot sustain on their own. That is why the DSF is raising its annual fundraising goal from $300,000 to $500,000 (&lt;a href=&quot;https://www.djangoproject.com/weblog/2026/jun/10/dsf-2026-fundraising-goals/&quot;&gt;2026 fundraising goals&lt;/a&gt;). The additional funding reflects what it takes to responsibly hire and maintain this role, continue supporting our Django Fellows, and keep the rest of our programs running without cutting corners.&lt;/p&gt;
&lt;p&gt;Six agencies stepped up first. We are asking others to follow.&lt;/p&gt;
&lt;p&gt;If your company builds on Django, sells products that run on Django, or employs developers who work with Django every day, this is your opportunity to invest in the infrastructure that makes that possible. No contribution is too small, and every organization that joins this effort makes it easier for the next one to say yes.&lt;/p&gt;
&lt;p&gt;You can reach out directly through our &lt;a href=&quot;https://www.djangoproject.com/contact/foundation/&quot;&gt;Contact the DSF&lt;/a&gt; page to discuss a contribution toward the Executive Director fund, or make a general donation at &lt;a href=&quot;https://www.djangoproject.com/foundation/donate/&quot;&gt;djangoproject.com/foundation/donate/&lt;/a&gt;. Individual community members can also contribute via &lt;a href=&quot;https://opencollective.com/django&quot;&gt;Open Collective&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the community's help, with your company's help, we can get there.&lt;/p&gt;
&lt;h2 id=&quot;s-what-comes-next&quot;&gt;What Comes Next&lt;/h2&gt;
&lt;p&gt;The board is formalizing the hiring process and will publish the job posting in the coming weeks. When it is ready, we will announce it across the DSF blog, Django Forum, Django Discord, and our other community channels.&lt;/p&gt;
&lt;p&gt;If you know someone who would be a great fit for this role, start thinking about them now.&lt;/p&gt;
&lt;p&gt;Thank you to Caktus Group, Lincoln Loop, Six Feet Up, Cuttlesoft, OddBird, and Two Rock for leading the way.&lt;/p&gt;</description>
	<pubDate>Wed, 17 Jun 2026 13:00:00 +0000</pubDate>
</item>
<item>
	<title>Python Software Foundation: Everything Security at PyCon US 2026</title>
	<guid>https://pyfound.blogspot.com/2026/06/everything-security-at-pycon-us-2026.html</guid>
	<link>https://pyfound.blogspot.com/2026/06/everything-security-at-pycon-us-2026.html</link>
	<description>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h1 class=&quot;heading-element&quot;&gt;&lt;/h1&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#everything-security-at-pycon-us-2026&quot; id=&quot;user-content-everything-security-at-pycon-us-2026&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Phew, PyCon US 2026 is a wrap! Now it's time
to share about everything security that happened
in case you weren't able to attend (or you just want to reminisce). Subscribe to
the &lt;a href=&quot;https://www.youtube.com/@PyConUS&quot; rel=&quot;nofollow&quot;&gt;PyCon US channel on YouTube&lt;/a&gt;
so you're notified as soon as recordings for each talk are published.
This blog post will also be updated with links once all
talks are available.&lt;/p&gt;&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h2 class=&quot;heading-element&quot;&gt;PyCon US Security Track&lt;/h2&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#pycon-us-security-track&quot; id=&quot;user-content-pycon-us-security-track&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv9gYHjX6merpeiYfk0AI-9uH1Ql3AYV5q76TkKHdpjI_W1NXnaIJfRQMCeNMdVrUMmjhNCmFw3fIohcEH22oKeJRlbi24iUDkHxHlNY9cgME8bIecsVrYTLlJreirlvuOZN7GkIWyZ7HCCNPsqYIizL6pGcOiJC8Nmt6WFVewSIr1gog6VQ/s4032/IMG_5052.jpeg&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv9gYHjX6merpeiYfk0AI-9uH1Ql3AYV5q76TkKHdpjI_W1NXnaIJfRQMCeNMdVrUMmjhNCmFw3fIohcEH22oKeJRlbi24iUDkHxHlNY9cgME8bIecsVrYTLlJreirlvuOZN7GkIWyZ7HCCNPsqYIizL6pGcOiJC8Nmt6WFVewSIr1gog6VQ/s320/IMG_5052.jpeg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;Hala Ali on generating SBOMs directly from the Python runtime&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/juanitagomezr/&quot; target=&quot;_blank&quot;&gt;Juanita Gomez&lt;/a&gt; and &lt;a href=&quot;https://sethmlarson.dev/&quot; target=&quot;_blank&quot;&gt;Seth Larson&lt;/a&gt; were the chairs of the first talk track dedicated to security at PyCon US: &lt;a href=&quot;https://us.pycon.org/2026/tracks/security/&quot; target=&quot;_blank&quot;&gt;Trailblazing Python Security&lt;/a&gt;! We're excited to share the recordings for each talk featured in the track:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Anatomy of a Phishing Campaign&lt;/b&gt; by Mike Fiedler&lt;/li&gt;&lt;li&gt;&lt;b&gt;Zero Trust in 200ms: Implementing Identity-Per-Transaction with Python and Serverless&lt;/b&gt; by Tristian McKinnon&lt;/li&gt;&lt;li&gt;&lt;b&gt;Rust for CPython&lt;/b&gt; by Emma Smith&lt;/li&gt;&lt;li&gt;&lt;b&gt;Asleep at the Wheel: SBOMit for Python builds&lt;/b&gt; by Sanchit Sahay and Abhishek Reddypalle&lt;/li&gt;&lt;li&gt;&lt;b&gt;Post-Incident Runtime SBOM Generation from Python memory&lt;/b&gt; by Hala Ali&lt;/li&gt;&lt;li&gt;&lt;b&gt;GitHub Actions Security in Python Packages&lt;/b&gt; by Andrew Nesbitt&lt;/li&gt;&lt;li&gt;&lt;b&gt;Breaking Bad (Packages): Why Traditional Vulnerability Tracking 
Fails Supply Chain Attacks&lt;/b&gt; by Shelby Cunningham and Madison Ficorilli&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Thanks so much to the speakers and volunteers who helped make this inaugural track a success. For several of the talks above the room was &lt;b&gt;standing-room only!&lt;/b&gt;&amp;nbsp;The support and interest in security topics from the Python community was incredible to see and we're hoping to see you all again next year to continue learning and sharing ideas.&lt;/p&gt;&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h2 class=&quot;heading-element&quot;&gt;PSF Security Update&lt;/h2&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#psf-security-update&quot; id=&quot;user-content-psf-security-update&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMYpFn5QdHVYYnMvX0B6Le1jdOQW5qRhll4CdTw38yekAPcckilnNqA3I_vG_XPY0vhSjf5T1mc_Ji4sCSDWh6n-ZCcJykNakY73qQN8nIp9LxNX7yTB9RXoepqINxM46Qa1ccQq8_N0_BoHILyuNf-GJQFulgL1OMcvtDDsJnw77oCdmqkw/s3319/IMG_5111.PNG&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;241&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMYpFn5QdHVYYnMvX0B6Le1jdOQW5qRhll4CdTw38yekAPcckilnNqA3I_vG_XPY0vhSjf5T1mc_Ji4sCSDWh6n-ZCcJykNakY73qQN8nIp9LxNX7yTB9RXoepqINxM46Qa1ccQq8_N0_BoHILyuNf-GJQFulgL1OMcvtDDsJnw77oCdmqkw/s320/IMG_5111.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;&quot;Security isn't free!&quot;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&amp;nbsp;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Following Amanda Casari's amazing keynote, &lt;a href=&quot;https://www.linkedin.com/in/miketheman/&quot; target=&quot;_blank&quot;&gt;Mike Fiedler&lt;/a&gt; and &lt;a href=&quot;https://sethmlarson.dev&quot;&gt;Seth Larson&lt;/a&gt; took the stage to give a brief update of the past
year of security work at the Python Software Foundation (PSF).&lt;/p&gt;
&lt;p&gt;Overall 2026 was the year of &lt;i&gt;more&lt;/i&gt;, both good and &lt;i&gt;not-so-good&lt;/i&gt;.
 More packages than ever
and being published to the &lt;a href=&quot;https://pypi.org/&quot; target=&quot;_blank&quot;&gt;Python Package Index&lt;/a&gt;&amp;nbsp;(PyPI), but also more malware
and specifically watering-hole attacks targeting PyPI users. The 
double-edged sword of being a popular and widely-used programming 
language also makes Python and its users a more interesting target for 
attackers.&lt;/p&gt;&lt;p&gt;The slides for this presentation are available for&amp;nbsp;&lt;a href=&quot;https://speakerdeck.com/sethmlarson/psf-security-engineer-update-pycon-us-2026&quot;&gt;download via speakerdeck&lt;/a&gt;.&lt;/p&gt;&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h2 class=&quot;heading-element&quot;&gt;OSS Maintainer Security Open Space&lt;/h2&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#oss-maintainers-security-open-space&quot; id=&quot;user-content-oss-maintainers-security-open-space&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJR3NjtBM9DOuizjoophmFacyowZrjH7c_D3ryIeW-RJbMvftW9qdGVx3M8h9WS_9tzBwChobXqJ0OtDLpUQ4OPD3nVRA64q39c3udgb5yf-1Pm4_MTXDGlaIdyi7nDKRooKl1wpFQKtzEimlV4kiRtFof6L8txx3w9_QZ83vbLbUrn5-R0Q/s745/IMG_4997.PNG&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;201&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJR3NjtBM9DOuizjoophmFacyowZrjH7c_D3ryIeW-RJbMvftW9qdGVx3M8h9WS_9tzBwChobXqJ0OtDLpUQ4OPD3nVRA64q39c3udgb5yf-1Pm4_MTXDGlaIdyi7nDKRooKl1wpFQKtzEimlV4kiRtFof6L8txx3w9_QZ83vbLbUrn5-R0Q/s320/IMG_4997.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;For the fourth year in a row Seth Larson hosted a security-themed
&lt;a href=&quot;https://us.pycon.org/2026/schedule/open-spaces/#OpenSpace-43&quot; rel=&quot;nofollow&quot;&gt;Open Space&lt;/a&gt;
at PyCon US. This year the open space was titled &quot;Security for Open Source project maintainers&quot; with
the goal of &quot;gather with fellow open source project maintainers to discuss
current challenges with open source security&quot;.&lt;/p&gt;
&lt;p&gt;A handful of Open Source maintainers were present to discuss security issues.
The format was open-ended discussion with a few prompts to start the
discussion off including vulnerability handling and CI/CD security.&lt;/p&gt;
&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h3 class=&quot;heading-element&quot;&gt;CI/CD Security&lt;/h3&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#cicd-security&quot; id=&quot;user-content-cicd-security&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Following the many watering-hole attacks on established Open Source projects involving CI/CD pipelines, hardening project CI/CD pipeline definitions was the first discussion topic. The overwhelming recommendation was to use &lt;a href=&quot;http://docs.zizmor.sh/&quot; rel=&quot;nofollow&quot;&gt;Zizmor&lt;/a&gt;
with its &lt;code&gt;--fix&lt;/code&gt; mode and a &lt;code&gt;GH_TOKEN&lt;/code&gt;. Other tools came up such as gha-update,
pinact, Dependabot, Renovate, and using lock files like &lt;code&gt;pip-compile&lt;/code&gt; to lock
dependencies in your CI/CD workflows. Dependency Cooldowns were also a popular concept for dependencies involved in builds and publishing.&lt;/p&gt;&lt;p&gt;The most recent resource published for all-in-one repository security
was a blog post by &lt;a href=&quot;https://astral.sh/blog/open-source-security-at-astral&quot; rel=&quot;nofollow&quot;&gt;William Woodruff on open source security at Astral&lt;/a&gt;
that details CI/CD security and how to configure repositories.&lt;/p&gt;
&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h3 class=&quot;heading-element&quot;&gt;Vulnerability Reporting&lt;/h3&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#vulnerabilities&quot; id=&quot;user-content-vulnerabilities&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;The bulk of the discussion was about vulnerabilities and challenges
around handling the volume of reports from reporters using LLMs.
The prevailing theme is that the volume of reports has increased substantially,
with &lt;i&gt;anec-data&lt;/i&gt; being that vulnerability handling &quot;previously was ~20% of
time spent on a project&quot; and is now &quot;almost all&quot; the time spent. Many reports
are duplicates, verbose, extremely low quality due to the use of LLMs
but the number of valid or almost-security issues has increased, too.&lt;/p&gt;
&lt;p&gt;This &quot;almost all&quot; number is particularly frightening, many Open Source contributors didn't get into this line of
volunteering because they wanted to work on security-related tasks.&lt;/p&gt;
&lt;p&gt;There was some side discussion about how to judge whether handling
a vulnerability in private was still a useful thing to do if
the vulnerability is trivially discoverable using a publicly available
LLM. The conversation referenced the Linux kernel's &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=36d49bba19f2c19c933d13b25dcf4eb607a030b3&quot;&gt;discussion of the same topic&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h3 class=&quot;heading-element&quot;&gt;Security Policies &amp;amp; Threat Models&lt;/h3&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#security-policies--threat-models&quot; id=&quot;user-content-security-policies--threat-models&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Talking about ways to mitigate the negative effects of
LLMs and agents on security work lead to a discussion of security policies and threat models. Few projects, especially
smaller ones, have tried this approach of documenting their
threat model to see if this has a meaningful impact on
the quality or quantity of reports received.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://devguide.python.org/security/policy/&quot;&gt;Python&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;https://docs.djangoproject.com/en/6.0/topics/security/&quot; rel=&quot;nofollow&quot;&gt;Django&lt;/a&gt;, &lt;a href=&quot;https://nodejs.org/learn/getting-started/security-best-practices&quot; rel=&quot;nofollow&quot;&gt;Node&lt;/a&gt;, and&amp;nbsp;&lt;a href=&quot;https://curl.se/dev/vuln-disclosure.html&quot; rel=&quot;nofollow&quot;&gt;curl&lt;/a&gt; were given
as good examples of threat models to copy and learn from for your
own projects.&lt;/p&gt;
&lt;p&gt;There was an issue of discoverability, some documentation is
in &lt;code&gt;CONTRIBUTING.md&lt;/code&gt;, or on a website, but not checked into
source control for the actual project, or used an organization-wide
&lt;code&gt;.github/SECURITY.md&lt;/code&gt;. Some projects didn't use an &lt;code&gt;AGENTS.md&lt;/code&gt; (and
didn't want to, for fear of inviting even more LLM-driven contributions), and it was difficult to tell whether any particular documentation was
having an effect. There's also the difficulty of models changing or
becoming more capable over time. More testing is necessary here!&lt;/p&gt;
&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h3 class=&quot;heading-element&quot;&gt;Contributor Quality Signals&lt;/h3&gt;&lt;a class=&quot;anchor&quot; href=&quot;https://gist.github.com/#contributor-quality-and-trust-scoring&quot; id=&quot;user-content-contributor-quality-and-trust-scoring&quot;&gt;&lt;span class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;A separate meta-conversation through the previous topics was
about having a way to signal that a particular contributor or security researcher
had a high &quot;contributor quality&quot;. The value of such a signal would tell
maintainers where to focus their limited time, such as reports from someone more likely to engage with
the process and follow instructions. &quot;Talking with an LLM, indirectly&quot; was mentioned multiple
times as a negative but unfortunately common experience of maintainers interacting with
first-time contributors.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ehmatthes/gh-profiler&quot;&gt;gh-profiler&lt;/a&gt; from Eric Matthes was referenced
during the discussion, and a few maintainers tested this on their own profiles
and profiles of low-quality contributions they'd received recently.
There was an interest in finding metrics or signals that are tougher to automate
or fake. The group identified that as soon as such a signal was widely used that agents would simply &quot;route around&quot; the barrier.&lt;/p&gt;&lt;div class=&quot;markdown-heading&quot;&gt;&lt;h2 class=&quot;heading-element&quot;&gt;Alpha-Omega × Python Software Foundation&amp;nbsp;&lt;/h2&gt;&lt;/div&gt;&lt;p&gt;Thanks to&amp;nbsp;&lt;a href=&quot;https://alpha-omega.dev&quot;&gt;Alpha-Omega&lt;/a&gt;&amp;nbsp;for sponsoring security at the PSF. Their support funds two roles: the Security Developer-in-Residence, held by Seth Larson, and the PyPI Safety &amp;amp; Security Engineer, held by Mike Fiedler. Seth and Mike delivered a joint update on their work at PyCon US 2026.&lt;/p&gt;&lt;p&gt;The over-arching theme of the update was the 
impact of higher volumes of reports, vulnerabilities, malware, and 
supply-chain attacks are having on the Python ecosystem along with work
 done to mitigate some of the hockey-stick graphs we're seeing.&lt;/p&gt;&lt;p&gt;Seth
 detailed the Python Security Response Team (PSRT) governance and 
process changes detailed in PEP 811. These changes aim to improve the 
capacity of the PSRT ahead of an increasing workload triaging and 
remediating security vulnerabilities reported to Python and pip.&lt;/p&gt;&lt;p&gt;Mike
 detailed work for mitigating malware and supply-chain attacks to PyPI, especially novel attacks such as the Shai-Hulud 
worm that targets and exploits insecure CI/CD pipelines and developer 
API tokens to propagate malware.&amp;nbsp;&lt;/p&gt;&lt;p&gt;If you are interested the full set of slides is available for&amp;nbsp;&lt;a href=&quot;https://speakerdeck.com/sethmlarson/alpha-omega-x-python-software-foundation-pycon-us-2026-sponsor-presentation&quot;&gt;download via speakerdeck&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Wed, 17 Jun 2026 09:55:10 +0000</pubDate>
</item>
<item>
	<title>Bob Belderbos: Building an AI Agent in 6 Weeks (and Finally Understanding How They Work)</title>
	<guid>https://belderbos.dev/blog/jeff-haemer-agentic-ai-cohort/</guid>
	<link>https://belderbos.dev/blog/jeff-haemer-agentic-ai-cohort/</link>
	<description>&lt;p&gt;Jeff Haemer has written software since he was teaching it at the University of Colorado in the early 1980s. But he felt he needed to brush up his Python, and above all get a grounding in AI.&lt;/p&gt;
&lt;p&gt;In his words AI was &quot;a big undifferentiated cloud of things I didn't know.&quot; Time to change that.&lt;/p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;/span&gt;
&lt;p&gt;Six weeks into our &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://pythonagenticai.com&quot;&gt;Python Agentic AI&lt;/a&gt; cohort, he ended up with an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/Sudavit/expenses-ai-agent&quot;&gt;agentic application&lt;/a&gt; with a few thousand lines of code, almost 250 unit tests, 100% coverage, and three working interfaces: a web UI, a command line, and a Telegram bot that talks to his phone.&lt;/p&gt;
&lt;p&gt;He even went as far as running mutation testing. More than that, through the program he developed a &lt;em&gt;mental model&lt;/em&gt; of how agents actually work under the covers.&lt;/p&gt;
&lt;h2 id=&quot;the-gap&quot;&gt;The gap&lt;/h2&gt;
&lt;p&gt;Jeff came in with a long career behind him and a clear-eyed view of what he was missing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;It's a giant world and changing every day, and I didn't even know in many ways where to start. When you told me you were thinking about doing an AI cohort, I said, please do that and sign me up, and I will happily jump in feet first.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He set expectations low on purpose. &quot;I expected myself to crash and burn because I have a very spotty background.&quot; He'd taught plenty of courses; he knew how the first run of anything goes. He signed on as the cohort's beta tester and decided to stay enthusiastic through whatever broke.&lt;/p&gt;
&lt;p&gt;Watch the full interview with Jeff:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZMe0d9M7ARs&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;core-logic-first-interfaces-on-top&quot;&gt;Core logic first, interfaces on top&lt;/h2&gt;
&lt;p&gt;An agent is a program that takes a request, reasons about it with an AI model, and acts. The cohort builds the reasoning core first, then wraps interfaces around it. That structure got tested the hard way in the Telegram week, when connecting the agent to a chat app hit a wall.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;I got to the end of that week and I wasn't even close, and I said, okay, I failed you. And you said, go on to the next week, because we designed the software so those units are independent of one another. We'll rewrite it.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He moved on. The Telegram unit was independent, so an unfinished interface didn't block the rest of the build. We later rebuilt that week's material from almost 100 pages down to 41, starting from a simpler working version. When Jeff came back to it, it worked.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;It was beautiful. When we hit a speed bump, that worked. It proved itself.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There's a meta lesson here, and a reminder of what well-designed software looks like: build the thing that does the work first, keep the edges replaceable. This saved the beta cohort from going under.&lt;/p&gt;
&lt;h2 id=&quot;mocking-the-thing-he-kept-putting-off&quot;&gt;Mocking, the thing he kept putting off&lt;/h2&gt;
&lt;p&gt;The concept that gave Jeff the most trouble was mocking, the practice of replacing a real outside service (an API, a database) with a stand-in so a test can run fast and offline.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The biggest pain for me was finally understanding what mocking involves. I even asked a friend of mine, a test automation Python guy, and he said, I never really understood that either.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He avoided it until week four or five, when Juanjo made it non-negotiable:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;You got me to the point where I could actually separate my unit tests, which were independent of outside services, from my integration tests. I learned stuff about pytest, I learned stuff about mocking, and I learned stuff about my own code. I just ended up thinking about things in a different way.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jeff's rigor with the test suite paid dividends. By the end they were catching real issues, including a function that slipped coverage when he deployed to a Debian box, which he set out to track down on his own.&lt;/p&gt;
&lt;h2 id=&quot;ai-as-teaching-assistant-not-autopilot&quot;&gt;AI as teaching assistant, not autopilot&lt;/h2&gt;
&lt;p&gt;Jeff wrote the code by hand. He used AI deliberately, as a tutor for the spots where his Python ran out, not as a generator to fill the file for him.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;I understand conceptually what to do here, but I don't know enough Python to struggle through the docs and work through all the bugs in that short amount of time. So, show me how to do this. AI turns into a great teaching assistant.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unit tests gave each week a &lt;em&gt;definition of done&lt;/em&gt;. The result is an artifact he can reason about, not a diff he has to trust on faith.&lt;/p&gt;
&lt;h2 id=&quot;understanding-by-building&quot;&gt;Understanding by building&lt;/h2&gt;
&lt;p&gt;The win Jeff cared about most wasn't the repo. It was the &lt;em&gt;mental model&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;It's different having done it than even reading about it. If somebody had written an explanation, a week later I'd have a vague idea, a month later I'd say I read an article about it but don't remember anything, and two months later I'd say I've never heard of that. This, I think I understand.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He tested it against a toy agent he found in the wild, a hallucinating Wikipedia clone, and could trace exactly what it did: validate the input, structure it, hand it to the model, get structured output back, cache it in a database.&lt;/p&gt;
&lt;p&gt;From &quot;big undifferentiated cloud of things I didn't know&quot; to a firm grounding in how AI agents work. Jeff ended up with a great artifact on GitHub, but the real win has been this deeper understanding that he will take to his next AI project.&lt;/p&gt;
&lt;p&gt;We're excited to see what Jeff will build next with this new skill set.&lt;/p&gt;</description>
	<pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>PyCoder’s Weekly: Issue #739: JIT Delayed, Sandboxes, OpenRouter, and More (2026-06-16)</title>
	<guid>https://pycoders.com/issues/739</guid>
	<link>https://pycoders.com/issues/739</link>
	<description>&lt;p&gt; &lt;span&gt;#739 – JUNE 16, 2026&lt;/span&gt;&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/issues/739/feed&quot;&gt;View in Browser »&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://pycoders.com&quot;&gt;&lt;img alt=&quot;The PyCoder&amp;rsquo;s Weekly Logo&quot; src=&quot;https://cdn.pycoders.com/37bdf31dc645f968ffb90196e5d38ff5&quot; /&gt;&lt;/a&gt;&lt;/p&gt; &lt;hr /&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16599/feed&quot; target=&quot;_blank&quot;&gt;Steering Council Announcement Regarding the JIT&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; The Python Steering Council has announced that the work on the JIT needs to be paused until a new PEP gets written. There are many unresolved questions about the approach and integration with other tools and the work on the JIT has reached a stage where these questions need to be answered. &lt;a href=&quot;https://pycoders.com/link/16595/feed&quot; target=&quot;_blank&quot;&gt;Additional discussion&lt;/a&gt;&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16599/feed&quot; target=&quot;_blank&quot;&gt;PYTHON.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16613/feed&quot; target=&quot;_blank&quot;&gt;Python in a Sandbox With MicroPython and WASM&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Simon&amp;rsquo;s been in search of the perfect code sandbox. This article is about his latest attempt and covers why he wants a sandbox and what tech he&amp;rsquo;s used to achieve it.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16613/feed&quot; target=&quot;_blank&quot;&gt;SIMON WILLISON&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16626/feed&quot; target=&quot;_blank&quot;&gt;Wallaby for Python runs Tests as you Type and Streams Results Next to Code, Plus AI Context&lt;/a&gt;&lt;/h3&gt; &lt;a href=&quot;https://pycoders.com/link/16626/feed&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://cdn.pycoders.com/d9737f4d049b7cace4391e2cb122bba5&quot; alt=&quot;alt&quot; /&gt;&lt;/a&gt; &lt;p&gt; Wallaby brings pytest / unittest results, runtime values, coverage, errors, and time-travel debugging into VS Code, so you can fix Python faster and give Copilot, Cursor, or Claude the execution context they need to stop guessing. &lt;a href=&quot;https://pycoders.com/link/16626/feed&quot; target=&quot;_blank&quot;&gt;Try it free, now in beta →&lt;/a&gt;&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16626/feed&quot; target=&quot;_blank&quot;&gt;WALLABY&lt;/a&gt;&lt;/span&gt; &lt;span&gt;sponsor&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16600/feed&quot; target=&quot;_blank&quot;&gt;Accessing Multiple AI Models With the OpenRouter API&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Access models from popular AI providers in Python through OpenRouter&amp;rsquo;s unified API with smart routing, fallbacks, and cost controls.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16600/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;span&gt;course&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16610/feed&quot; target=&quot;_blank&quot;&gt;Quiz: Accessing Multiple AI Models With the OpenRouter API&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16610/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16612/feed&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;scikit-learn&lt;/code&gt; 1.9 Released&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16612/feed&quot; target=&quot;_blank&quot;&gt;SCIKIT-LEARN.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16601/feed&quot; target=&quot;_blank&quot;&gt;Python 3.14.6 and 3.13.14 Released&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16601/feed&quot; target=&quot;_blank&quot;&gt;PYTHON.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;h2&gt;Articles &amp;amp; Tutorials&lt;/h2&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16620/feed&quot; target=&quot;_blank&quot;&gt;Skip Jupyter&amp;rsquo;s Hidden State: Reactive Notebooks With Marimo&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Marimo is a reactive Python notebook designed to make data science workflows more reproducible. This article shows how it avoids hidden execution state, saves notebooks as plain .py files for cleaner Git diffs, isolates dependencies with uv, supports pytest cells, and exports notebooks into reusable formats including scripts, HTML, and WASM dashboards.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16620/feed&quot; target=&quot;_blank&quot;&gt;CODECUT.AI&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16617/feed&quot; target=&quot;_blank&quot;&gt;Khuyen Tran&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16593/feed&quot; target=&quot;_blank&quot;&gt;EuroPython 2026: Celebrating 25 Years&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; What&amp;rsquo;s happening at EuroPython 2026? The conference celebrates its 25th anniversary this year in Kraków, Poland. This week on the show, organizers Mia Bajić and Daria Linhart Grudzien join me to discuss this year&amp;rsquo;s conference.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16593/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;span&gt;podcast&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16596/feed&quot; target=&quot;_blank&quot;&gt;SQLPyHelper: Unified DataBase API&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; SQLPyHelper is a Python library that provides a unified API across SQLite, PostgreSQL, MySQL, SQL Server, and Oracle. It has async support for FastAPI, cross-database migration, connection pooling, and transactions.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16596/feed&quot; target=&quot;_blank&quot;&gt;DEV.TO&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16609/feed&quot; target=&quot;_blank&quot;&gt;Adebayo Olaonipekun&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16594/feed&quot; target=&quot;_blank&quot;&gt;Stroll Down Startup Lane&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; PyCon&amp;rsquo;s Startup Row is a stretch of booths where early-stage companies built on Python show off what they&amp;rsquo;re creating. In this episode, Talk Python interviews a host of folks from this year&amp;rsquo;s booths.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16594/feed&quot; target=&quot;_blank&quot;&gt;TALK PYTHON&lt;/a&gt;&lt;/span&gt; &lt;span&gt;podcast&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16614/feed&quot; target=&quot;_blank&quot;&gt;Pyodide 314.0 Release&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; This post announces the Pyodide 314.0 release and describes its features, including a focus on standardization and packaging. You can now build Pyodide wheels and post them to PyPI.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16614/feed&quot; target=&quot;_blank&quot;&gt;PYODIDE.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16621/feed&quot; target=&quot;_blank&quot;&gt;The Smallest Brain You Can Build&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; A perceptron explained from scratch in Python, with interactive demos. Learn weights, bias, the decision boundary, epochs, learning rate, and why you normalize data.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16621/feed&quot; target=&quot;_blank&quot;&gt;DEVARSH RANPARA&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16622/feed&quot; target=&quot;_blank&quot;&gt;Are You Expected to Run 5 Type-Checkers Now?&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Library maintainers may feel overwhelmed by the plurality of type checkers that exist. We offer some guidance on how to focus their efforts where they matter most.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16622/feed&quot; target=&quot;_blank&quot;&gt;MARCO GORELLI&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16611/feed&quot; target=&quot;_blank&quot;&gt;How to Tell if Your Python Mock Is Actually Working&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; A test that passes because the real API returned an error is not a passing test. Here&amp;rsquo;s how to verify your mock is intercepting, and fix it when it isn&amp;rsquo;t.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16611/feed&quot; target=&quot;_blank&quot;&gt;BOB BELDERBOS&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16616/feed&quot; target=&quot;_blank&quot;&gt;Cursor vs Windsurf: Which AI Code Editor Is Best for Python?&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Compare Cursor vs Windsurf for Python across code completion, multi-file editing, and debugging to choose the right editor for your workflow.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16616/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16602/feed&quot; target=&quot;_blank&quot;&gt;Tricky Python Quiz&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; A tricky Python quiz game about surprising edge cases, weird outputs, and traps with questions from the popular WTFPython GitHub repo.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16602/feed&quot; target=&quot;_blank&quot;&gt;ADARSHD.DEV&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16623/feed&quot; target=&quot;_blank&quot;&gt;Adarsh Divakaran&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16603/feed&quot; target=&quot;_blank&quot;&gt;Free Threading Internals: Deferred Reference Counting&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; This is a follow up to Victor&amp;rsquo;s article on reference counting covering more complex counting mechanisms including immortal objects.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16603/feed&quot; target=&quot;_blank&quot;&gt;VICTOR STINNER&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;h2&gt;Projects &amp;amp; Code&lt;/h2&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16618/feed&quot; target=&quot;_blank&quot;&gt;Relier: Zero-Job-Loss Reliability Layer for Celery&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16618/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/GETRELIER&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16598/feed&quot; target=&quot;_blank&quot;&gt;Kolade Fajimi&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16625/feed&quot; target=&quot;_blank&quot;&gt;uuid-utils: Rust-Based Replacement for Python&amp;rsquo;s UUID&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16625/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/AMINALAEE&lt;/a&gt; • Shared by Amin&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16615/feed&quot; target=&quot;_blank&quot;&gt;pytrendy: Trend Detection in Time Series Data&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16615/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/RUSSELLSB&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16624/feed&quot; target=&quot;_blank&quot;&gt;django-deploy-probes: Django Health &amp;amp; Startup Endpoints&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16624/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/EMFPDLZJ&lt;/a&gt; • Shared by minjeong bak&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16606/feed&quot; target=&quot;_blank&quot;&gt;NumCircBuf: High-Performance Numerical Circular Buffers&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16606/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/BASIMALI-AI&lt;/a&gt; • Shared by Syed Basim Ali&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;h2&gt;Events&lt;/h2&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16608/feed&quot; target=&quot;_blank&quot;&gt;Weekly Real Python Office Hours Q&amp;amp;A (Virtual)&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; June 17, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16608/feed&quot; target=&quot;_blank&quot;&gt;REALPYTHON.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16607/feed&quot; target=&quot;_blank&quot;&gt;How CPython Works on Android&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; June 18, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16607/feed&quot; target=&quot;_blank&quot;&gt;LUMA.COM&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16623/feed&quot; target=&quot;_blank&quot;&gt;Adarsh D&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16605/feed&quot; target=&quot;_blank&quot;&gt;PyData Bristol Meetup&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; June 18, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16605/feed&quot; target=&quot;_blank&quot;&gt;MEETUP.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16604/feed&quot; target=&quot;_blank&quot;&gt;PyLadies Dublin&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; June 18, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16604/feed&quot; target=&quot;_blank&quot;&gt;PYLADIES.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16619/feed&quot; target=&quot;_blank&quot;&gt;Python for (Almost) Everything&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; June 18 to June 19, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16619/feed&quot; target=&quot;_blank&quot;&gt;MEETUP.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16597/feed&quot; target=&quot;_blank&quot;&gt;PyCon Singapore 2026&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; June 19 to June 22, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16597/feed&quot; target=&quot;_blank&quot;&gt;PYCON.SG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;hr /&gt; &lt;p&gt;Happy Pythoning!&lt;br /&gt;This was PyCoder&amp;rsquo;s Weekly Issue #739.&lt;br /&gt;&lt;a href=&quot;https://pycoders.com/issues/739/feed&quot;&gt;View in Browser »&lt;/a&gt;&lt;/p&gt; &lt;img src=&quot;https://pycoders.com/issues/739/open/feed&quot; width=&quot;1&quot; height=&quot;1&quot; alt=&quot;alt&quot; /&gt; 
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Subscribe to 🐍 PyCoder&amp;rsquo;s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week &lt;a href=&quot;https://pycoders.com/?utm_source=pycoders&amp;utm_medium=feed&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 16 Jun 2026 19:30:00 +0000</pubDate>
</item>
<item>
	<title>Ari Lamstein: Upcoming O’Reilly Workshop: Building Data Apps with Streamlit and Copilot (July 2026)</title>
	<guid>https://arilamstein.com/blog/2026/06/16/upcoming-oreilly-workshop-building-data-apps-with-streamlit-and-copilot-2/</guid>
	<link>https://arilamstein.com/blog/2026/06/16/upcoming-oreilly-workshop-building-data-apps-with-streamlit-and-copilot-2/</link>
	<description>&lt;p&gt;On &lt;strong&gt;July 9&lt;/strong&gt; (9am–1pm Pacific), I&amp;#8217;ll be teaching a &lt;strong&gt;4‑hour live workshop&lt;/strong&gt; for O&amp;#8217;Reilly: &lt;strong&gt;Building Data Apps with Streamlit and Copilot.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the second time I&amp;#8217;ve run this workshop, and I&amp;#8217;ve made several improvements based on what I learned the first time.&lt;/p&gt;
&lt;p&gt;If you work in Python and want to turn your analyses into interactive, shareable tools, this workshop is designed for you. We&amp;#8217;ll start from a Jupyter notebook and build a complete Streamlit app that lets users explore a dataset through interactive controls, charts, and maps. Along the way, we&amp;#8217;ll use Copilot to speed up development and discover Streamlit features more efficiently.&lt;/p&gt;
&lt;h3&gt;What we&amp;#8217;ll cover&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Structuring a Streamlit app&lt;/li&gt;
&lt;li&gt;Working with user input (select boxes, filters, etc.)&lt;/li&gt;
&lt;li&gt;Creating interactive graphics with Plotly&lt;/li&gt;
&lt;li&gt;Organizing the UI with columns and tabs&lt;/li&gt;
&lt;li&gt;Deploying your app to Streamlit Cloud&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The workshop is hands‑on: you&amp;#8217;ll build the app step‑by‑step, and by the end you&amp;#8217;ll have a working project you can adapt to your own data.&lt;/p&gt;
&lt;h3&gt;What You&amp;#8217;ll Build&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s a screenshot from the app we&amp;#8217;ll build together:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arilamstein.com/wp-content/uploads/2026/03/workshop-app-screenshot.png&quot;&gt;&lt;img /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The app lets users choose a state and demographic statistic, explore how it changes over time, and view the data as a chart, map, or table.&lt;/p&gt;
&lt;p&gt;And while the example uses demographic data, the skills you&amp;#8217;ll learn—structuring an app, building interactive controls, and creating dynamic visualizations—apply to any Streamlit project you want to build.&lt;/p&gt;
&lt;h3&gt;Who is this for?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Data scientists and analysts who want to make their work more interactive&lt;/li&gt;
&lt;li&gt;Python users who want to build dashboards without learning web development&lt;/li&gt;
&lt;li&gt;Anyone curious about Streamlit or Copilot&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How to Register&lt;/h3&gt;
&lt;p&gt;The workshop is hosted on O&amp;#8217;Reilly, which is a membership platform. If you&amp;#8217;re not already a member, I have a &lt;strong&gt;30-day free trial&lt;/strong&gt; you can use. To register for the workshop with the free trial:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start your free trial at &lt;strong&gt;&lt;a href=&quot;https://learning.oreilly.com/get-learning/?code=ARILAM26&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this link&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Then &lt;strong&gt;&lt;a href=&quot;https://www.oreilly.com/live-events/building-data-apps-with-streamlit-and-copilot/0642572306243/0642572306236/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;register for the workshop&lt;/a&gt;&lt;/strong&gt; itself&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Also worth knowing: &lt;strong&gt;the workshop is recorded&lt;/strong&gt;. So if July 9 doesn&amp;#8217;t work for you, it&amp;#8217;s still worth registering — you&amp;#8217;ll have access to the recording.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d love to see you there.&lt;/p&gt;</description>
	<pubDate>Tue, 16 Jun 2026 18:38:12 +0000</pubDate>
</item>
<item>
	<title>Mariatta: Waitlisted for the Core Devs Sprint: When the Bad News was Also the Good News</title>
	<guid>https://mariatta.ca/posts/waitlisted-core-devs-sprint/</guid>
	<link>https://mariatta.ca/posts/waitlisted-core-devs-sprint/</link>
	<description>&lt;p&gt;Last week, I learned that I was one of 17 people
&lt;a href=&quot;https://discuss.python.org/t/2026-python-core-dev-sprint-at-openai/106928&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;waitlisted for the Python Core Devs Sprint at OpenAI&lt;/a&gt;
this year.&lt;/p&gt;
&lt;p&gt;A waitlist that long realistically means I probably won&amp;rsquo;t get in. I was sad, of course. The sprint alternates between
Europe and the US. Traveling to Europe is &amp;hellip; hard and complicated. I couldn&amp;rsquo;t go to last year&amp;rsquo;s in Europe, because of
the location and work conflict. I was really hoping to go to this year&amp;rsquo;s US sprint. Next year it will be back in Europe,
out of reach again. That&amp;rsquo;s potentially not sprinting for three years in a row.&lt;/p&gt;</description>
	<pubDate>Tue, 16 Jun 2026 16:00:00 +0000</pubDate>
</item>
<item>
	<title>Python Bytes: #484 All our tools</title>
	<guid>https://pythonbytes.fm/episodes/show/484/all-our-tools</guid>
	<link>https://pythonbytes.fm/episodes/show/484/all-our-tools</link>
	<description>&amp;lt;strong&amp;gt;Topics covered in this episode:&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;

&amp;lt;ul&amp;gt;
	&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;a href=&quot;https://pi.dev/?featured_on=pythonbytes&quot;&amp;gt;pi&amp;lt;/a&amp;gt; + &amp;lt;a href=&quot;https://github.com/obra/superpowers/tree/main?featured_on=pythonbytes&quot;&amp;gt;superpowers&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Terminal: &amp;lt;a href=&quot;http://Warp.dev?featured_on=pythonbytes&quot;&amp;gt;Warp.dev&amp;lt;/a&amp;gt; + &amp;lt;a href=&quot;https://ohmyz.sh/?featured_on=pythonbytes&quot;&amp;gt;OhMyZSH&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;{&amp;lt;a href=&quot;https://blink.sh/?featured_on=pythonbytes&quot;&amp;gt;Blink&amp;lt;/a&amp;gt;,&amp;lt;a href=&quot;https://sw.kovidgoyal.net/kitty/?featured_on=pythonbytes&quot;&amp;gt;kitty&amp;lt;/a&amp;gt;} + &amp;lt;a href=&quot;https://mosh.org/?featured_on=pythonbytes&quot;&amp;gt;mosh&amp;lt;/a&amp;gt; + &amp;lt;a href=&quot;https://github.com/tmux/tmux?featured_on=pythonbytes&quot;&amp;gt;tmux&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;a href=&quot;https://www.anthropic.com/product/claude-code?featured_on=pythonbytes&quot;&amp;gt;Claude code&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;a href=&quot;https://goodsnooze.gumroad.com/l/macwhisper?featured_on=pythonbytes&quot;&amp;gt;MacWhisper&amp;lt;/a&amp;gt; or &amp;lt;a href=&quot;https://handy.computer?featured_on=pythonbytes&quot;&amp;gt;Handy&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;a href=&quot;https://tailscale.com/?featured_on=pythonbytes&quot;&amp;gt;Tailscale&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Extras&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Joke&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;

&amp;lt;/ul&amp;gt;&amp;lt;a href='https://www.youtube.com/watch?v=wgKF3yvpxPU' style='font-weight: bold;'data-umami-event=&quot;Livestream-Past&quot; data-umami-event-episode=&quot;484&quot;&amp;gt;Watch on YouTube&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;About the show&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Sponsored by us! Support our work through:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Our &amp;lt;a href=&quot;https://training.talkpython.fm/?featured_on=pythonbytes&quot;&amp;gt;&amp;lt;strong&amp;gt;courses at Talk Python Training&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Six Feet Up is hosting a LinkedIn Live
&amp;lt;strong&amp;gt;Connect with the hosts&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Michael: &amp;lt;a href=&quot;https://fosstodon.org/@mkennedy&quot;&amp;gt;@mkennedy@fosstodon.org&amp;lt;/a&amp;gt; / &amp;lt;a href=&quot;https://bsky.app/profile/mkennedy.codes?featured_on=pythonbytes&quot;&amp;gt;@mkennedy.codes&amp;lt;/a&amp;gt; (bsky)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Calvin: &amp;lt;a href=&quot;https://sixfeetup.social/@calvin?featured_on=pythonbytes&quot;&amp;gt;@calvinhp@sixfeetup.social&amp;lt;/a&amp;gt; / &amp;lt;a href=&quot;https://bsky.app/profile/calvinhp.com?featured_on=pythonbytes&quot;&amp;gt;@calvinhp.com&amp;lt;/a&amp;gt; (bsky)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Show: &amp;lt;a href=&quot;https://fosstodon.org/@pythonbytes&quot;&amp;gt;@pythonbytes@fosstodon.org&amp;lt;/a&amp;gt; / &amp;lt;a href=&quot;https://bsky.app/profile/pythonbytes.fm&quot;&amp;gt;@pythonbytes.fm&amp;lt;/a&amp;gt; (bsky)
Join us on YouTube at &amp;lt;a href=&quot;https://pythonbytes.fm/stream/live&quot;&amp;gt;&amp;lt;strong&amp;gt;pythonbytes.fm/live&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt; to be part of the audience. Usually &amp;lt;strong&amp;gt;Tuesday&amp;lt;/strong&amp;gt; at 7am PT. Older video versions available there too.
Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to &amp;lt;a href=&quot;https://pythonbytes.fm/friends-of-the-show&quot;&amp;gt;our friends of the show list&amp;lt;/a&amp;gt;, we'll never share it.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Calvin #1: &amp;lt;a href=&quot;https://pi.dev/?featured_on=pythonbytes&quot;&amp;gt;pi&amp;lt;/a&amp;gt; + &amp;lt;a href=&quot;https://github.com/obra/superpowers/tree/main?featured_on=pythonbytes&quot;&amp;gt;superpowers&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;terminal-first, open-source coding agent&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Session management is a first-class citizen&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Extension model is what makes pi special — it's aggressively composable&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Superpowers brings a structured software development methodology as loadable skills&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Steps back and asks you what you're really trying to do&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;“hand you the keys to the car” mode vs guardrails might not be for everyone&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Michael #2: Terminal: &amp;lt;a href=&quot;http://Warp.dev?featured_on=pythonbytes&quot;&amp;gt;Warp.dev&amp;lt;/a&amp;gt; + &amp;lt;a href=&quot;https://ohmyz.sh/?featured_on=pythonbytes&quot;&amp;gt;OhMyZSH&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;If you’re using the base terminal with default settings, you have so much head-room for improvement.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;I’ve been using &amp;lt;a href=&quot;http://Warp.dev?featured_on=pythonbytes&quot;&amp;gt;Warp.dev&amp;lt;/a&amp;gt; since Elvis talked me into it. ;)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Remarkable terminal but the AI side of things is a bit junky, can be turned off&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;OhMyZSH gives better autocomplete
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;e.g. git branch [HTML_REMOVED] lists all branches in the local repo!&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&quot;http://Commandbookapp.com?featured_on=pythonbytes&quot;&amp;gt;Commandbookapp.com&amp;lt;/a&amp;gt; is excellent to keep the terminal focused on terminal things and more server commands and other automation in Command Book.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Calvin #3: {&amp;lt;a href=&quot;https://blink.sh/?featured_on=pythonbytes&quot;&amp;gt;Blink&amp;lt;/a&amp;gt;,&amp;lt;a href=&quot;https://sw.kovidgoyal.net/kitty/?featured_on=pythonbytes&quot;&amp;gt;kitty&amp;lt;/a&amp;gt;} + &amp;lt;a href=&quot;https://mosh.org/?featured_on=pythonbytes&quot;&amp;gt;mosh&amp;lt;/a&amp;gt; + &amp;lt;a href=&quot;https://github.com/tmux/tmux?featured_on=pythonbytes&quot;&amp;gt;tmux&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&quot;https://sw.kovidgoyal.net/kitty/?featured_on=pythonbytes&quot;&amp;gt;&amp;lt;strong&amp;gt;Kitty Terminal&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt; — GPU-accelerated terminal emulator for macOS, Linux, and Windows with support for graphics, ligatures, and a powerful tiling layout system built right in.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&quot;https://blink.sh/?featured_on=pythonbytes&quot;&amp;gt;&amp;lt;strong&amp;gt;Blink Shell&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt; — The go-to terminal for iPad/iPhone power users; full SSH and Mosh client with a gorgeous interface built specifically for mobile professional workflows.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&quot;https://mosh.org/?featured_on=pythonbytes&quot;&amp;gt;&amp;lt;strong&amp;gt;Mosh&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt; — Mobile Shell replaces SSH for remote connections, surviving network switches, sleep cycles, and flaky Wi-Fi with zero dropped sessions — essential for staying connected to long-running agentic jobs.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&quot;https://github.com/tmux/tmux?featured_on=pythonbytes&quot;&amp;gt;&amp;lt;strong&amp;gt;tmux&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt; — Terminal multiplexer that keeps sessions alive on your Linux server indefinitely; detach from a Mosh session on your Mac, reconnect from your iPad, and your agent is right where you left it.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;The combo&amp;lt;/strong&amp;gt; — Kitty or Blink + Mosh + tmux creates a &quot;persistent remote brain&quot; pattern: your beefy Linux homelab runs the compute-heavy agent sessions 24/7, and any device becomes a thin client to drop in and out at will.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Michael #4: &amp;lt;a href=&quot;https://www.anthropic.com/product/claude-code?featured_on=pythonbytes&quot;&amp;gt;Claude code&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;I prefer the IDE experience, the new PyCharm + Claude integration is really good. VS Code too. Why IDE? Because we should still be present with our code and managing context is much easier.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use the best/latest models on high thinking. “Speed” is not your friend, it’s just shortcuts.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Create skills and agents and use them.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Curate your own rules (e.g. Talk Python’s &amp;lt;a href=&quot;http://Claude.md?featured_on=pythonbytes&quot;&amp;gt;Claude.md&amp;lt;/a&amp;gt;)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Works well on non-coding things. Just create a folder, put a ton of files in there and it’s like NotebookLM + Chat + more.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Calvin #5: &amp;lt;a href=&quot;https://goodsnooze.gumroad.com/l/macwhisper?featured_on=pythonbytes&quot;&amp;gt;MacWhisper&amp;lt;/a&amp;gt; or &amp;lt;a href=&quot;https://handy.computer?featured_on=pythonbytes&quot;&amp;gt;Handy&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Transcribes your speech using your choice of Whisper or Parakeet models.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;All transcription is done on your device, &amp;lt;strong&amp;gt;no data leaves your machine.&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Automatic Speaker Recognition with local models.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Handy is more basic, but open source and runs on all platforms.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Michael #6: &amp;lt;a href=&quot;https://tailscale.com/?featured_on=pythonbytes&quot;&amp;gt;Tailscale&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;No need to open ports at all, Tailscale makes machines inside the same network accessible to each other&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Works great for laptops, desktops, etc. But also available for servers.
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Though I still use cloud firewalls for servers.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;How I use it&amp;lt;/strong&amp;gt;:
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;My dev database server&amp;lt;/strong&amp;gt;, preloaded with QA data, is always running on my home mac mini m4 pro. All my apps look for that server before looking locally and tailscale makes them always accessible to each other&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;My &amp;lt;strong&amp;gt;local LLMs expose OpenAI API compatible APIs&amp;lt;/strong&amp;gt;. Tailscale makes these accessible even while traveling or at a coffee shop.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use my &amp;lt;strong&amp;gt;mini as an exit node&amp;lt;/strong&amp;gt;. All traffic is routed outbound from my local fiber network. Great to restricted IPs like accessing my servers without caring about the local IP.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Screen share back to my home machines even while traveling.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Listen to the &amp;lt;a href=&quot;https://talkpython.fm/episodes/show/546/self-hosting-apps-for-python-people?featured_on=pythonbytes&quot;&amp;gt;Talk Python episode with Alex&amp;lt;/a&amp;gt; for a deeper conversation.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Extras&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Calvin:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&quot;https://www.telescopo.app?featured_on=pythonbytes&quot;&amp;gt;Telescopo&amp;lt;/a&amp;gt; great Mac Markdown viewer/editor.
Michael:&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;One more: &amp;lt;a href=&quot;https://typora.io/?featured_on=pythonbytes&quot;&amp;gt;Typora markdown&amp;lt;/a&amp;gt; editor.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Created &amp;lt;a href=&quot;https://mkennedy.codes/docs/?featured_on=pythonbytes&quot;&amp;gt;formal documentation for many of my open source packages&amp;lt;/a&amp;gt; using &amp;lt;a href=&quot;https://posit-dev.github.io/great-docs/?featured_on=pythonbytes&quot;&amp;gt;Great Docs&amp;lt;/a&amp;gt;.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Via Mark Little: &amp;lt;a href=&quot;https://www.anthropic.com/news/fable-mythos-access?featured_on=pythonbytes&quot;&amp;gt;Statement on the US government directive to suspend access to Fable 5 and Mythos 5&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Joke: &amp;lt;a href=&quot;https://x.com/pr0grammerhum0r/status/2063078450311598430?s=12&amp;amp;featured_on=pythonbytes&quot;&amp;gt;No second date&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;</description>
	<pubDate>Tue, 16 Jun 2026 08:00:00 +0000</pubDate>
</item>
<item>
	<title>HoloViz: HoloViz for LLMs</title>
	<guid>https://blog.holoviz.org/posts/holoviz_llm/</guid>
	<link>https://blog.holoviz.org/posts/holoviz_llm/</link>
	<pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Kay Hayen: Nuitka Release 4.1</title>
	<guid>https://nuitka.net/posts/nuitka-release-41.html</guid>
	<link>https://nuitka.net/posts/nuitka-release-41.html</link>
	<description>&lt;p&gt;This is to inform you about the new stable release of &lt;a class=&quot;reference external&quot; href=&quot;https://nuitka.net&quot;&gt;Nuitka&lt;/a&gt;. It is the extremely compatible Python compiler,
&lt;a class=&quot;reference external&quot; href=&quot;https://nuitka.net/doc/download.html&quot;&gt;“download now”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This release adds many new features and corrections with a focus on
async code compatibility, missing generics features, and Python 3.14
compatibility and Python compilation scalability yet again.&lt;/p&gt;

&lt;h2&gt;Bug Fixes&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Fix, decorators were breaking when disabling
deferred annotations. (Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, nested loops could have wrong traces lead to mis-optimization.
(Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Fix, run-time check of package configuration was
incorrect. (Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;__builtins__&lt;/span&gt;&lt;/code&gt; lacked necessary
compatibility in compiled functions. (Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distutils:&lt;/strong&gt; Fix, incorrect UTF-8 decoding was used for TOML input
file parsing. (Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, multiple hard value assignments could cause compile time
crashes. (Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, string concatenation was not properly annotating exception
exits. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--verbose-output&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--show-modules-output&lt;/span&gt;&lt;/code&gt;
did not work with forward slashes. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Fix, there were various compatibility issues
including dictionary watchers and inline values. (Fixed in 4.0.2
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Fix, stack pointer initialization to &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;localsplus&lt;/span&gt;&lt;/code&gt;
was incorrect to avoid garbage collection issues. (Fixed in 4.0.2
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Fix, generic type variable scoping in classes was
incorrect. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Fix, there were various issues with function
generics. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.8+:&lt;/strong&gt; Fix, names in named expressions were not mangled.
(Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Fix, module checksums were not robust against quoting
style of module-name entry in YAML configurations. (Fixed in 4.0.2
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Fix, doing imports in queried expressions caused
corruption. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Fix, support for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;uv_build&lt;/span&gt;&lt;/code&gt; in the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--project&lt;/span&gt;&lt;/code&gt; option was
broken. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility:&lt;/strong&gt; Fix, names assigned in assignment expressions were
not mangled. (Fixed in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Fix, there were still various issues with function
generics. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clang:&lt;/strong&gt; Fix, debug mode was disabled for clang generally, but only
ClangCL and macOS Clang didn’t want it. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zig:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--windows-console-mode=attach|disable&lt;/span&gt;&lt;/code&gt; was not
working when using Zig. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Fix, yet another way self dependencies can look like,
needed to have support added. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Fix, generic types in classes had bugs with
multiple type variables. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Fix, repeated builds were not producing binary identical
results. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Fix, compiling with newer Python versions did not fall
back to Zig when the developer prompt MSVC was unusable, and error
reporting could crash. (Fixed in 4.0.4 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zig:&lt;/strong&gt; Fix, the workaround for Windows console mode &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;attach&lt;/span&gt;&lt;/code&gt; or
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;disable&lt;/span&gt;&lt;/code&gt; was incorrectly applied on non-Windows platforms. (Fixed
in 4.0.4 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Fix, linking with Python Build Standalone failed
because &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;libHacl_Hash_SHA2&lt;/span&gt;&lt;/code&gt; was not filtered out unconditionally.
(Fixed in 4.0.4 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.6+:&lt;/strong&gt; Fix, exceptions like &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;CancelledError&lt;/span&gt;&lt;/code&gt; thrown into
an async generator awaiting an inner awaitable could be swallowed,
causing crashes. (Fixed in 4.0.4 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, not all ordered set modules accepted generators for update.
(Fixed in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Disabled warning about rebuilding the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pytokens&lt;/span&gt;&lt;/code&gt;
extension module. (Fixed in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Filtered &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;libHacl_Hash_SHA2&lt;/span&gt;&lt;/code&gt; from link libs
unconditionally. (Fixed in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Disabled unusable unicode consistency checks for
Python versions 3.4 to 3.6. (Fixed in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python3.12+&lt;/strong&gt; Avoided cloning call nodes on class level which
caused issues with generic functions in combination with decorators.
(Added in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Added support for generic type variables in &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;async&lt;/span&gt;
&lt;span class=&quot;pre&quot;&gt;def&lt;/span&gt;&lt;/code&gt; functions. (Added in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Fix, flushing outputs for prompts was not working in all
cases when progress bars were enabled. (Fixed in 4.0.6 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Fix, unused variable warnings were missing at C compile time
when using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;zig&lt;/span&gt;&lt;/code&gt; as a C compiler. (Fixed in 4.0.6 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Fix, forced stdout and stderr paths as a feature was
broken. (Fixed in 4.0.6 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, replacing a branch did not accurately track shared active
variables causing optimization crashes. (Fixed in 4.0.7 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Fix, failed to remove extended attributes because files
need to be made writable first. (Fixed in 4.0.7 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, dict &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pop&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;setdefault&lt;/span&gt;&lt;/code&gt; using with &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;:=&lt;/span&gt;&lt;/code&gt; rewrites
lacked exception-exit annotations for un-hashable keys. (Fixed in
4.0.8 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.13:&lt;/strong&gt; Fix, the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;__parameters__&lt;/span&gt;&lt;/code&gt; attribute of generic
classes was not working. (Fixed in 4.0.8 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.11+:&lt;/strong&gt; Fix, starred arguments were not working as type
variables. (Fixed in 4.0.8 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python2:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;FileNotFoundError&lt;/span&gt;&lt;/code&gt; compatibility fallback
handling was not working properly. (Fixed in 4.0.8 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility:&lt;/strong&gt; Fix, loop ownership check in value traces was
missing, causing issues with nested loops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Improved &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--windows-console-mode=attach&lt;/span&gt;&lt;/code&gt; to properly
handle console handles, enabling cases like &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;os.system&lt;/span&gt;&lt;/code&gt; to work
nicely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python2:&lt;/strong&gt; Fix, there was a compatibility issue where providing
default values to the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;mkdtemp&lt;/span&gt;&lt;/code&gt; function was failing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Fix, there were spurious issues with C23 embedding in
32-bit MinGW64 by switching to &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;coff_obj&lt;/span&gt;&lt;/code&gt; resource mode for it as
well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Fix, the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;post-import-code&lt;/span&gt;&lt;/code&gt; execution could fail
because the triggering sub-package was not yet available in
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;sys.modules&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Fix, listing package DLLs with &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--list-package-dlls&lt;/span&gt;&lt;/code&gt; was
broken due to recent plugin lifecycle changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--list-package-exe&lt;/span&gt;&lt;/code&gt; was not working properly on
non-Windows platforms failing to detect executable files correctly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Handled paths starting with &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;{PROGRAM_DIR}&lt;/span&gt;&lt;/code&gt; the same as a
relative path when parsing the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--onefile-tempdir-spec&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Followed multiprocessing &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;forkserver&lt;/span&gt;&lt;/code&gt; changes for
newer Python versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Fix, generic class type parameters handling was
incorrect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12:&lt;/strong&gt; Fix, deferred evaluation of type aliases was
failing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.12+:&lt;/strong&gt; Aligned &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;sum&lt;/span&gt;&lt;/code&gt; built-in float summation with
CPython’s compensated sum for better accuracy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.10+:&lt;/strong&gt; Fix, uncompiled coroutine &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;throw()&lt;/span&gt;&lt;/code&gt; return
handling was incorrect, restoring completed coroutine results via
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;StopIteration.value&lt;/span&gt;&lt;/code&gt; rather than exposing them as ordinary return
values to the outer await chain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.13+:&lt;/strong&gt; Fix, uncompiled coroutine &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;cancel()/await&lt;/span&gt;&lt;/code&gt;
suspension handling was incorrect, improved to ensure integration
compatibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Made finding &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;create-dmg&lt;/span&gt;&lt;/code&gt; more robustly by also checking
the Homebrew path for Intel and from &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PATH&lt;/span&gt;&lt;/code&gt; properly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility:&lt;/strong&gt; Fix, class frames were not exposing frame locals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Detected &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;static-libpython&lt;/span&gt;&lt;/code&gt; problems, which affected some
forms of Anaconda.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distutils:&lt;/strong&gt; Rejected &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--project&lt;/span&gt;&lt;/code&gt; mixed with &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--main&lt;/span&gt;&lt;/code&gt; arguments
as it is not useful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;zig&lt;/span&gt;&lt;/code&gt; from &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PATH&lt;/span&gt;&lt;/code&gt; or from &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;ziglang&lt;/span&gt;&lt;/code&gt; was not
being used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distutils:&lt;/strong&gt; Fix, the wrong &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;module-root&lt;/span&gt;&lt;/code&gt; config value was being
checked for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;uv&lt;/span&gt;&lt;/code&gt; build backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Fix, was attempting to change removed (rejected) DLLs,
which of course failed and errored out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Fix, tuple reuse was not fully compatible,
potentially causing crashes due to outdated hash caches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, fake modules were still being attempted to located when imported
by other code, which could conflict with existing modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.5+:&lt;/strong&gt; Fix, failed to send uncompiled coroutines the sent
in value in &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;from&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, older &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;gcc&lt;/span&gt;&lt;/code&gt; compilers lacking newer intrinsic methods had
compilation issues that needed to be addressed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Fix, multiphase module extension modules with
post-load code were not working properly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, Avoid using the non-inline copy of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pkg_resources&lt;/span&gt;&lt;/code&gt; with the
inline copy of Jinja2. These could mismatch and cause errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, loops could make releasing of previous values very unclear,
causing optimization errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;incbin&lt;/span&gt;&lt;/code&gt; resource mode was not working with old &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;gcc&lt;/span&gt;&lt;/code&gt; C++
fallback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.4 to 3.6:&lt;/strong&gt; Fix, bytecode demotion was not working
properly for these versions, also bytecode only files not working.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Added a check for the broken &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;patchelf&lt;/span&gt;&lt;/code&gt; versions 0.10
and 0.11 to prevent breaking Qt plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Android:&lt;/strong&gt; Allowed &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;patchelf&lt;/span&gt;&lt;/code&gt; version 0.18 on Android.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Fix, the header path for self uninstalled Python was not
detected correctly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Release:&lt;/strong&gt; Fix, inclusion of the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pkg_resources&lt;/span&gt;&lt;/code&gt; inline copy for
Python 2 to source distributions was missing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Detected the OBS versions of SUSE Linux better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Suse:&lt;/strong&gt; Allowed using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;patchelf&lt;/span&gt;&lt;/code&gt; 0.18.0 there too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.11:&lt;/strong&gt; Fix, package and module dicts were not aligned close
enough to avoid a CPython bug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, unbound compiled methods could crash when called without an
object passed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Fix, multiphase module extension modules with
postload. (Fixed in 4.0.8 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Onefile:&lt;/strong&gt; Fix, while waiting for the child, it may already be
terminated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Removed existing absolute rpaths for Homebrew and
MacPorts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Avoided warning in CPython headers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Followed allocator changes more closely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatibility:&lt;/strong&gt; Avoided using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pkg_resources&lt;/span&gt;&lt;/code&gt; for Jinja2
template location for loading.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No-GIL:&lt;/strong&gt; Applied some bug fixes to get basic things to work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Package Support&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Add support for newer &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;paddle&lt;/span&gt;&lt;/code&gt; version. (Added in
4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Add workaround for refcount checks of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pandas&lt;/span&gt;&lt;/code&gt;.
(Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Add support for newer &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;h5py&lt;/span&gt;&lt;/code&gt; version. (Added in
4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Add support for newer &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;scipy&lt;/span&gt;&lt;/code&gt; package. (Added in
4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Revert accidental &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;os.getenv&lt;/span&gt;&lt;/code&gt; over &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;os.environ.get&lt;/span&gt;&lt;/code&gt;
changes in anti-bloat configurations that stopped them from working.
Affected packages are &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;networkx&lt;/span&gt;&lt;/code&gt;, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;persistent&lt;/span&gt;&lt;/code&gt;, and
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;tensorflow&lt;/span&gt;&lt;/code&gt;. (Fixed in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Added missing DLLs for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;openvino&lt;/span&gt;&lt;/code&gt;. (Added in 4.0.7
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhanced the package configuration YAML schema by adding the
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;relative_to&lt;/span&gt;&lt;/code&gt; parameter for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;from_filenames&lt;/span&gt;&lt;/code&gt; DLL specification,
avoiding error-prone purely relative paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;flet_desktop&lt;/span&gt;&lt;/code&gt; app assets were missing, now
preserving the packaged runtime and sidecar DLLs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Added support for the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;tyro&lt;/span&gt;&lt;/code&gt; package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Added data files for the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;perfetto&lt;/span&gt;&lt;/code&gt; package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Added support for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;anyio&lt;/span&gt;&lt;/code&gt; process forking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Added support for the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;plotly.graph&lt;/span&gt;&lt;/code&gt; package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anaconda:&lt;/strong&gt; Fix, dependencies for the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;numpy&lt;/span&gt;&lt;/code&gt; conda package on
Windows were incorrect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Enhanced the auto-icon hack in PySide6 to use compatible
class names.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone:&lt;/strong&gt; Fix, Qt libraries were duplicated with &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PySide6&lt;/span&gt;&lt;/code&gt;
WebEngine framework support on macOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Fix, automatic detection of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;mypyc&lt;/span&gt;&lt;/code&gt; runtime
dependencies was including all top level modules of the containing
package by accident. (Fixed in 4.0.5 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anaconda:&lt;/strong&gt; Fix, &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;delvewheel&lt;/span&gt;&lt;/code&gt; plugin was not working with Python
3.8+. This enhances compatibility with installed PyPI packages that
use it for their DLLs. (Fixed in 4.0.6 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Fix, our protection workaround could confuse methods
used with &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PySide6&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;New Features&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Added the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--recommended-python-version&lt;/span&gt;&lt;/code&gt; option to display
recommended Python versions for supported, working, or commercial
usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Add message to inform users about &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;Nuitka[onefile]&lt;/span&gt;&lt;/code&gt; if
compression is not installed. (Added in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Add support for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;uv_build&lt;/span&gt;&lt;/code&gt; in the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--project&lt;/span&gt;&lt;/code&gt; option.
(Added in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Onefile:&lt;/strong&gt; Allow extra includes as well. (Added in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Add &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;nuitka-project-set&lt;/span&gt;&lt;/code&gt; feature to define project
variables, checking for collisions with reserved runtime variables.
(Added in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Added new option to select &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--reproducible&lt;/span&gt;&lt;/code&gt; builds or
not. (Added in 4.0.6 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.10+:&lt;/strong&gt; Added support for
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;importlib.metadata.package_distributions()&lt;/span&gt;&lt;/code&gt;. (Added in 4.0.8
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Added support for the multiprocessing &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;forkserver&lt;/span&gt;&lt;/code&gt;
context. (Added in 4.0.8 already, for 4.1 Python 3.6 and earlier, as
well as 3.14 support were added too.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reports:&lt;/strong&gt; Added structured resource usage (&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;rusage&lt;/span&gt;&lt;/code&gt;) performance
information to compilation reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reports:&lt;/strong&gt; Included individual module-level C compiler caching
(&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;ccache&lt;/span&gt;&lt;/code&gt;/&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;clcache&lt;/span&gt;&lt;/code&gt;) statistics in compilation reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added support for detecting and correctly resolving the Python prefix
for the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PyEnv&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;Homebrew&lt;/span&gt;&lt;/code&gt; Python flavor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Added support for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;rusage&lt;/span&gt;&lt;/code&gt; information for Scons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Added the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;__compiled__.extension_filename&lt;/span&gt;&lt;/code&gt; attribute to
give the real filename of the containing extension module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Added support for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--clang&lt;/span&gt;&lt;/code&gt; or ARM. (Added in 4.0.8
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt; Added support for resources names as not just integers,
important when we copy them from template files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MacPorts:&lt;/strong&gt; Added basic support for this Python flavor. More work
will be needed to get it to work fully though.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Optimization&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;Avoid including &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;importlib._bootstrap&lt;/span&gt;&lt;/code&gt; and
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;importlib._bootstrap_external&lt;/span&gt;&lt;/code&gt;. (Added in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Linux:&lt;/strong&gt; Cached the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;syscall&lt;/span&gt;&lt;/code&gt; used for time keeping during
compilation to avoid loading &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;libc&lt;/span&gt;&lt;/code&gt; for each trace. (Added in 4.0.8
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Output a warning for modules that remain unfinished after the
third optimization pass.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added an extra micro pass trigger when new variables are introduced
or variable usage changes severely, ensuring optimizations are fully
propagated, avoiding unnecessary extra full passes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provided scripts to compile Python statically with PGO tailored for
Nuitka on Linux, Windows, and macOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added support for running the Data Composer tool from a compiled
Nuitka binary without spawning an uncompiled Python process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhanced the usage of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;vectorcall&lt;/span&gt;&lt;/code&gt; for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PyCFunction&lt;/span&gt;&lt;/code&gt; objects by
directly checking for its presence instead of relying purely on
flags, allowing more frequent use of this faster execution path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cached frequently used declarations for top-level variables to speed
up C code generation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sped up trace collection merging by avoiding unnecessary set creation
and using a set instead of a list for escaped traces.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimized plugin hook execution by tracking overloaded methods and
added an option to show plugin usage statistics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved performance of module location by avoiding unnecessary
module name reconstruction and redundant filesystem checks for
pre-loaded packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved the caching of distribution name lookups to effectively
avoid repeated IO operations across all package types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; Cached callback plugin dispatch for
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;onFunctionBodyParsing&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;onClassBodyParsing&lt;/span&gt;&lt;/code&gt; to skip argument
computation when no plugin overrides them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.13:&lt;/strong&gt; Handled sub-packages of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pathlib&lt;/span&gt;&lt;/code&gt; as hard modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handled hard attributes through merge traces as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Made constant blobs more compact by avoiding repeated identifiers and
unnecessary fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhanced Python compilation scripts further. (Fixed in 4.0.8
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recognized late incomplete variables better. (Fixed in 4.0.8
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Made constant blobs more compact. (Fixed in 4.0.8 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimized calls with only constant keywords and variable posargs too.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Anti-Bloat&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;Fix, memory bloat occurred when C compiling &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;sqlalchemy&lt;/span&gt;&lt;/code&gt;. (Fixed in
4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pydoc&lt;/span&gt;&lt;/code&gt; in &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;PySimpleGUI&lt;/span&gt;&lt;/code&gt;. (Added in 4.0.2 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoided using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;doctest&lt;/span&gt;&lt;/code&gt; from &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;zodbpickle&lt;/span&gt;&lt;/code&gt;. (Added in 4.0.5
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoided inclusion of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;cython&lt;/span&gt;&lt;/code&gt; when using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pyav&lt;/span&gt;&lt;/code&gt;. (Added in 4.0.7
already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoided including &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;typing_extensions&lt;/span&gt;&lt;/code&gt; when using &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;numpy&lt;/span&gt;&lt;/code&gt;. (Added
in 4.0.7 already.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Organizational&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Relocated the warning about the available source code of
extension modules to be evaluated at a more appropriate time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debian:&lt;/strong&gt; Remove recommendation for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;libfuse2&lt;/span&gt;&lt;/code&gt; package as it is
no longer useful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debian:&lt;/strong&gt; Used &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;platformdirs&lt;/span&gt;&lt;/code&gt; instead of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;appdirs&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Removed Python 3.11+ restriction for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;clang-format&lt;/span&gt;&lt;/code&gt;
as it is available everywhere, even Python 2.7, and we still want
nicely formatted code when we read things. (Added in 4.0.6 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removed no longer useful inline copy of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;wax_off&lt;/span&gt;&lt;/code&gt;. We have our own
stubs generator project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Release:&lt;/strong&gt; Added missing package to the CI container for building
Nuitka Debian packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer:&lt;/strong&gt; Updated AI instructions for creating Minimal
Reproducible Examples (MRE) to skip unneeded C compilation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Added an internal function for checking if a string is
a valid Python identifier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI:&lt;/strong&gt; Added a task in Visual Studio Code to export the currently
selected Python interpreter path to a file, making it available as
“python” and “pip” matching the selected interpreter. This makes it
easier to use a specific version with no instructions needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI:&lt;/strong&gt; Updated the rules to instruct AI to only generate useful
comments that add context not present in the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Containers:&lt;/strong&gt; Added template rendering support for Jinja2 (&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;.j2&lt;/span&gt;&lt;/code&gt;)
container files in our internal Podman tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Projects:&lt;/strong&gt; Clarified the current status and rationale of Python
2.6 support in the developer manual.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Added experimental flag
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--experimental=ignore-extra-micro-pass&lt;/span&gt;&lt;/code&gt; to allow ignoring extra
micro pass detection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visual Code:&lt;/strong&gt; Added integration scripts for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;bash&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;zsh&lt;/span&gt;&lt;/code&gt;
autocompletion of Nuitka CLI options. These are now also integrated
into Visual Studio Code terminal profiles and the Debian package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RPM:&lt;/strong&gt; Included the Python compile script for Linux.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RPM:&lt;/strong&gt; Removed the requirement for &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;distutils&lt;/span&gt;&lt;/code&gt; in the spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Tests&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;Install only necessary build tools for test cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoided spurious failures in reference counting tests due to Python
internal caching differences. (Fixed in 4.0.3 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, the parsing of the compilation report for reflected tests was
incorrect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Ignored a syntax error message change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python 3.14:&lt;/strong&gt; Added test execution support options to the main
test runner to use this version as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, the runner binary path was mishandled for the third pass of
reflected compilations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removed the usage of obsolete plugins in reflected compilation tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Prevented boolean testing of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;namedtuples&lt;/span&gt;&lt;/code&gt; to avoid
unexpected bugs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;Test&lt;/span&gt;&lt;/code&gt; suffix to syntax test files and disabled “python”
mode and spell checking for them to resolve issues reported in IDEs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix, newline handling in diff outputs from the output comparison tool
was incorrect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Covered &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;post-import-code&lt;/span&gt;&lt;/code&gt; functionality with a new subpackage test
case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prevented the program test suite from running an unnecessary variant
to save execution time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Ignored differences from GUI framework error traces in
headless runs in output comparisons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reflected test for Nuitka, where it compiles itself and compares its
operation has been restored to functional state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Used the new method to clear internal caches if available for
reference counts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disabled running nested loops test with Python 2.6.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Containers:&lt;/strong&gt; Detected Python 2 defaulting containers in Podman
tooling.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Cleanups&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI:&lt;/strong&gt; Fix, there was a double space in the Windows Runtime DLLs
inclusion message. (Fixed in 4.0.1 already.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Onefile:&lt;/strong&gt; Separated files and defines for extra includes for
onefile boot and Python build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Provided nicer errors in case of “unset” variables being
used, so we can tell it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactored the process execution results to correctly utilize our
&lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;namedtuples&lt;/span&gt;&lt;/code&gt; variant, that makes it easier to understand what code
does with the results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Enabled automatic conversion of em-dashes and en-dashes
in code comments to the autoformat tool. AI won’t stop producing them
and they can cause &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;SyntaxError&lt;/span&gt;&lt;/code&gt; for older Python versions, nor is
unnecessarily using UTF-8 welcome.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensured that cloned outline nodes are assigned their correct names
immediately upon creation, that avoids inconsistencies during their
creation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Updated to the latest versions of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;black&lt;/span&gt;&lt;/code&gt; and adopted
a faster &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;isort&lt;/span&gt;&lt;/code&gt; execution by caching results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Modified the PyLint wrapper to exit gracefully instead
of raising an error when no matching files require checking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Avoided checking YAML package configuration files twice,
since autoformat already handles them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Ensured that YAML package configuration checks output
the original filename instead of the temporary one when a failure
occurs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Prevented pushing of tags from triggering git pre-push
quality checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Silenced the output of &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;optipng&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;jpegoptim&lt;/span&gt;&lt;/code&gt;
during image optimization auto-formatting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visual Code:&lt;/strong&gt; Added the generated Python alias path file to the
ignore list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Enabled auto-formatting for the Nuitka devcontainer
configuration file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Watch:&lt;/strong&gt; Avoided absolute paths in compilation to make reports more
comparable across machines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Changed &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;mdformat&lt;/span&gt;&lt;/code&gt; checks to run only once and
silently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Disabled format security errors in debug mode and moved
Python-related warning disables into common build setup code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality:&lt;/strong&gt; Updated to the latest &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;deepdiff&lt;/span&gt;&lt;/code&gt; version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scons:&lt;/strong&gt; Avoided MSVC telemetry since it can produce outputs that
break CI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Enhanced non-deployment handler for importing excluded
modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Split import module finding functionality into more pieces for
enhanced readability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Added more assertions for constants loading and
checking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;macOS:&lt;/strong&gt; Dropped the &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;universal&lt;/span&gt;&lt;/code&gt; target arch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Added more traces for deep hash verification.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This release builds on the scalability improvements established in 4.0,
with enhanced Python 3.14 support, expanded package compatibility, and
significant optimization work.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;docutils literal notranslate&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--project&lt;/span&gt;&lt;/code&gt; option seems usable now.&lt;/p&gt;
&lt;p&gt;Python 3.14 support remains experimental, but only barely made the cut,
and probably will get there in hotfixes. Some of the corrections came in
so late before the release, that it was just not possible to feel good
about declaring it fully supported just yet.&lt;/p&gt;</description>
	<pubDate>Mon, 15 Jun 2026 22:00:00 +0000</pubDate>
</item>
<item>
	<title>Eli Bendersky: Plugins case study: Pluggy</title>
	<guid>https://eli.thegreenplace.net/2026/plugins-case-study-pluggy/</guid>
	<link>https://eli.thegreenplace.net/2026/plugins-case-study-pluggy/</link>
	<description>&lt;p&gt;Recently I came upon &lt;a class=&quot;reference external&quot; href=&quot;https://pluggy.readthedocs.io/en/latest/&quot;&gt;Pluggy&lt;/a&gt;,
a Python library for developing plugin systems. It was originally developed
as part of the &lt;tt class=&quot;docutils literal&quot;&gt;pytest&lt;/tt&gt; project - known for its rich plugin ecosystem - and
later extracted into a standalone library. You're supposed to reach out for
Pluggy if you want to add a plugin system to your tool or library and want
to use something proven rather than rolling your own.&lt;/p&gt;
&lt;p&gt;In this post I will share some notes on how Pluggy works, and will
then review how it aligns with the
&lt;a class=&quot;reference external&quot; href=&quot;https://eli.thegreenplace.net/2012/08/07/fundamental-concepts-of-plugin-infrastructures&quot;&gt;fundamental concepts of plugin infrastructures&lt;/a&gt;.&lt;/p&gt;
&lt;img alt=&quot;Pluggy plug logo&quot; class=&quot;align-center&quot; src=&quot;https://eli.thegreenplace.net/images/2026/pluggy-plug.png&quot; /&gt;
&lt;div class=&quot;section&quot; id=&quot;using-pluggy&quot;&gt;
&lt;h2&gt;Using Pluggy&lt;/h2&gt;
&lt;p&gt;Pluggy is built around the concept of &lt;em&gt;hooks&lt;/em&gt;: functions that host
applications or tools (from here on, just &amp;quot;hosts&amp;quot;) expose and plugins implement.
A host exposes hooks by using
a decorator returned from &lt;tt class=&quot;docutils literal&quot;&gt;pluggy.HookspecMarker&lt;/tt&gt; and a plugin implements this
hook using a decorator returned from &lt;tt class=&quot;docutils literal&quot;&gt;pluggy.HookimplMarker&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Pluggy's &lt;a class=&quot;reference external&quot; href=&quot;https://pluggy.readthedocs.io/en/stable/&quot;&gt;documentation&lt;/a&gt; explains
this fairly well; in this post, I'll show how to implement the &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt; tool
with some plugins, introduced in &lt;a class=&quot;reference external&quot; href=&quot;https://eli.thegreenplace.net/2012/08/07/fundamental-concepts-of-plugin-infrastructures&quot;&gt;the original article in my plugin series&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a reminder, &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt; is a toy tool that takes markup notation similar to
reStructuredText, and converts it to to HTML. It supports plugins to handle
custom &amp;quot;roles&amp;quot; like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;some text :role:`customized text` and more text
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As well as plugins that do arbitrary processing on the entire text.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;defining-hooks&quot;&gt;
&lt;h3&gt;Defining hooks&lt;/h3&gt;
&lt;p&gt;&lt;a class=&quot;reference external&quot; href=&quot;https://github.com/eliben/code-for-blog/tree/main/2026/plugin-pluggy/htmlize/htmlize&quot;&gt;Out host&lt;/a&gt; defines two hooks:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pluggy&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;hookspec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pluggy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HookspecMarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;htmlize&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@hookspec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstresult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;htmlize_role_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;role_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Return a function accepting role contents.&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;    The function will be called with a single argument - the role contents, and&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    should return what the role gets replaced with.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@hookspec&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;htmlize_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Return a function accepting full document contents.&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;    The function will be called with a single argument - the document contents&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    (after paragraph splitting and role processing), and should return the&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    transformed contents.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A hook is created by calling &lt;tt class=&quot;docutils literal&quot;&gt;HookspecMarker&lt;/tt&gt; with the project's name. This
project name has to match between the host and its plugins. Pluggy is permissive
about what hooks accept as parameters and what they return; for maximal
flexibility and to stay true to the original &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt; example, our hooks
return functions.&lt;/p&gt;
&lt;p&gt;To accompany this &lt;tt class=&quot;docutils literal&quot;&gt;HookspecMarker&lt;/tt&gt;, the host also defines a &lt;tt class=&quot;docutils literal&quot;&gt;HookimplMarker&lt;/tt&gt; with
the same name:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hookimpl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pluggy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HookimplMarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;htmlize&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is used by plugins to attach to hooks when they're loaded.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;loading-plugins-in-the-host&quot;&gt;
&lt;h3&gt;Loading plugins in the host&lt;/h3&gt;
&lt;p&gt;The host's main function loads plugins at startup as follows:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pluggy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PluginManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;htmlize&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_hookspecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hookspecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_setuptools_entrypoints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;htmlize&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;tt class=&quot;docutils literal&quot;&gt;hookspecs&lt;/tt&gt; is our Python module containing the hooks shown above.
&lt;tt class=&quot;docutils literal&quot;&gt;load_setuptools_entrypoints&lt;/tt&gt; is Pluggy's helper for loading plugins that
were &lt;tt class=&quot;docutils literal&quot;&gt;pip&lt;/tt&gt;-installed into the same environment and registered as
setuptools &lt;a class=&quot;reference external&quot; href=&quot;https://setuptools.pypa.io/en/latest/userguide/entry_point.html&quot;&gt;entry points&lt;/a&gt;.
It's a way to signal - in one's &lt;tt class=&quot;docutils literal&quot;&gt;setup.py&lt;/tt&gt; or &lt;tt class=&quot;docutils literal&quot;&gt;pyproject.toml&lt;/tt&gt; file - some
metadata that projects can review at runtime. In our project, the plugins
register themselves with this section in the &lt;tt class=&quot;docutils literal&quot;&gt;pyproject.toml&lt;/tt&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;[project.entry-points.htmlize]
tt = &amp;quot;tt&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This says &amp;quot;for entry point &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt;, define a new entry named &lt;tt class=&quot;docutils literal&quot;&gt;tt&lt;/tt&gt;&amp;quot;.
Pluggy's &lt;tt class=&quot;docutils literal&quot;&gt;load_setuptools_entrypoints&lt;/tt&gt; then uses &lt;a class=&quot;reference external&quot; href=&quot;https://docs.python.org/3/library/importlib.metadata.html&quot;&gt;importlib.metadata&lt;/a&gt;
to access this information.&lt;/p&gt;
&lt;p&gt;Note that Pluggy doesn't require using this mechanism. Hosts can implement any
plugin discovery method they want, and add plugins directly to their
&lt;tt class=&quot;docutils literal&quot;&gt;PluginManager&lt;/tt&gt; with the &lt;tt class=&quot;docutils literal&quot;&gt;register&lt;/tt&gt; method. But this is the mechanism used
for &lt;tt class=&quot;docutils literal&quot;&gt;pytest&lt;/tt&gt; and many other projects; it makes it very easy to
automatically discover and register plugins that are installed with &lt;tt class=&quot;docutils literal&quot;&gt;pip&lt;/tt&gt; and
equivalent tools.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;invoking-plugins&quot;&gt;
&lt;h3&gt;Invoking plugins&lt;/h3&gt;
&lt;p&gt;Once &lt;tt class=&quot;docutils literal&quot;&gt;PluginManager&lt;/tt&gt; loads the plugins, invoking them is straightforward;
here's how &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt; invokes the contents hooks &lt;a class=&quot;footnote-reference&quot; href=&quot;https://eli.thegreenplace.net/feeds/python.atom.xml#footnote-1&quot; id=&quot;footnote-reference-1&quot;&gt;[1]&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Build full contents back again, and ask plugins to act on&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# contents.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plugin_manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;htmlize_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Generally, hook invocations return a &lt;em&gt;list&lt;/em&gt; of all the hooks attached to by
different plugins (a single host application can have multiple plugins installed
and attaching to the same hook). When the host invokes the hook as shown above,
the default order is LIFO, but plugins can affect this with
&lt;a class=&quot;reference external&quot; href=&quot;https://pluggy.readthedocs.io/en/stable/#call-time-order&quot;&gt;hook options&lt;/a&gt;
like &lt;tt class=&quot;docutils literal&quot;&gt;tryfirst&lt;/tt&gt; and &lt;tt class=&quot;docutils literal&quot;&gt;trylast&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;implementing-hooks-in-plugins&quot;&gt;
&lt;h3&gt;Implementing hooks in plugins&lt;/h3&gt;
&lt;p&gt;Here's our entire &lt;tt class=&quot;docutils literal&quot;&gt;narcissist&lt;/tt&gt; plugin that's attaching to the contents hook:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;htmlize&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@htmlize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hookimpl&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;htmlize_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;repl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&amp;lt;b&amp;gt;I (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;)&amp;lt;/b&amp;gt;'&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\bI\b'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hook&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some notes:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;It expects &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt; to be installed; as discussed previously, we rely on
Pluggy's default install-based approach where both the host and plugins are
installed into the same Python environment and can thus find each other.
However, Pluggy supports any custom discovery method.&lt;/li&gt;
&lt;li&gt;It uses the &lt;tt class=&quot;docutils literal&quot;&gt;hookimpl&lt;/tt&gt; exported value shown earlier.&lt;/li&gt;
&lt;li&gt;It returns a function that acts on contents; this is the &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt;-specific
contract (ABI, if you will) we've discussed before.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;fundamental-plugin-concepts-in-this-case-study&quot;&gt;
&lt;h2&gt;Fundamental plugin concepts in this case study&lt;/h2&gt;
&lt;p&gt;Let's see how this case study of Pluggy measures against the
&lt;a class=&quot;reference external&quot; href=&quot;https://eli.thegreenplace.net/2012/08/07/fundamental-concepts-of-plugin-infrastructures&quot;&gt;Fundamental plugin concepts&lt;/a&gt;
that were covered &lt;a class=&quot;reference external&quot; href=&quot;https://eli.thegreenplace.net/tag/plugins&quot;&gt;several times on this blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It's important to remember that Pluggy is not a specific host application with
a bespoke plugin system; rather, it's a reusable library for creating such
plugin systems. Therefore, this is more of a &lt;em&gt;meta&lt;/em&gt; case study.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;discovery&quot;&gt;
&lt;h3&gt;Discovery&lt;/h3&gt;
&lt;p&gt;Generally, Pluggy leaves discovery logic to the user's discretion. Its
&lt;tt class=&quot;docutils literal&quot;&gt;PluginManager&lt;/tt&gt; has a &lt;tt class=&quot;docutils literal&quot;&gt;register&lt;/tt&gt; method for adding plugins, and these can
be discovered in any way the application chooses.&lt;/p&gt;
&lt;p&gt;That said, Pluggy comes with one discovery mechanism built in - through the
entry points process of Python packaging, as shown above. This is hugely
convenient for a large number of applications, as long as both the application
and its plugins are installed via standard Python packaging tools (which is
a very reasonable assumption in the Python ecosystem).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;registration&quot;&gt;
&lt;h3&gt;Registration&lt;/h3&gt;
&lt;p&gt;In the entry point process, plugins register themselves by adding a
&lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;[project.entry-points.&amp;lt;HOST-ID&amp;gt;]&lt;/span&gt;&lt;/tt&gt; section in their &lt;tt class=&quot;docutils literal&quot;&gt;pyproject.toml&lt;/tt&gt;
file.&lt;/p&gt;
&lt;p&gt;Otherwise - as in the previous section - users are free to devise their own
registration schemes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;hooks&quot;&gt;
&lt;h3&gt;Hooks&lt;/h3&gt;
&lt;p&gt;This one is easy, since it's called &lt;em&gt;hooks&lt;/em&gt; in Pluggy parlance as well!
Pluggy's implementation of hooks is rather elegant, with function decorators
available for plugins to set. We've seen an example of this above with
&lt;tt class=&quot;docutils literal&quot;&gt;&amp;#64;htmlize.hookimpl&lt;/tt&gt; decorating &lt;tt class=&quot;docutils literal&quot;&gt;htmlize_contents&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;exposing-an-application-api-to-plugins&quot;&gt;
&lt;h3&gt;Exposing an application API to plugins&lt;/h3&gt;
&lt;p&gt;Since Pluggy is designed for Python hosts and Python plugins, this one is
fairly straightforward. The plugins typically assume the host project is
already installed in the Python environment and its modules can be imported.&lt;/p&gt;
&lt;p&gt;In our example, &lt;tt class=&quot;docutils literal&quot;&gt;hookimpl&lt;/tt&gt; is imported from &lt;tt class=&quot;docutils literal&quot;&gt;htmlize&lt;/tt&gt; by the plugin to
accomplish this. It also shows how host data is passed to the plugin - the
&lt;tt class=&quot;docutils literal&quot;&gt;post&lt;/tt&gt; and &lt;tt class=&quot;docutils literal&quot;&gt;db&lt;/tt&gt; parameters. These are APIs exposed by the host for the
plugins' use.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;conclusion-is-pluggy-worth-it&quot;&gt;
&lt;h2&gt;Conclusion - is Pluggy worth it?&lt;/h2&gt;
&lt;p&gt;In footnote 2 of my original &lt;a class=&quot;reference external&quot; href=&quot;https://eli.thegreenplace.net/2012/08/07/fundamental-concepts-of-plugin-infrastructures&quot;&gt;fundamental concepts of plugin infrastructures&lt;/a&gt;
post, I wrote &lt;a class=&quot;footnote-reference&quot; href=&quot;https://eli.thegreenplace.net/feeds/python.atom.xml#footnote-2&quot; id=&quot;footnote-reference-2&quot;&gt;[2]&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
This is probably why there are very few well-established plugin frameworks
in existence (even in low-level languages like C or C++). It's too easy (and
tempting) to roll your own.&lt;/blockquote&gt;
&lt;p&gt;I still believe my statement is true - plugin frameworks are very easy
to create, and the functionality they provide is relatively small compared to
their large surface area. In other words, this is a &lt;em&gt;shallow API&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That said, Pluggy does provide some nice functionality for the more advanced
uses of plugins:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Automatic entry point registration mechanism - if you need it&lt;/li&gt;
&lt;li&gt;Signature validation&lt;/li&gt;
&lt;li&gt;Consistent plugin result collection across multiple hook attachments in a
single plugin and across many plugins&lt;/li&gt;
&lt;li&gt;Plugin ordering with &lt;tt class=&quot;docutils literal&quot;&gt;firstresult&lt;/tt&gt;, &lt;tt class=&quot;docutils literal&quot;&gt;tryfirst&lt;/tt&gt;, &lt;tt class=&quot;docutils literal&quot;&gt;trylast&lt;/tt&gt;, etc.&lt;/li&gt;
&lt;li&gt;Hook &amp;quot;wrappers&amp;quot; for some special use cases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Are these worthwhile for your project? It really depends on the project,
and it's always worth keeping the &lt;a class=&quot;reference external&quot; href=&quot;https://eli.thegreenplace.net/2017/benefits-of-dependencies-in-software-projects-as-a-function-of-effort/&quot;&gt;tradeoff between dependencies and project
effort&lt;/a&gt;
in mind.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;code&quot;&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;The full code repository for this post &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/eliben/code-for-blog/tree/main/2026/plugin-pluggy&quot;&gt;is available here&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;docutils&quot; /&gt;
&lt;table class=&quot;docutils footnote&quot; frame=&quot;void&quot; id=&quot;footnote-1&quot; rules=&quot;none&quot;&gt;
&lt;colgroup&gt;&lt;col class=&quot;label&quot; /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign=&quot;top&quot;&gt;
&lt;tr&gt;&lt;td class=&quot;label&quot;&gt;&lt;a class=&quot;fn-backref&quot; href=&quot;https://eli.thegreenplace.net/feeds/python.atom.xml#footnote-reference-1&quot;&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Here &lt;tt class=&quot;docutils literal&quot;&gt;plugin_manager&lt;/tt&gt; is the value previously returned from
&lt;tt class=&quot;docutils literal&quot;&gt;pluggy.PluginManager&lt;/tt&gt;; in the previous code snippet it's saved into
&lt;tt class=&quot;docutils literal&quot;&gt;pm&lt;/tt&gt; - the different variable name is because a function call is made
and &lt;tt class=&quot;docutils literal&quot;&gt;plugin_manager&lt;/tt&gt; is the parameter name.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class=&quot;docutils footnote&quot; frame=&quot;void&quot; id=&quot;footnote-2&quot; rules=&quot;none&quot;&gt;
&lt;colgroup&gt;&lt;col class=&quot;label&quot; /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign=&quot;top&quot;&gt;
&lt;tr&gt;&lt;td class=&quot;label&quot;&gt;&lt;a class=&quot;fn-backref&quot; href=&quot;https://eli.thegreenplace.net/feeds/python.atom.xml#footnote-reference-2&quot;&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;To be fair, that post predates the creation of Pluggy!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 14 Jun 2026 10:20:58 +0000</pubDate>
</item>
<item>
	<title>Bob Belderbos: Why Rust does not need OOP</title>
	<guid>https://belderbos.dev/blog/why-rust-does-not-need-oop/</guid>
	<link>https://belderbos.dev/blog/why-rust-does-not-need-oop/</link>
	<description>&lt;p&gt;When I heard structs replace classes in Rust, I was a bit surprised. I thought, how can you do without classes? But as I started to learn Rust, I realized that structs, traits, ownership and composition help resist the temptation of OOP. In fact, Rust's approach to programming is more focused on data and behavior rather than objects.&lt;/p&gt;
&lt;p&gt;Let's look at 5 reasons why Rust does not need OOP.&lt;/p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;/span&gt;&lt;h2 id=&quot;1-composition&quot;&gt;1. Composition&lt;/h2&gt;
&lt;p&gt;One major drawback of OOP is deep inheritance trees.&lt;/p&gt;
&lt;p&gt;In classic OOP you would define class A, then class B inherits from A, then class C inherits from B, and so on. This can lead to a complex and fragile codebase where changes in one class can affect many others.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Animal&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Dog&lt;/span&gt;&lt;span class=&quot;z-storage&quot;&gt; extends&lt;/span&gt;&lt;span class=&quot;z-entity&quot;&gt; Animal&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ServiceDog&lt;/span&gt;&lt;span class=&quot;z-storage&quot;&gt; extends&lt;/span&gt;&lt;span class=&quot;z-entity&quot;&gt; Dog&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;a href=&quot;https://belderbos.dev/blog/what-rust-structs-taught-me-about-state-ownership/&quot;&gt;What Rust Structs Taught Me About State Ownership&lt;/a&gt; I showed this example:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Tokenizer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    chars&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;char&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    position&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Tokenizer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; advance&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;char&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ch&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;chars&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;position)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;copied&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;position &lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        ch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; peek&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;char&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;chars&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;position)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;copied&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; // char is Copy, returns a value not a reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We see a clear separation of data (the fields) and behavior (the methods). The Tokenizer struct holds the state, while the methods define how to interact with that state. This is a more flexible and modular approach than OOP's class-based design.&lt;/p&gt;
&lt;p&gt;Rust also uses composition instead of inheritance. You can create complex types by combining simpler ones without the need for a class hierarchy.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Animal&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Dog&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    animal&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Animal&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ServiceDog&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    dog&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Dog&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;A great resource on this principle is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://python-patterns.guide/gang-of-four/composition-over-inheritance/&quot;&gt;Composition Over Inheritance&lt;/a&gt;, part of Brandon Rhodes' &lt;em&gt;Python Patterns Guide&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For an example where I think OOP &amp;amp; inheritance went off the rails is Django's &lt;em&gt;class-based views&lt;/em&gt;. The inheritance tree of those views is too deep making it an unpleasant API to work with, and the code so much harder to reason about. A better way is the more functional approach, see &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://spookylukey.github.io/django-views-the-right-way/&quot;&gt;Luke Plant's Django Views — The Right Way&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;2-traits&quot;&gt;2. Traits&lt;/h2&gt;
&lt;p&gt;In Python, think Protocols. In Java, think interfaces. In Rust, traits are a powerful way to define shared behavior without the need for a class hierarchy; polymorphism without inheritance.&lt;/p&gt;
&lt;p&gt;Classic OOP:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-java z-variable z-other&quot;&gt;Animal a&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; = new&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Dog&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;speak&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Rust, you can achieve similar behavior using traits:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Speak&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; speak&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make_noise&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(x&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;impl&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Speak&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    x&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;speak&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The advantage here is that you can implement the &lt;code&gt;Speak&lt;/code&gt; trait for any type, and you don't need to have a common base class. This allows for more flexibility and code reuse.&lt;/p&gt;
&lt;p&gt;Python has something similar with Protocols, which are part of the &lt;code&gt;typing&lt;/code&gt; module. They allow you to define a set of methods that a class must implement, without requiring inheritance.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;/span&gt;&lt;span&gt; typing&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;/span&gt;&lt;span&gt; Protocol&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Speak&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-entity&quot;&gt;Protocol&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; speak&lt;/span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;(self) -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make_noise&lt;/span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;(x: Speak) -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    x.speak()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a more flexible alternative to ABCs (Abstract Base Classes) and allows for &lt;em&gt;duck typing&lt;/em&gt; while still providing type safety. I wrote &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://pybit.es/articles/typing-protocol-abc-alternative/&quot;&gt;an article about this on Pybites&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Where OOP couples data and behavior, Rust's traits allow you to define behavior separately from data. This promotes code reuse and flexibility without the need for a rigid class structure.&lt;/p&gt;
&lt;p&gt;Rust encourages:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; User&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Serialize&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Validate&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Persist&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is closer to the Single Responsibility Principle, the Unix philosophy of &quot;do one thing and do it well&quot;, functional programming of data-oriented design with pure functions that operate on data, and composition over inheritance.&lt;/p&gt;
&lt;p&gt;Hence Rust allows you to mix and match traits to create complex behavior without the need for a class hierarchy.&lt;/p&gt;
&lt;h2 id=&quot;3-ownership-and-borrowing&quot;&gt;3. Ownership and borrowing&lt;/h2&gt;
&lt;p&gt;Many OOP patterns exist to control mutation and provide proper encapsulation. In Rust, ownership and borrowing rules ensure that data is accessed safely and efficiently.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(data&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Data&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        // takes ownership (moved in)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(data&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Data&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;       // borrows, read-only&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(data&lt;/span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;: &amp;amp;mut&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Data&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;   // borrows, can mutate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just by looking at the function signature in Rust, you can understand how data is being used and modified: who owns it, who mutates it, and when it goes out of scope. It eliminates the need for patterns like getters/setters, which are often used in OOP to control access to data. And these rules are enforced at compile time, not runtime.&lt;/p&gt;
&lt;h2 id=&quot;4-modularity&quot;&gt;4. Modularity&lt;/h2&gt;
&lt;p&gt;I came to the conclusion some time ago that Python's module scope is a great feature. It allows you to organize code in a way that is more flexible than OOP's class-based organization. In Rust, modules and crates provide a way to organize code without the need for classes.&lt;/p&gt;
&lt;p&gt;Classic OOP:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;public class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Counter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    private int&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    public void&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; increment&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        value &lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Rust, you can use module-level functions and structs to achieve the same result:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; internal&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-storage z-type&quot;&gt;    pub struct&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Counter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        value&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    impl&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Counter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        pub fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; increment&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-keyword z-storage&quot;&gt;&amp;amp;mut&lt;/span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;            self&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;value &lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Outside:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span&gt;value &lt;/span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;// inaccessible&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;increment&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; // ok&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, &lt;code&gt;increment&lt;/code&gt; is a mutating method, the same as a setter. The win isn't avoiding methods, it's two things.&lt;/p&gt;
&lt;p&gt;First, the privacy boundary is the module, not the object: &lt;code&gt;value&lt;/code&gt; is hidden from the whole module, and you can hide free functions and structs too, not just wrap fields in a class.&lt;/p&gt;
&lt;p&gt;Second, you only write the method when you need to guard an invariant. If a field is just plain data, mark it &lt;code&gt;pub&lt;/code&gt; and read it directly, no getter ceremony. Java's idiom nudges you to wrap every field in &lt;code&gt;get&lt;/code&gt;/&lt;code&gt;set&lt;/code&gt; whether it needs it or not.&lt;/p&gt;
&lt;p&gt;So encapsulation lives at the module level, not the class level. It also leans toward a more functional style where pure functions operate on data without mutable state.&lt;/p&gt;
&lt;p&gt;In Python you can also hide functions and variables at the module level:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; _private_function&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pass&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this does not prevent somebody importing it so you need fencing mechanisms like &lt;code&gt;__all__&lt;/code&gt; to control what gets imported. Python's &lt;code&gt;_private&lt;/code&gt; is a suggestion, Rust's module privacy is enforced by the compiler.&lt;/p&gt;
&lt;h2 id=&quot;5-enums-and-pattern-matching&quot;&gt;5. Enums and pattern matching&lt;/h2&gt;
&lt;p&gt;In OOP, you often use class hierarchies to represent different types of objects. In Rust, you can use enums and pattern matching to achieve similar results without the need for a class hierarchy.&lt;/p&gt;
&lt;p&gt;Classic OOP:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;abstract class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Shape&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Circle&lt;/span&gt;&lt;span class=&quot;z-storage&quot;&gt; extends&lt;/span&gt;&lt;span class=&quot;z-entity&quot;&gt; Shape&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Square&lt;/span&gt;&lt;span class=&quot;z-storage&quot;&gt; extends&lt;/span&gt;&lt;span class=&quot;z-entity&quot;&gt; Shape&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Rust, you can use enums to represent different shapes:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Shape&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Circle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Square&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; area&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(shape&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Shape&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; shape {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Shape&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Circle&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(r)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3.14&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; r&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; r,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Shape&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Square&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;(s)&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s&lt;/span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;/span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; s,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not only is an enum more lightweight than a class hierarchy, it also pairs up really well with pattern matching handling different cases in a concise and (!) exhaustive manner. The compiler will not let you forget a case.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In short, OOP bundles data and behavior together which made a lot of sense to me for a long time. Learning Rust though, I am seeing new paradigms how the language designers have decoupled the two.&lt;/p&gt;
&lt;p&gt;With Rust you get the good parts of OOP: encapsulation, abstraction and polymorphism, while dropping the less maintainable parts: inheritance trees, mutable state and coupling.&lt;/p&gt;
&lt;p&gt;So to wrap up, here is a comparison of classic OOP -&amp;gt; Python -&amp;gt; Rust:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Concern&lt;/th&gt;&lt;th&gt;Traditional OOP&lt;/th&gt;&lt;th&gt;Python&lt;/th&gt;&lt;th&gt;Rust&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Encapsulation&lt;/td&gt;&lt;td&gt;Classes with private/public members&lt;/td&gt;&lt;td&gt;Modules + &lt;code&gt;_private&lt;/code&gt; convention&lt;/td&gt;&lt;td&gt;&lt;code&gt;mod&lt;/code&gt; + &lt;code&gt;pub&lt;/code&gt; visibility&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Polymorphism&lt;/td&gt;&lt;td&gt;Inheritance + virtual methods&lt;/td&gt;&lt;td&gt;Duck typing / Protocols&lt;/td&gt;&lt;td&gt;Traits&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Reuse&lt;/td&gt;&lt;td&gt;Inheritance&lt;/td&gt;&lt;td&gt;Composition&lt;/td&gt;&lt;td&gt;Composition&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;State modeling&lt;/td&gt;&lt;td&gt;Class hierarchies&lt;/td&gt;&lt;td&gt;&lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;dataclass&lt;/code&gt;, classes&lt;/td&gt;&lt;td&gt;&lt;code&gt;struct&lt;/code&gt; + &lt;code&gt;enum&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Object lifecycle&lt;/td&gt;&lt;td&gt;GC / constructors&lt;/td&gt;&lt;td&gt;GC&lt;/td&gt;&lt;td&gt;Ownership + borrowing&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Error handling&lt;/td&gt;&lt;td&gt;Exceptions&lt;/td&gt;&lt;td&gt;Exceptions&lt;/td&gt;&lt;td&gt;&lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; + exhaustive matching&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;typical-style-evolution&quot;&gt;Typical style evolution&lt;/h3&gt;
&lt;p&gt;Old-school OOP:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Object → Class → Inheritance → Framework&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Modern Python:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Data → Functions → Composition → Protocols&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rust:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Data → Ownership → Traits → Composition&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you see Python gets you far and is versatile, but Rust's ownership and traits give you an even more reliable and maintainable way to structure your code without the need for OOP.&lt;/p&gt;
&lt;h3 id=&quot;different-philosophy&quot;&gt;Different philosophy&lt;/h3&gt;
&lt;p&gt;I am not picking on Java or OOP, I've been a fan for a long time. Studying philosophy (e.g. Plato) gives you &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.linkedin.com/posts/bbelderbos_python-philosophy-share-7313152877324066819-tzzs/&quot;&gt;a deeper appreciation for this way of thinking&lt;/a&gt;. But it can also lead to overcomplication and unnecessary coupling.&lt;/p&gt;
&lt;p&gt;It's good to learn the different paradigms and understand their strengths and weaknesses. In summary:&lt;/p&gt;
&lt;p&gt;Traditional OOP:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Model the world as interacting objects.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Python:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;We trust developers.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is awesome, but not without risk. It allows for great flexibility and rapid development, but it can also lead to bugs and maintenance issues if not used carefully.&lt;/p&gt;
&lt;p&gt;Rust:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Prove correctness to the compiler.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A newer paradigm for me, but the way Rust decouples data and behavior, enforces ownership and borrowing rules, and promotes composition over inheritance, all sit well with me.&lt;/p&gt;
&lt;p&gt;Those things do lead to more reliable and maintainable code. It encourages you to think about your code in a way that is more focused on data and behavior rather than objects.&lt;/p&gt;</description>
	<pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Armin Ronacher: Dangerous Technology For Americans Only</title>
	<guid>https://lucumr.pocoo.org/2026/6/13/americans-only/</guid>
	<link>https://lucumr.pocoo.org/2026/6/13/americans-only/</link>
	<description>&lt;p&gt;There is a bit of schadenfreude on Twitter right now about Anthropic being hit
by the US government&amp;#8217;s export control directive to &lt;a href=&quot;https://www.anthropic.com/news/fable-mythos-access&quot;&gt;suspend access to Fable and
Mythos&lt;/a&gt;.  Anthropic and
their leadership have spent a lot of time and effort describing its own
technology as dangerous and in need of strict controls and regulation.  Now that
the US government appears to have taken that framing seriously and told them to
turn it off for foreign nationals I can see why people are making fun of that
situation.&lt;/p&gt;
&lt;p&gt;I understand the reaction, but I urge you to not entertain it for too long
because it is a giant distraction.  The important part is not that Anthropic&amp;#8217;s
safety language came back to bite them but the line the US government is
drawing: this technology is apparently so powerful that only Americans should
have it.&lt;/p&gt;
&lt;p&gt;We are on a clear path towards a world of division.  One should think that if a
model is too dangerous for everyone, then it is too dangerous for Americans too.
Instead the US is treating these models like weapons that need to be controlled.
It is not just about capabilities, it is about racism and nationalism.  If you
have the wrong passport, you are not to be trusted.  This is a very different
thing from safety, and Europeans should pay close attention to it.&lt;/p&gt;
&lt;h2&gt;Safety and National Control&lt;/h2&gt;
&lt;p&gt;The directive, as Anthropic describes it, applies to foreign nationals whether
they are inside or outside the United States, including foreign national
Anthropic employees.  That is an astonishing boundary if you think about it.  We
moved from &amp;#8220;do not sell this model to hostile governments&amp;#8221; to nationality itself
being the defining boundary.  This should be a wake-up call to Europeans in and
outside the US, and quite frankly, any non US citizen.&lt;/p&gt;
&lt;p&gt;A lot of AI safety discourse presents itself as universal: humanity,
catastrophic risk, safeguards, responsible deployment.  Even Anthropic&amp;#8217;s own
writings start out that way, but yet every time regulation is discussed there
is an overtone of national security and that it cannot get into the wrong hands.
It&amp;#8217;s not just Anthropic, it&amp;#8217;s the entire US based discourse on AI.  The
foundation is that the US has moral superiority and others are not to be
trusted.  That there are other countries are authoritarian, that they lack
freedoms.&lt;/p&gt;
&lt;p&gt;That should make us uncomfortable, not just Europeans, but particularly us.  It
is also a situation you cannot regulate yourself out of.  European technology
policy is entirely unprepared for this, because this is not a question of
regulation but a question of might and power, something that Europe lacks.&lt;/p&gt;
&lt;p&gt;Europe has spent years trying to regulate large American technology companies,
sometimes for good reasons.  I am not reflexively against that.  The DMA matters
&lt;a href=&quot;https://lucumr.pocoo.org/2026/6/10/gaslighting/&quot;&gt;because access matters&lt;/a&gt;.  Users should have agency
over their devices, their data, and the software they run.  But regulation is a
useless substitute for capability and we are lacking that.  Regulation might try
to force open doors but if those doors only come from American or Chinese
companies, then that accomplishes very little.&lt;/p&gt;
&lt;p&gt;Also let&amp;#8217;s not be naive in that this is a negotiation of money and force.  The
US is in that position because the US has a mighty military.  The US can bomb
nations anywhere in the world, force international trade routes closed and get
away with it.  That&amp;#8217;s true leverage.&lt;/p&gt;
&lt;h2&gt;Oh Europe&lt;/h2&gt;
&lt;p&gt;Europe is dependent on the United States in ways that are becoming increasingly
impossible to ignore.  We depend on American cloud providers, operating systems,
developer platforms and now AI models and internet from satellites.  We also
depend on global semiconductor supply chains we do not control.  If access to
frontier AI becomes a matter of American national security policy, Europe is not
a peer in that conversation and might not even be a market.&lt;/p&gt;
&lt;p&gt;That is a humiliating position, but one that happened entirely intentionally.&lt;/p&gt;
&lt;p&gt;European citizens and politicians still have not managed to move beyond blaming
the EU for its failures.  We built and maintained fragmented markets and then
pretended we had a single one.  We let company formation, hiring, equity
compensation, tax, notaries, KYC, banking, and cross-border services remain much
harder than they need to be and we are playing these rules against each other.
Not just on the European level, but within every single member state.  We
protect the trusts and established enterprises, who are risk averse and
entrenched, instead of trusting the next generation to build great companies.
We created a culture where process &lt;a href=&quot;https://lucumr.pocoo.org/2025/10/21/eu-resigation/&quot;&gt;becomes an excuse for low
agency&lt;/a&gt;.  We made it hard to build new and large
companies and then act surprised when our most ambitious founders move somewhere
else or just decided to incorporate their companies in the US.&lt;/p&gt;
&lt;p&gt;Increasingly, Europeans who want to build very large technology companies move
to the United States.  They do it because the capital markets are better, the
startup infrastructure is better, &lt;a href=&quot;https://lucumr.pocoo.org/2026/4/23/equity-for-europeans/&quot;&gt;employee equity is better
understood&lt;/a&gt;.  I cannot blame anyone doing it,
and I&amp;#8217;m guilty of this myself as we have incorporated our holding in Delaware.
If you are trying to raise serious money, hire aggressively, and move quickly,
the US often looks like the only game in town.  Because quite frankly: it is.&lt;/p&gt;
&lt;p&gt;But this is why we are on a dangerous death spiral already.  Talent leaves
because the ecosystem is weak and the ecosystem stays weak because talent
leaves.  Infrastructure makes the world: build excellent swimming pools and you
will grow a generation of great swimmers.&lt;/p&gt;
&lt;p&gt;The temporary task is straightforward but uncomfortable: Europeans need to
believe in themselves enough not to surrender to American gravity.  Moving to
the US as a founder or tech employee is rational and individually it is often
the right decision.  But if every ambitious person treats Europe as a lost
cause, then Europe becomes one.  If everyone with agency leaves, the only people
left to shape the system are the people most comfortable with the system as it
is.  Then we really should not be surprised when nothing changes.&lt;/p&gt;
&lt;p&gt;Europe needs more ambition, more ownership, more urgency, and more willingness
to build.  It needs less resignation.  It needs to stop confusing regulation
with strategy and dependency with virtue.  We need to deregulate where rules
serve mostly as protectionism.  We need capital markets that can fund companies
at the scale modern technology requires.  We need employee ownership to become
normal rather than exotic.  We need a real single market for services, not just
speeches about one.  We need countries to stop fighting each other while
claiming to act in the European interest.&lt;/p&gt;
&lt;p&gt;Most importantly: we need to stop blaming the politicians.  Too many European
companies are adding to that bureaucracy entirely out of their own choice.  They
drown you in paperwork.  At one point I had to sign a four page contract for a
120 Euro lamp at an Austrian retailer, just to pick up from their store 15
minutes later.  Sometimes I cannot get a speaking engagement at a European event
without someone sending me complex rights waivers over.  It&amp;#8217;s all just paperwork
protection against potential downsides.&lt;/p&gt;
&lt;p&gt;When we do not have the power to influence, we should at least understand why
and where things are failing.  Too many entrepreneurs are blaming EU regulation
for failures that are originating within the member states.  EU regulation is
the result of a democratic process between countries that are lobbying in favor
of their local industries against others in the same economic bloc.  No amount
of &lt;a href=&quot;https://lucumr.pocoo.org/2025/12/9/fixing-europe/&quot;&gt;abolishment of the EU&lt;/a&gt; is going to fix this harsh
reality.  Nothing more demonstrates this as the inability for cross-border M&amp;amp;A in
the European Union.  It&amp;#8217;s not the EU that blocks it, it&amp;#8217;s the country that loses
out.&lt;/p&gt;
&lt;p&gt;Strengthening Europe is necessary because weakness makes us pawns.  A Europe
that cannot build, cannot finance, cannot coordinate and cannot defend its own
interests will not be treated as an equal.  It will be regulated around,
export-controlled around, consulted after the fact or not consulted at all.&lt;/p&gt;
&lt;h2&gt;The American Trap&lt;/h2&gt;
&lt;p&gt;I do not want the lesson to be that Europe simply needs to turn itself into a
copy of the United States.  The US has solved some things that Europe has not.
It has deep capital markets, a much stronger culture of ownership, a greater
tolerance for risk, and institutions that often try to make progress possible
rather than explain why it cannot happen.  It also has achieved an internal
level of integration that is unparalleled in Europe.  Tremendous advantages!&lt;/p&gt;
&lt;p&gt;But the American path is not obviously a healthy one in all aspects.  It tends
to take paths with a lot of conflict and wars, a lot of internal societal
division and deep inequalities.  It centralizes powers away from citizens in the
presidency and people with money.  You are still trading one set of failures for
another.  You are at the whim of the US government and its strict rules and
regulations.  The US barely manages to uphold the rights for its own citizens
today.&lt;/p&gt;
&lt;p&gt;We should be honest about both sides.  You do not win by pretending that Europe
is fine.  You also do not win by pretending that America has figured everything
out.&lt;/p&gt;
&lt;p&gt;We must not be blind to all the signs of how international cooperation is
falling apart around us.  The US no longer talks to European governments before
implementing orders that directly affect Europeans.  It is threatening to take
Greenland, the territory of Denmark, one of its oldest allies.  Treaties,
alliances and institutions have lost all their worth.&lt;/p&gt;
&lt;p&gt;All that matters even if our own lives are focused on building companies,
creating wealth, hiring people and making things.  Our individual path to
success is one thing, but it depends on a world where contracts work, visas work
and don&amp;#8217;t change on a moment&amp;#8217;s notice, trade routes stay open, payment systems
function, and families are not torn apart by border regimes or wars.  If the
world descends into chaos, our basic needs cannot be considered met just because
we have a great salaries or equity or investors that trust us.&lt;/p&gt;
&lt;p&gt;This is why strengthening Europe cannot be the final goal.  A stronger EU is,
at best, a temporary defense against a darker world and not an excuse to replace
American nationalism with European nationalism.  The long-term answer cannot be
bigger and bigger blocs fighting over who may use which model, which chip, which
cloud or which trade route.&lt;/p&gt;
&lt;h2&gt;The Way Out Is Cooperation&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;m not asking here for Europeans to get their shit together just to compete
with the US or China.  Maybe I hope that this is a thing that develops, but the
goal absolutely cannot be that we accept the deterioration of international
relationships long term.&lt;/p&gt;
&lt;p&gt;I truly believe that Open Source matters and international cooperation matters.
It is not a magical answer to every problem, but it is one of the few paths we
have that does not naturally lead to total concentration of power.&lt;/p&gt;
&lt;p&gt;If frontier AI becomes something only large corporations and governments can
control, then everyone else becomes dependent on their judgment.  That is a bad
place to be.  Corporations will optimize for their incentives, as well
structured as they might be, and governments will optimize for more and more
power.  Right now we&amp;#8217;re on a path in which access to general-purpose capability
is mediated by a small number of actors with tremendous powers.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not naive in pretending AI cannot carry inherent risks.  Open systems are
messy, they can be misused and they create uncomfortable questions about
dual-use capabilities.  I do not want to wave that away but closed systems do
not make those questions disappear either.  Moving the power to decide into
fewer hands is not a solution I believe in.  And I would have the same opinion
if I was a US citizen living in the US.&lt;/p&gt;
&lt;p&gt;Any path that puts large blocs in a constant fight against each other has
despicable downstream effects that result in the removal of individual rights.
It&amp;#8217;s entirely pointless for the US to talk about freedoms that do not extend to
non-US citizens and the same is true for Europe or any other country.  We might
accept these restrictions temporarily, but we absolutely cannot accept them long
term for the inhumane effects that they can cause.&lt;/p&gt;
&lt;p&gt;If we believe this technology can be used for good, then broad access matters
and our goal should be to restore the international rule of law, and not to
further weaken it.  If we find ourselves in a war against our friends from other
countries, cold or hot, we have failed as society.&lt;/p&gt;
&lt;p&gt;The world we should be working back toward is one of international cooperation,
globalization in the best sense of the word, and human dignity.  The internet
has made our lives irreversibly international: every day people fall in love
across borders, marry across languages, move across continents, and work with
friends they may never meet in countries they may never visit.  Identifying too
strongly with any one country in that world is a fool&amp;#8217;s errand.&lt;/p&gt;
&lt;p&gt;Over the last decade too many of the people I got to know through Open Source
were directly dragged into a war.  I want to believe there is a way for us to
break this cycle.  We should be repairing failed states, rebuilding trust
between people, and finding ways to cooperate again instead of letting the
richest countries arm themselves and fight over who gets to control the future
and narrative.  Of course I want Europe to become stronger so it can stop being
a pawn, but if we mistake that temporary need for the destination, I will be
deeply disappointed.&lt;/p&gt;
&lt;p&gt;The way out is not American supremacy, Chinese supremacy or European supremacy.
The way out is to climb back toward cooperation before the alternative becomes
war.&lt;/p&gt;
&lt;p&gt;Artificial Intelligence is quickly becoming another instrument of militarization
and national rivalry, when it could be one of the most powerful tools for
cooperation we have.  We should be using it to help people across societies and
languages understand one another, not fighting over who gets to control it.&lt;/p&gt;</description>
	<pubDate>Sat, 13 Jun 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: The Real Python Podcast – Episode #299: EuroPython 2026: Celebrating 25 Years</title>
	<guid>https://realpython.com/podcasts/rpp/299/</guid>
	<link>https://realpython.com/podcasts/rpp/299/</link>
	<description>&lt;p&gt;What's happening at EuroPython 2026? The conference celebrates its 25th anniversary this year in Kraków, Poland. This week on the show, organizers Mia Bajić and Daria Linhart Grudzien join me to discuss this year's conference.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 12 Jun 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>EuroPython: June Newsletter: Talks Schedule Released</title>
	<guid>https://blog.europython.eu/june-newsletter-one-month-to-go/</guid>
	<link>https://blog.europython.eu/june-newsletter-one-month-to-go/</link>
	<description>&lt;p&gt;Hi all Pythonistas! &amp;#x1F44B;&amp;#xA0;&lt;/p&gt;&lt;p&gt;We have just one month left until we all meet up in Krak&amp;#xF3;w, and we&amp;#x2019;ve got a lot of new stuff to tell you: the schedule is available, new keynote announcements, our 25 years of EuroPython celebrations (win a free ticket!), the release of our Speaker&amp;#x2019;s Orientation Workshop video on YouTube (in case you missed it!), remote ticket availability, a reminder about ticket prices (going up on June 26th!), plus plenty more &amp;#x1F49A;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%8E%89-talk-schedule-available&quot;&gt;&lt;strong&gt;&amp;#x1F389; Talk Schedule Available&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Let&amp;#x2019;s start with the big one: the programme team have been working tirelessly to get the talk schedule finalised, and you can now read it, in full, over on our website. The talks this year were selected from a record breaking number of submissions, and we are really excited about the number of topics covered from such a wide range of speakers.&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Start noting down your &amp;#x2018;must see&amp;#x2019; favourites now, and plan out your &amp;amp;aposjourney&amp;amp;apos through the conference: &lt;a href=&quot;https://ep2026.europython.eu/schedule/?ref=blog.europython.eu&quot;&gt;https://ep2026.europython.eu/schedule/&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%8E%A4-keynote-announcements&quot;&gt;&lt;strong&gt;&amp;#x1F3A4; Keynote Announcements&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Guido van Rossum&lt;/strong&gt;, &lt;strong&gt;&amp;#x141;ukasz Langa, Pablo Galindo Salgado, &lt;/strong&gt;and &lt;strong&gt;Leah Wasser &lt;/strong&gt;were already on the schedule as keynote speakers, but we&amp;#x2019;ve now confirmed three more! We are very excited to have the following speakers joining us in Krak&amp;#xF3;w:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;William Woodruff&lt;/strong&gt; is a Member of Technical Staff at &lt;strong&gt;Astral&lt;/strong&gt;, where he works on building high-performance, secure tooling that is modernising the Python developer experience. Prior to Astral, he was an Engineering Director at Trail of Bits, leading high-impact security initiatives across open-source ecosystems.&lt;/p&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/data-src-image-11ed3ba2-5754-4c68-a4b7-c8129c9e9b1b.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;1080&quot; height=&quot;1350&quot; /&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Marlene Mhangami&lt;/strong&gt; is a Senior Developer Advocate at Microsoft and GitHub, where she focuses on the cutting edge of Python and AI. As a computer scientist, keynote speaker, and explorer, she is a massive driving force behind community growth across the globe.&lt;/p&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/data-src-image-b3f89841-291f-432c-8550-5f8368095096.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;1080&quot; height=&quot;1350&quot; /&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Imogen Wright&lt;/strong&gt; is a Senior Engineer at Amazon EC2, where they focus on making incredibly complex systems behave. Their career spans over two decades of solving high-stakes challenges across theoretical physics, HIV drug resistance, COVID genomics, cloud technologies, and even ad tech!&lt;/p&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/data-src-image-1deff8a4-5cde-45bd-a6d1-f913da8b78c8.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;1080&quot; height=&quot;1350&quot; /&gt;&lt;hr /&gt;&lt;p&gt;All of our keynote speakers are some of the most respected leaders in the industry and in their specific fields, and we are privileged to have them join us at EuroPython 2026. We are so pleased to be able to put together such an incredible line up! &amp;#x1F40D;&amp;#x1F49A;&lt;/p&gt;&lt;h2 id=&quot;%E2%8C%9B-get-your-ticket-before-prices-increase&quot;&gt;&lt;strong&gt;&amp;#x231B; Get Your Ticket Before Prices Increase&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;We know that many of you have already purchased tickets (thank you!) but a quick reminder to those who have yet to do so: ticket prices will increase on &lt;strong&gt;June 26th&lt;/strong&gt; and our &lt;strong&gt;Late Bird&lt;/strong&gt; prices will apply, so if you&amp;#x2019;re thinking of coming, it definitely makes sense to secure your ticket before then!&amp;#xA0;&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Purchase your tickets today on the EuroPython 2026 website: &lt;a href=&quot;https://ep2026.europython.eu/tickets/?ref=blog.europython.eu&quot;&gt;https://ep2026.europython.eu/tickets/&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%92%BB-remote-ticket-sales&quot;&gt;&lt;strong&gt;&amp;#x1F4BB; Remote Ticket Sales&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;If you are joining us remotely this year, just a heads up that remote sales will start next &lt;strong&gt;Monday, 15th June&lt;/strong&gt;. The tickets will be available to purchase on our website as soon as Monday rolls around!&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%8E%82-25-years-of-europython&quot;&gt;&lt;strong&gt;&amp;#x1F382; 25 Years of EuroPython&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;We are celebrating 25 years of EuroPython this year (I know, we can&amp;#x2019;t believe it either!), and we have a few fun things planned to make it special, including a chance to win a free ticket - which you can transfer to someone else, if you&amp;#x2019;ve already got yours!&lt;/p&gt;&lt;h3 id=&quot;%F0%9F%93%9C-the-oldest-badge-contest&quot;&gt;&amp;#x1F4DC;&lt;strong&gt; The Oldest Badge Contest&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Are you one of those people who keeps your badges from previous conferences? It might be about to pay off: we will be having a contest to find the &lt;strong&gt;Oldest EuroPython Badge&lt;/strong&gt; amongst all attendees this year! Dig around in your drawers, boxes, attic or other archive and find the oldest EuroPython badge (with your name on it&amp;#x2026;) that you can. Whoever has the oldest will win the contest!&lt;/p&gt;&lt;h3 id=&quot;%F0%9F%8E%AB-free-ticket-competition-your-europython-experiences&quot;&gt;&amp;#x1F3AB;&lt;strong&gt; Free Ticket Competition: Your EuroPython Experiences&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;We&amp;#x2019;re running a competition - open to anyone who has attended EuroPython in the past - who can record a short video telling us about their &lt;strong&gt;most impactful EuroPython experience&lt;/strong&gt;! The competition is open to anyone who has attended EuroPython before, and is really easy to enter. No need for anything very fancy: just record yourself talking and tell us why your particular experience at EuroPython made such an impact on you.&lt;/p&gt;&lt;p&gt;The competition will be closing on &lt;strong&gt;June 21st&lt;/strong&gt; (extended!), so you&amp;#x2019;ve still got plenty of time to enter.&lt;/p&gt;&lt;p&gt;&amp;#x1F449;  For the details, see the entry form: &lt;a href=&quot;https://forms.gle/WNPErwWtpE1oPVhD9?ref=blog.europython.eu&quot;&gt;https://forms.gle/WNPErwWtpE1oPVhD9&lt;/a&gt;&amp;#xA0;&lt;/p&gt;&lt;h3 id=&quot;%F0%9F%92%AD-taking-a-trip-down-memory-lane&quot;&gt;&amp;#x1F4AD;&lt;strong&gt; Taking a Trip Down Memory Lane&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Finally, we thought you might appreciate a little video we&amp;#x2019;ve posted on YouTube recently: Jonathan Hartley spoke to us at PyCon US about one of his favourite EuroPython experiences of the past:&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%A6%84-django-girls-workshop-sign-up&quot;&gt;&lt;strong&gt;&amp;#x1F984; Django Girls Workshop Sign Up&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;We are sure many of you are already aware of &lt;strong&gt;Django Girls&lt;/strong&gt; and the great work that they do in making Python and Django more accessible to people around the world (often but not only girls!), and we are super pleased to announce that they will be running a workshop at EuroPython 2026 in Krak&amp;#xF3;w!&lt;/p&gt;&lt;p&gt;&amp;#x1F449;  The workshop is a full day, on &lt;strong&gt;18 July &lt;/strong&gt;(a sprint day), and you can register on the Django Girls website: &lt;a href=&quot;https://djangogirls.org/en/krakow2/?ref=blog.europython.eu&quot;&gt;https://djangogirls.org/en/krakow2/&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%8F%83%E2%80%8D%E2%99%80%EF%B8%8F-women-in-python-5k-run&quot;&gt;&amp;#x1F3C3;&amp;#x200D;&amp;#x2640;&amp;#xFE0F; &lt;strong&gt;Women in Python 5K Run&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;On &lt;strong&gt;Thursday 16th July&lt;/strong&gt; there will be a group run with the aim of enabling some friendly networking and friendship building between women in the Python community.&lt;/p&gt;&lt;p&gt;It is open to runners of all experience levels, and will be a nice route around Krak&amp;#xF3;w - along the river and at walking distance from the conference venue. If you are interested, please fill out the form below to help us prepare better (no commitment required - yet!), and we will send details of how to confirm your place closer to the time.&lt;/p&gt;&lt;p&gt;We&amp;#x2019;d like to thank our sponsor &lt;a href=&quot;https://www.arm.com/?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;Arm&lt;/a&gt; for supporting this run.&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Register your interest here: &lt;a href=&quot;https://forms.gle/bcsBTtNX1crEQhbw8?ref=blog.europython.eu&quot;&gt;https://forms.gle/bcsBTtNX1crEQhbw8&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%E2%AD%90-on-site-volunteering&quot;&gt;&lt;strong&gt;&amp;#x2B50; On-Site Volunteering&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;A big thank you to all who responded to our call for on-site volunteers, and we are now considering the applications. We had over &lt;strong&gt;110 applications&lt;/strong&gt; (far more than last year), and we loved to see applications from countries all over the world! &amp;#x1F49A;&lt;/p&gt;&lt;p&gt;We are now selecting volunteers, and you will receive notification of the status of your application in the following week (13-19th June). We will contact everyone who applied, even if you were not selected.&lt;/p&gt;&lt;p&gt;Thanks again to all of you - volunteers are the heart of EuroPython and we could not run the conference without you. &amp;#x2728;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%91%A9%E2%80%8D%F0%9F%8F%AB-speaker-orientation-workshop&quot;&gt;&lt;strong&gt;&amp;#x1F469;&amp;#x200D;&amp;#x1F3EB; Speaker Orientation Workshop&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;The EuroPython Speaker Orientation ran on the 3rd June 2026, and contained valuable tips from some of the most experienced speakers in our community. The panel spent an hour and a half giving practical advice on preparing talks, creating effective slides, managing nerves, engaging audiences, and handling Q&amp;amp;A sessions.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Cheuk Ting Ho&lt;/strong&gt;, &lt;strong&gt;Rodrigo Gir&amp;#xE3;o Serr&amp;#xE3;o&lt;/strong&gt;, and &lt;strong&gt;Sebastian Witowski&lt;/strong&gt; answered questions from new and returning speakers, sharing insights and lessons from their own conference speaking journeys.&lt;/p&gt;&lt;p&gt;Thank you to our amazing panel and everyone who joined us - we can&amp;#x2019;t wait to see you in Krak&amp;#xF3;w!&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%92%9A-financial-aid-round-up&quot;&gt;&lt;strong&gt;&amp;#x1F49A; Financial Aid Round Up&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;This year, we received a record-high 217 financial aid applications across two rounds. We know how much care, hope, and effort goes into every application, and our financial aid team have worked hard to review them all with the attention they deserve.&lt;/p&gt;&lt;p&gt;We&amp;#x2019;re happy to share that all financial aid decisions have been sent out. With the &amp;#x20AC;35,000 budget provided by the EuroPython Society, we have issued 84 grant offers. We are grateful to be able to support so many members of our community, and sincerely hope that all grantees will be able to join us in Krak&amp;#xF3;w this summer to learn, connect, and celebrate the 25th anniversary of EuroPython.&lt;/p&gt;&lt;p&gt;To everyone who applied but was not offered a grant: we are very sorry for the disappointing news. If we miss you in Krak&amp;#xF3;w, we still very much hope you&amp;#x2019;ll be part of the conference and connect with us remotely.&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%93%BA-europython-youtube-channel&quot;&gt;&lt;strong&gt;&amp;#x1F4FA; EuroPython YouTube Channel&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;We&amp;amp;aposve been posting a lot of new content over on the &lt;a href=&quot;http://youtube.com/EuroPythonConference?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;EuroPython YouTube Channel&lt;/a&gt;, including some fun short interviews from PyCon US:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/shorts/FDqYfl9cvlA?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;Carol Willing talks about her favourite EuroPython moment&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/shorts/_-YqLVMmi50?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;Can you believe that some people have attended this many EuroPython conferences?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/shorts/-f_IbYRKD84?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;What fun things were planned at PyCon Italia this year?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;#x1F449; Subscribe and keep up with our latest videos: &lt;a href=&quot;https://www.youtube.com/@EuroPythonConference?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;https://www.youtube.com/@EuroPythonConference&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%92%AC-last-call-for-sponsor-booths&quot;&gt;&lt;strong&gt;&amp;#x1F4AC; Last Call for Sponsor Booths&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;We&amp;amp;aposre down to our last few sponsorship slots with booths! Want to meet the Python community face-to-face at EuroPython 2026? This is your final chance to connect with our thousands of attendees.&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Email &lt;a href=&quot;mailto:sponsoring@europython.eu&quot;&gt;sponsoring@europython.eu&lt;/a&gt; before the slots are gone!&lt;/p&gt;&lt;h2 id=&quot;%E2%9A%99%EF%B8%8F-reminder-rust-summit&quot;&gt;&lt;strong&gt;&amp;#x2699;&amp;#xFE0F; Reminder: Rust Summit&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Registration is still open for the full-day Rust summit, exploring the intersection of Rust and the Python ecosystem - it is a &amp;#x2018;must-see&amp;#x2019; for anyone interested in how Rust is turbocharging Python tooling and Python computational libraries in 2026.&lt;/p&gt;&lt;p&gt;This summit is designed for developers who already possess some practical experience in these topics and are looking to deepen their expertise, share lessons learned, and contribute to the community&amp;amp;aposs collective knowledge.&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Register for the Rust Summit: &lt;a href=&quot;https://ep2026.europython.eu/session/rust-summit-at-europython?ref=blog.europython.eu&quot;&gt;https://ep2026.europython.eu/session/rust-summit-at-europython&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%A4%9D-community-partners&quot;&gt;&lt;strong&gt;&amp;#x1F91D; Community Partners&lt;/strong&gt;&lt;/h2&gt;&lt;h3 id=&quot;%F0%9F%A6%AC-pystok&quot;&gt;&amp;#x1F9AC; PyStok&lt;/h3&gt;&lt;p&gt;PyStok #83 lands on June 17th at 18:00 at Zmiana Klimatu in Bia&amp;#x142;ystok &amp;#x2013; and free registration is officially live! &lt;/p&gt;&lt;p&gt;Between the &amp;quot;speed dating&amp;quot; networking, JetBrains giveaways, and the legendary &amp;quot;Podlaskie afterparty&amp;quot;, it&amp;#x2019;s the perfect spot to soak up those unique North-East Polish vibes and talk Python and AI with the local crowd.&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Grab your spot at &lt;a href=&quot;https://pystok.org/najblizsze-wydarzenie?ref=blog.europython.eu&quot; rel=&quot;noreferrer&quot;&gt;https://pystok.org/najblizsze-wydarzenie&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%93%A3-community-outreach&quot;&gt;&lt;strong&gt;&amp;#x1F4E3; Community Outreach&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;The EuroPython Society has continued our world tour of Python events, and as always, thank you to everyone that came to speak to us!&lt;/p&gt;&lt;h3 id=&quot;%F0%9F%87%BA%F0%9F%87%B8-pycon-us&quot;&gt;&lt;strong&gt;&amp;#x1F1FA;&amp;#x1F1F8; PyCon US&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Several members of the EuroPython Society were at PyCon US in Long Beach, and we were very happy to have a stand at the conference and meet friends old and new. We know many of you will be joining us in Krak&amp;#xF3;w as well, and we look forward to seeing you again!&lt;/p&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/data-src-image-38dd9925-d124-4ff0-9f19-b8d96c479f1c.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;1280&quot; height=&quot;959&quot; /&gt;&lt;p&gt;&amp;#x1F449; For more information about what we got up to PyCon US, check out our post on the EuroPython Society blog: &lt;a href=&quot;https://europython-society.org/europython-society-at-pycon-us-2026/?ref=blog.europython.eu&quot;&gt;https://europython-society.org/europython-society-at-pycon-us-2026/&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;%F0%9F%87%AE%F0%9F%87%B9-pycon-italia&quot;&gt;&lt;strong&gt;&amp;#x1F1EE;&amp;#x1F1F9; PyCon Italia&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;The EuroPython Society also had a stand at PyCon Italia, which we shared with the Django Software Foundation, and we were pleased to see such interest in our stickers, which we managed to &amp;#x2018;sell out&amp;#x2019; of on the 2nd day of talks! If you want more stickers, you know where to go!&lt;/p&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/data-src-image-c07cbc77-bfe9-4352-a5a4-87654cd82494.jpeg&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;1024&quot; height=&quot;768&quot; /&gt;&lt;h2 id=&quot;%F0%9F%8E%81-sponsor-spotlight&quot;&gt;&lt;strong&gt;&amp;#x1F381; Sponsor Spotlight&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;We&amp;amp;aposd like to thank our three Platinum sponsors for supporting EuroPython:&lt;/p&gt;&lt;a href=&quot;https://careers.manychat.com/?ref=blog.europython.eu&quot;&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/05/manychat_clearspace_white_bg.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;2000&quot; height=&quot;547&quot; /&gt;&lt;/a&gt;&lt;span&gt;View job openings at Manychat&lt;/span&gt;&lt;p&gt;&lt;strong&gt;Manychat builds AI-powered chat automation for 1M+ creators and brands at real production scale.&lt;/strong&gt;&lt;/p&gt;&lt;hr /&gt;&lt;a href=&quot;https://www.microsoft.com/?ref=blog.europython.eu&quot;&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/microsoft-whitebg-clearspace.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;2000&quot; height=&quot;547&quot; /&gt;&lt;/a&gt;&lt;p&gt;&lt;strong&gt;Open Source enables Microsoft products and services to bring choice, technology and community to our customers.&lt;/strong&gt;&lt;/p&gt;&lt;hr /&gt;&lt;a href=&quot;https://vercel.com/?ref=blog.europython.eu&quot;&gt;&lt;img src=&quot;https://blog.europython.eu/content/images/2026/06/vercel-whitebg-clearspace.png&quot; class=&quot;kg-image&quot; alt=&quot;alt&quot; width=&quot;2000&quot; height=&quot;547&quot; /&gt;&lt;/a&gt;&lt;p&gt;&lt;strong&gt;Vercel provies Agentic Infrastructure for every app and agent. They are the creators of AI SDK, Next.js, Turborepo, and v0.&lt;/strong&gt;&lt;/p&gt;&lt;h2 id=&quot;%F0%9F%91%8B-stay-connected&quot;&gt;&lt;strong&gt;&amp;#x1F44B;  Stay Connected&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Follow us on social media and subscribe to our newsletter for all the updates:&lt;/p&gt;&lt;p&gt;&amp;#x1F449; Sign up for the newsletter: &lt;a href=&quot;https://blog.europython.eu/#/portal/signup&quot;&gt;https://blog.europython.eu/portal/signup&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a href=&quot;https://www.linkedin.com/company/europython/?ref=blog.europython.eu&quot;&gt;https://www.linkedin.com/company/europython/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;X/Twitter&lt;/strong&gt;: &lt;a href=&quot;https://x.com/europython?ref=blog.europython.eu&quot;&gt;https://x.com/europython&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Mastodon&lt;/strong&gt;: &lt;a href=&quot;https://fosstodon.org/@europython?ref=blog.europython.eu&quot;&gt;https://fosstodon.org/@europython&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Bluesky&lt;/strong&gt;: &lt;a href=&quot;https://bsky.app/profile/europython.eu?ref=blog.europython.eu&quot;&gt;https://bsky.app/profile/europython.eu&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Instagram&lt;/strong&gt;: &lt;a href=&quot;https://www.instagram.com/europython/?ref=blog.europython.eu&quot;&gt;https://www.instagram.com/europython/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;YouTube&lt;/strong&gt;: &lt;a href=&quot;https://www.youtube.com/@EuroPythonConference?ref=blog.europython.eu&quot;&gt;https://www.youtube.com/@EuroPythonConference&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Okay, what a packed edition this one has been! It&amp;#x2019;s all go here at EuroPython and as you can see, we have so much in store for you. Don&amp;#x2019;t forget: get your tickets before the prices increase, and we can&amp;#x2019;t wait to see you really, really soon! &amp;#x1F40D;&amp;#x1F49A;&lt;/p&gt;&lt;p&gt;Cheers,&lt;/p&gt;&lt;p&gt;The EuroPython Team &lt;/p&gt;&lt;div class=&quot;kg-card kg-signup-card kg-width-wide &quot;&gt;
            
            &lt;div class=&quot;kg-signup-card-content&quot;&gt;
                
                &lt;div class=&quot;kg-signup-card-text &quot;&gt;
                    &lt;h2 class=&quot;kg-signup-card-heading&quot;&gt;&lt;span&gt;Sign up for EuroPython Blog&lt;/span&gt;&lt;/h2&gt;
                    &lt;p class=&quot;kg-signup-card-subheading&quot;&gt;&lt;span&gt;The official blog of everything &amp;amp; anything EuroPython! EuroPython 2026 13-19 July, Krak&amp;#xF3;w&lt;/span&gt;&lt;/p&gt;
                    
        &lt;form class=&quot;kg-signup-card-form&quot;&gt;
            
            &lt;div class=&quot;kg-signup-card-fields&quot;&gt;
                &lt;input class=&quot;kg-signup-card-input&quot; id=&quot;email&quot; type=&quot;email&quot; /&gt;
                &lt;button class=&quot;kg-signup-card-button kg-style-accent&quot; type=&quot;submit&quot;&gt;
                    &lt;span class=&quot;kg-signup-card-button-default&quot;&gt;Subscribe&lt;/span&gt;
                    &lt;span class=&quot;kg-signup-card-button-loading&quot;&gt;
        
            
                
                
                
            
            
                .nc-loop-dots-4-24-icon-o{--animation-duration:0.8s}
                .nc-loop-dots-4-24-icon-o *{opacity:.4;transform:scale(.75);animation:nc-loop-dots-4-anim var(--animation-duration) infinite}
                .nc-loop-dots-4-24-icon-o :nth-child(1){transform-origin:4px 12px;animation-delay:-.3s;animation-delay:calc(var(--animation-duration)/-2.666)}
                .nc-loop-dots-4-24-icon-o :nth-child(2){transform-origin:12px 12px;animation-delay:-.15s;animation-delay:calc(var(--animation-duration)/-5.333)}
                .nc-loop-dots-4-24-icon-o :nth-child(3){transform-origin:20px 12px}
                @keyframes nc-loop-dots-4-anim{0%,100%{opacity:.4;transform:scale(.75)}50%{opacity:1;transform:scale(1)}}
            
        
    &lt;/span&gt;
                &lt;/button&gt;
            &lt;/div&gt;
            &lt;div class=&quot;kg-signup-card-success&quot;&gt;
                Email sent! Check your inbox to complete your signup.
            &lt;/div&gt;
            &lt;div class=&quot;kg-signup-card-error&quot;&gt;&lt;/div&gt;
        &lt;/form&gt;
        
                    &lt;p class=&quot;kg-signup-card-disclaimer&quot;&gt;&lt;span&gt;No spam. Unsubscribe anytime.&lt;/span&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;</description>
	<pubDate>Fri, 12 Jun 2026 09:41:36 +0000</pubDate>
</item>
<item>
	<title>Hugo van Kemenade: I'm delighted to rejoin the Sovereign Tech Fellowship</title>
	<guid>https://hugovk.dev/blog/2026/sovereign-tech-fellowship/</guid>
	<link>https://hugovk.dev/blog/2026/sovereign-tech-fellowship/</link>
	<description>&lt;p&gt;I&amp;rsquo;m happy to rejoin the
&lt;a href=&quot;https://www.sovereign.tech/programs/fellowship&quot;&gt;Sovereign Tech Fellowship&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I was one of six participants in the
&lt;a href=&quot;https://hugovk.dev/2025/im-excited-to-join-the-sovereign-tech-fellowship/&quot;&gt;2025 pilot&lt;/a&gt; to pay
maintainers of critical open source technologies in the public interest. By all accounts
this first cohort was a resounding success, and I&amp;rsquo;m glad to see the programme continue.&lt;/p&gt;
&lt;p&gt;It was wonderful to be part of the inaugural Sovereign Tech Fellowship, and incredibly
beneficial to my projects: it gave me the time to focus on releasing Python 3.14 and
3.15 smoothly, to mentor and onboard others, and to support the wider community.&lt;/p&gt;
&lt;h2 id=&quot;2025-impact&quot; class=&quot;relative group&quot;&gt;2025 impact &lt;span class=&quot;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100&quot;&gt;&lt;a class=&quot;group-hover:text-primary-300 dark:group-hover:text-neutral-700&quot; href=&quot;https://hugovk.dev/tags/python/index.xml#2025-impact&quot;&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;The
&lt;a href=&quot;https://www.sovereign.tech/publications/evaluation-sovereign-tech-fellowship-2025&quot;&gt;2025 evaluation report&lt;/a&gt;
covers all six of us and the benefits of the programme at a higher level. Here&amp;rsquo;s some of
the specific things I achieved.&lt;/p&gt;
&lt;p&gt;I was happy with how the
&lt;a href=&quot;https://discuss.python.org/t/python-3-14-0-final-is-here/104210&quot;&gt;big Python 3.14.0&lt;/a&gt;
&lt;a href=&quot;https://hugovk.dev/2025/releasing-python-3-14-0/&quot;&gt;release went&lt;/a&gt;. This is in part from having a good
team to work with, and building on the past, but no doubt also due to being able to
focus and invest time thanks to the Fellowship.&lt;/p&gt;
&lt;p&gt;On many occasions, having time to dedicate to the role meant I could prioritise things
as they occurred. For example, when needing to make expedited releases, I could dedicate
time to go through all the necessary prep, and make the release without any stress of
fitting it in around a regular job. Similarly, when last-minute problems came up on
release day, such as newly-committed code not passing tests, I didn&amp;rsquo;t need to rush, and
could contact the contributor to arrange a fix. Some other release managers had reverted
similar changes to let the contributor try again for a later release, but there was less
pressure for me and I could wait longer.&lt;/p&gt;
&lt;p&gt;I was able to mentor other project members, such as helping onboard the next release
manager, and also answer questions for other triagers. I promoted two new triagers in
different projects. Other community members sometimes asked me about how to contribute.
I attended many community &amp;ldquo;office hours&amp;rdquo; meetings and Monthly Conference Organisers'
calls to share what&amp;rsquo;s going on and answer questions, and likewise
&lt;a href=&quot;https://hugovk.dev/blog/&quot;&gt;blogged&lt;/a&gt; and shared on social media such as
&lt;a href=&quot;https://mastodon.social/@hugovk&quot;&gt;Mastodon&lt;/a&gt;,
&lt;a href=&quot;https://bsky.app/profile/hugovk.dev&quot;&gt;Bluesky&lt;/a&gt; and
&lt;a href=&quot;https://www.linkedin.com/in/hugovk/&quot;&gt;LinkedIn&lt;/a&gt;. I was able to attend many conferences
and give talks about the upcoming release, and discuss with other attendees what happens
with Python releases and the project in general. This all helps improve transparency. I
also chaired many monthly
&lt;a href=&quot;https://docs-community.readthedocs.io/community/monthly-meeting.html&quot;&gt;Docs Working Group meetings&lt;/a&gt;,
and attended many other meetings from different projects.&lt;/p&gt;
&lt;p&gt;I was able to make many improvements in the release process, through additional
automation and testing to remove tedious manual steps. I&amp;rsquo;ve improved the accessibility
of websites visited by tens of millions per month.&lt;/p&gt;
&lt;p&gt;I created a triage dashboard that helped us close hundreds of issues, and also complete
forgotten backports including security fixes.&lt;/p&gt;
&lt;p&gt;I was also able to invest time on non-technical, social, organisational and governance
improvements. I&amp;rsquo;m proud
&lt;a href=&quot;https://discuss.python.org/t/alternate-the-language-summit-between-pycon-us-and-europython/102156&quot;&gt;my proposal was accepted&lt;/a&gt;
to alternate the Language Summit between PyCon US and EuroPython, rather than always
being in the US, to improve the diversity of voices of who will shape the future of
Python. The
&lt;a href=&quot;https://ep2026.europython.eu/language-summit/&quot;&gt;2026 summit will be held at EuroPython&lt;/a&gt;
and I&amp;rsquo;m helping organise.&lt;/p&gt;
&lt;p&gt;Since 2009, the summit has been a one-day event that takes place at PyCon US before the
main conference days. It has also been held at EuroPython twice, in 2010 and 2011. The
PSF mission is &lt;em&gt;&amp;ldquo;to support and facilitate the growth of a diverse and international
community of Python programmers&amp;rdquo;&lt;/em&gt;, and not all potential attendees can travel to the US
each year. This proposal took a lot of work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In November 2024, the core team discussed on Discord the possibility of alternating
the summit between PyCon US and EuroPython. People were in favour, but said it would
need to be discussed at the summit at PyCon US in May 2025.&lt;/li&gt;
&lt;li&gt;In March 2025, I asked for the topic to be added to the agenda, as I wasn&amp;rsquo;t attending.&lt;/li&gt;
&lt;li&gt;In May, the discussion took place. The minutes simply said: &amp;ldquo;Watch out for a Discourse
thread to discuss this.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;In July, during EuroPython, I asked summit attendees what the impression was, and they
said people were in favour. I also spoke with the chair of EuroPython Society about
the summit requirements, and they said they&amp;rsquo;d be happy to host us.&lt;/li&gt;
&lt;li&gt;In August, because no Discourse thread had appeared, I opened a proposal to alternate.&lt;/li&gt;
&lt;li&gt;In September, during the Steering Council Q&amp;amp;A at the Core Team Sprint, I asked about
next steps. The consensus was for the SC to open a formal poll amongst the core team.&lt;/li&gt;
&lt;li&gt;In October, the SC opened a poll for core team members.&lt;/li&gt;
&lt;li&gt;In November, the poll concluded overwhelmingly in favour of alternating.&lt;/li&gt;
&lt;li&gt;In December, the SC approved my request. I volunteered to help organise the summit and
opened discussions with the EuroPython Society to make it happen in 2026.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I had more free time to spend on non-open source things, but also more free time to help
the local Python community such as by co-organising two
&lt;a href=&quot;https://helsinki-python.github.io/&quot;&gt;local&lt;/a&gt;
&lt;a href=&quot;https://pydata-helsinki.github.io/&quot;&gt;meetups&lt;/a&gt;. One person I nominated became a Fellow of
the Python Software Foundation and another of the EuroPython Society, which recognises
the importance of community work.&lt;/p&gt;
&lt;p&gt;Finally, I enjoyed our monthly Fellowship meetings where the six of us all gave a
summary of our last month&amp;rsquo;s work. Similarly, it was great to meet most of them in person
along with people from the Agency at the
&lt;a href=&quot;https://www.sovereign.tech/news/who-will-maintain-our-digital-future&quot;&gt;event to mark the inaugural Sovereign Tech Fellowship cohort&lt;/a&gt;
and hear the results of the evaluation report.&lt;/p&gt;
&lt;h2 id=&quot;arbitrary-statistics&quot; class=&quot;relative group&quot;&gt;Arbitrary statistics &lt;span class=&quot;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100&quot;&gt;&lt;a class=&quot;group-hover:text-primary-300 dark:group-hover:text-neutral-700&quot; href=&quot;https://hugovk.dev/tags/python/index.xml#arbitrary-statistics&quot;&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;On GitHub:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Total contributions: 6,642&lt;/li&gt;
&lt;li&gt;Issues created: 90&lt;/li&gt;
&lt;li&gt;PRs created: 901&lt;/li&gt;
&lt;li&gt;Issues closed: 446&lt;/li&gt;
&lt;li&gt;PRs merged: 1,401&lt;/li&gt;
&lt;li&gt;PRs closed: 142&lt;/li&gt;
&lt;li&gt;Total issues involved with: 1,409&lt;/li&gt;
&lt;li&gt;Total PRs involved with: 4,095&lt;/li&gt;
&lt;li&gt;Repositories affected: 409&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Made 55 releases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;13 of Python 3.14&lt;/li&gt;
&lt;li&gt;3 of Python 3.15&lt;/li&gt;
&lt;li&gt;39 of PyPI projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Started maintaining:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://planetpython.org/&quot;&gt;Python Planet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pythonwheels.com/&quot;&gt;Python Wheels&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Archived:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/python-twitter-tools/twitter/issues/476&quot;&gt;Python Twitter Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://discuss.python.org/t/archive-python-ideas-mailing-list-in-favour-of-discourse/88398&quot;&gt;python-ideas mailing list&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attended eight conferences in Berlin (&lt;a href=&quot;https://25.foss-backstage.de/&quot;&gt;FOSS Backstage&lt;/a&gt;
and &lt;a href=&quot;https://25.foss-backstage.design/&quot;&gt;Design&lt;/a&gt;), Bologna
(&lt;a href=&quot;https://2025.pycon.it/en&quot;&gt;PyCon Italia&lt;/a&gt;), Prague
(&lt;a href=&quot;https://ep2025.europython.eu/&quot;&gt;EuroPython&lt;/a&gt;), Athens
(&lt;a href=&quot;https://2025.pycon.gr/en/&quot;&gt;PyCon Greece&lt;/a&gt;), Manchester
(&lt;a href=&quot;https://2025.pyconuk.org/&quot;&gt;PyCon UK&lt;/a&gt;), Tallinn
(&lt;a href=&quot;https://2025.pycon.ee/&quot;&gt;PyCon Estonia&lt;/a&gt;), Jyväskylä
(&lt;a href=&quot;https://fi.pycon.org/&quot;&gt;PyCon Finland&lt;/a&gt;) and Stockholm
(&lt;a href=&quot;https://pycon.se/&quot;&gt;PyCon Sweden&lt;/a&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On a discussion panel at one&lt;/li&gt;
&lt;li&gt;Gave a lightning talk at five&lt;/li&gt;
&lt;li&gt;Announced PyCon Finland at four&lt;/li&gt;
&lt;li&gt;Helped new contributors at sprints at three&lt;/li&gt;
&lt;li&gt;Hosted a barcamp session at one&lt;/li&gt;
&lt;li&gt;Helped organise one by reviewing talks and through promotion&lt;/li&gt;
&lt;li&gt;Volunteered at one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attended three online conferences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;March: SustainOSS Virtual Forum&lt;/li&gt;
&lt;li&gt;May: Maintainer Summit&lt;/li&gt;
&lt;li&gt;December: PyLadiesCon&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other events:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;September: &lt;a href=&quot;https://hugovk.dev/2025/python-core-sprint/&quot;&gt;Core Team Sprint&lt;/a&gt; in Cambridge
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://open.spotify.com/episode/3zMQYlP7hF7fKi8wdlAxyn&quot;&gt;Podcast interview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;December:
&lt;a href=&quot;https://www.sovereign.tech/news/who-will-maintain-our-digital-future&quot;&gt;Sovereign Tech Agency event&lt;/a&gt;
in Berlin to mark the inaugural Fellowship cohort&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Meetups:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Co-organised 16 meetups for &lt;a href=&quot;https://helsinki-python.github.io/&quot;&gt;two&lt;/a&gt; groups,
&lt;a href=&quot;https://pydata-helsinki.github.io/&quot;&gt;one&lt;/a&gt; which we restarted in 2025&lt;/li&gt;
&lt;li&gt;Attended 27 meetups of 11 groups in four cities and three countries&lt;/li&gt;
&lt;li&gt;Gave one long talk and four lightning talks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://docs-community.readthedocs.io/community/index.html&quot;&gt;Docs Working Group&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Organised 12
&lt;a href=&quot;https://docs-community.readthedocs.io/monthly-meeting/index.html&quot;&gt;monthly meetings&lt;/a&gt;,
chaired 9, attended 10&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/psf/user-success-wg/blob/main/WG-charter.md&quot;&gt;User Success Workgroup&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Attended two meetings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Published 17 blog posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;February: &lt;a href=&quot;https://hugovk.dev/2025/how-to-delay-a-python-release/&quot;&gt;How to delay a Python release&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;February:
&lt;a href=&quot;https://hugovk.dev/2025/im-excited-to-join-the-sovereign-tech-fellowship/&quot;&gt;I&amp;rsquo;m excited to join the Sovereign Tech Fellowship&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;February: &lt;a href=&quot;https://hugovk.dev/2025/improving-licence-metadata/&quot;&gt;Improving licence metadata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;March:
&lt;a href=&quot;https://hugovk.dev/2025/free-threaded-python-on-github-actions/&quot;&gt;Free-threaded Python on GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;April:
&lt;a href=&quot;https://hugovk.dev/2025/my-most-used-command-line-commands/&quot;&gt;My most used command-line commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;May: &lt;a href=&quot;https://hugovk.dev/2025/peps-and-co/&quot;&gt;PEPs &amp;amp; Co.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;June: &lt;a href=&quot;https://hugovk.dev/2025/run-coverage-on-tests/&quot;&gt;Run coverage on tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;August:
&lt;a href=&quot;https://hugovk.dev/2025/europython-2025-a-roundup-of-writeups/&quot;&gt;EuroPython 2025: A roundup of writeups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;September: &lt;a href=&quot;https://hugovk.dev/2025/ready-prek-go/&quot;&gt;Ready prek go!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;October: &lt;a href=&quot;https://hugovk.dev/2025/releasing-python-3-14-0/&quot;&gt;Releasing Python 3.14.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;October: &lt;a href=&quot;https://hugovk.dev/2025/lazy-imports/&quot;&gt;Three times faster with lazy imports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;November: &lt;a href=&quot;https://hugovk.dev/2025/python-core-sprint/&quot;&gt;Python Core Sprint 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;November: &lt;a href=&quot;https://hugovk.dev/2025/secrets-in-env-vars/&quot;&gt;Setting secrets in env vars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;December: &lt;a href=&quot;https://hugovk.dev/2025/steering-council-election/&quot;&gt;Steering Council election&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;December: &lt;a href=&quot;https://hugovk.dev/2025/steering-council-results/&quot;&gt;Steering Council results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;December: &lt;a href=&quot;https://hugovk.dev/2025/and-now/&quot;&gt;And now for something completely different&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;December: &lt;a href=&quot;https://hugovk.dev/2025/minus-six/&quot;&gt;Replacing python-dateutil to remove six&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reported 67 accounts to GitHub for spam/abuse/inauthentic activity.&lt;/p&gt;
&lt;h2 id=&quot;2026-and-beyond&quot; class=&quot;relative group&quot;&gt;2026 and beyond &lt;span class=&quot;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100&quot;&gt;&lt;a class=&quot;group-hover:text-primary-300 dark:group-hover:text-neutral-700&quot; href=&quot;https://hugovk.dev/tags/python/index.xml#2026-and-beyond&quot;&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;This time we&amp;rsquo;re 14 Fellows, and not only maintainers but also community managers and
technical writers. It&amp;rsquo;s great that Python core dev
&lt;a href=&quot;https://stan.ulbrych.org/&quot;&gt;Stan Ulbrych&lt;/a&gt; and PSF director
&lt;a href=&quot;https://georgiker.com/&quot;&gt;Georgi Ker&lt;/a&gt; are also joining, and I&amp;rsquo;m looking forward to
meeting the other
&lt;a href=&quot;https://www.sovereign.tech/news/meet-the-2026-sovereign-tech-fellows&quot;&gt;Sovereign Tech Fellows&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m really pleased to again be working with the Sovereign Tech Agency. They&amp;rsquo;re showing
the world some of the ways we can improve open source and critical digital
infrastructure, through a range of different
&lt;a href=&quot;https://www.sovereign.tech/programs&quot;&gt;programmes&lt;/a&gt;. Their success has informed the
proposal for an &lt;a href=&quot;https://eu-stf.openforumeurope.org/&quot;&gt;EU Sovereign Tech Fund (EU-STF)&lt;/a&gt;,
and they have also helped shape the
&lt;a href=&quot;https://digital-commons-edic.eu/&quot;&gt;European Digital Infrastructure Consortium for digital commons (DC-EDIC)&lt;/a&gt;,
with an &lt;a href=&quot;https://digital-commons-edic.eu/projects/#eu-stf&quot;&gt;EU-STF pilot&lt;/a&gt; kicking off
later this month which builds on their experience. And it&amp;rsquo;s good to see the focus on
maintenance and long-term sustainability in the brand new
&lt;a href=&quot;https://digital-strategy.ec.europa.eu/en/policies/open-source-strategy&quot;&gt;EU Open Source Strategy&lt;/a&gt;,
announced just last week.&lt;/p&gt;
&lt;p&gt;And by the way, the Sovereign Tech Agency are currently hiring, check out their
&lt;a href=&quot;https://www.sovereign.tech/jobs&quot;&gt;open positions&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;small&gt;Header photo by &lt;a href=&quot;https://www.janmichalko.com/&quot;&gt;Jan Michalko&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 12 Jun 2026 07:35:12 +0000</pubDate>
</item>
<item>
	<title>scikit-learn: scikit-learn release 1.9: better numerics, new core functionality</title>
	<guid>https://blog.scikit-learn.org/updates/release-1-9/</guid>
	<link>https://blog.scikit-learn.org/updates/release-1-9/</link>
	<description>&lt;div&gt;
  &lt;img src=&quot;https://blog.scikit-learn.org/assets/images/posts_images/1_9_release/scikit-learn_1_9.png&quot; alt=&quot;&quot; /&gt;
  

  
  
  
  

  

  

Author:  
      &lt;a href=&quot;https://gael-varoquaux.info/&quot; rel=&quot;me noopener noreferrer&quot;&gt;&lt;img src=&quot;https://blog.scikit-learn.org/assets/images/author_images/gael_varoquaux.png&quot; alt=&quot;Author Icon&quot; class=&quot;orcid-icon&quot; /&gt;Gael Varoquaux&lt;/a&gt;
     

&lt;br /&gt;&lt;br /&gt;

&lt;/div&gt;

&lt;p&gt;Scikit-learn 1.9 release is out, and it comes with solid improvements to
many existing estimators, making them faster, more stable, handling
missing values, adding GPU support… The release also enhances the
estimator displays in notebooks, and introduces a callback mechanism that
opens the door to progress bars or advanced monitoring of convergence.&lt;/p&gt;

&lt;h2 id=&quot;improvement-richer-html-views&quot;&gt;Improvement: Richer HTML views&lt;/h2&gt;

&lt;p&gt;The improvements that most will easily view are those on the estimator displays.&lt;br /&gt;
Since recent versions, the estimator views displayed in notebooks can show the parameters of the estimators (revealed by clicking on the estimator name). Latest release adds a view of the fitted attribute, as visible below:&lt;/p&gt;


 &lt;img src=&quot;https://blog.scikit-learn.org/assets/images/posts_images/1_9_release/fitted_attr.png&quot; alt=&quot;HTML displays showing the fitted attributes&quot; /&gt; 
 
  HTML display in a notebook, with the fitted attributes visible.
 

&lt;p&gt;In addition, the ColumnTransformer’s view has been enhanced to help the user understand how features are assembled:&lt;/p&gt;


 &lt;img src=&quot;https://blog.scikit-learn.org/assets/images/posts_images/1_9_release/feature_names.png&quot; alt=&quot;HTML displays showing the output feature names&quot; /&gt; 
 
  HTML display in a notebook, with the output feature names visible.
 


&lt;h2 id=&quot;a-new-promise-callbacks&quot;&gt;A new promise: Callbacks&lt;/h2&gt;

&lt;p&gt;Scikit-learn 1.9 comes with a callback mechanism, currently experimental. We spent a lot of time designing it so that it enables many different uses: nested tracking of progress (even in parallel computing) on a variety of measures, early stopping…&lt;br /&gt;
The release notes come with &lt;a href=&quot;https://scikit-learn.org/dev/auto_examples/release_highlights/plot_release_highlights_1_9_0.html#callbacks&quot;&gt;an example on how to use these callbacks to monitor scores and to display progress bars&lt;/a&gt; – &lt;a href=&quot;https://scikit-learn.org/stable/auto_examples/callbacks/plot_scoring_monitor.html&quot;&gt;a more advance monitoring example&lt;/a&gt;.&lt;/p&gt;

 &lt;a href=&quot;https://scikit-learn.org/dev/auto_examples/release_highlights/plot_release_highlights_1_9_0.html#callbacks&quot;&gt;
 &lt;img src=&quot;https://blog.scikit-learn.org/assets/images/posts_images/1_9_release/callbacks.png&quot; alt=&quot;The logging and progress-bar callbacks in a notebook&quot; /&gt;
 &lt;/a&gt;
 
  The logging and progress-bar callbacks in a notebook.
 


&lt;p&gt;As of today, the callbacks are implemented in logistic regression (with LBFGS solver), the various *SearchCV objects, Pipeline, StandardScaler. The next releases will progressively add callbacks in more and more estimators (this is a place where contributors can help).&lt;/p&gt;

&lt;h2 id=&quot;improved-statistics-and-numerics&quot;&gt;Improved statistics and numerics&lt;/h2&gt;

&lt;p&gt;As users, what we like about scikit-learn routines is that they tend to
be “fire-and-forget”, because they reliably run on a huge diversity of
inputs: sparse inputs, missing values, different data types. This
diversity of inputs is compounded by a diversity of modeling choices:
different losses, sample weights…&lt;/p&gt;

&lt;p&gt;Each release of scikit-learn extends the toolbox, sometimes by completing
the combinatorial of options and data types rather than adding new
estimators. Release 1.9 was a real consolidation in this respect:&lt;/p&gt;

&lt;h3 id=&quot;tree-based-models&quot;&gt;Tree-based models&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Native missing-value support in RandomForestRegressor when minimizing
the absolute error criterion&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Support of missing-values for tree-based models monotonic constraints&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Improved the statistical correctness of fitting with sample weights in &lt;a href=&quot;https://scikit-learn.org/stable/modules/ensemble.html#histogram-based-gradient-boosting&quot;&gt;HistGradientBoosting&lt;/a&gt;, &lt;a href=&quot;https://scikit-learn.org/stable/modules/ensemble.html#random-forests&quot;&gt;RandomForest&lt;/a&gt; and &lt;a href=&quot;https://scikit-learn.org/stable/modules/ensemble.html#extremely-randomized-trees&quot;&gt;ExtraTree&lt;/a&gt; (having exact support of sample weights in complex pipelines is challenging)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;linear-models&quot;&gt;Linear models&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Logistic regression can use natively float32, thus removing memory pressure&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Multi-Task linear models support fitting on sparse X and sample weights&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;More stable and faster &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.RidgeCV.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RidgeCV&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.RidgeClassifierCV.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RidgeClassifierCV&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Gap safe screening of features for very fast fitting of sparse
squared-loss regressors&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;other-models&quot;&gt;Other models&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Sample weight support in &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.cluster.MiniBatchKMeans.html&quot;&gt;minibatch kmeans&lt;/a&gt; (a very scalable clustering)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Numeric stability of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yeo-johnson&lt;/code&gt; in the &lt;a href=&quot;https://scikit-learn.org/dev/modules/generated/sklearn.preprocessing.PowerTransformer.html#sklearn.preprocessing.PowerTransformer&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preprocessing.PowerTransformer&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Faster &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.manifold.SpectralEmbedding.html&quot;&gt;Spectral embedding&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;staying-up-to-date-with-the-ecosystem&quot;&gt;Staying up to date with the ecosystem&lt;/h3&gt;

&lt;p&gt;Scikit-learn can now return sparse arrays, rather than sparse matrices.
Indeed, scipy is slowly de-emphasizing sparse matrices, which often
surprise users with their behavior that depart from arrays.&lt;/p&gt;

&lt;h2 id=&quot;increasing-support-for-gpu&quot;&gt;Increasing support for GPU&lt;/h2&gt;

&lt;p&gt;Scikit-learn is increasingly gaining support for optimized compute backends, which enables it, for instance, to run on GPUs. The challenge (and the value) is the incredible diversity of estimators and usecases supported by scikit-learn, and the package is progressively adding backend support in more and more places.&lt;br /&gt;
In the 1.9 release, the major features to gain GPU support were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html&quot;&gt;Logistic regression&lt;/a&gt; and &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.PoissonRegressor.html&quot;&gt;Poisson regression&lt;/a&gt; with LBFGS solver&lt;/li&gt;
  &lt;li&gt;More metrics (eg average precision score, …)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.kernel_approximation.Nystroem.html&quot;&gt;Nystroem kernel approximation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href=&quot;https://scikit-learn.org/dev/modules/array_api.html#array-api-support-experimental&quot;&gt;the docs&lt;/a&gt; for all details on how to use the compute backends and which estimator support them.&lt;/p&gt;

&lt;p&gt;PS: the user experience is currently not as good as with the default compute backend (numpy). But adding and improving GPU support (with the “array API”) is a good place for talented volunteers to help move the project forward.&lt;/p&gt;

&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;

&lt;p&gt;Scikit-learn is the work of &lt;a href=&quot;https://scikit-learn.org/stable/about.html#the-people-behind-scikit-learn&quot;&gt;many contributors&lt;/a&gt;, with people volunteering
their time as well as financial sponsors –
see &lt;a href=&quot;https://scikit-learn.org/dev/institutional_support.html#funding&quot;&gt;the funding page&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Fri, 12 Jun 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Talk Python to Me: #551: Stroll Down Startup Lane - 2026</title>
	<guid>https://talkpython.fm/episodes/show/551/stroll-down-startup-lane-2026</guid>
	<link>https://talkpython.fm/episodes/show/551/stroll-down-startup-lane-2026</link>
	<description>If you've ever been to PyCon, you know one of the best parts of the expo hall is Startup Row, a stretch of booths where early-stage companies built on Python show off what they're creating. But only attendees get to walk that lane, so let's bring it to everyone. In this episode, we stroll down Startup Row together. We kick things off with the organizers, Jason and Shay, who share the program's origin story going back to Paul Graham and the PSF, plus some surprising stats, including two unicorns among the alumni. Then we meet five startups: Tetrix, bringing AI to institutional investing in private markets. Arcjet, security that lives inside your app as an SDK. Phemeral.dev, serverless hosting built for Python web apps. CapiscIO, an identity and authority layer for AI agents. And Pixeltable, a multimodal database from Marcel Kornacker, co-creator of Apache Parquet. See if you can spot the theme running through them all. Let's go for a walk.&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode sponsors&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;a href='https://talkpython.fm/agentfield-page'&amp;gt;AgentField AI&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href='https://talkpython.fm/training'&amp;gt;Talk Python Courses&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;h2 class=&quot;links-heading mb-4&quot;&amp;gt;Links from the show&amp;lt;/h2&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Guests&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Naunidh Bhalla&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/naunidhbhalla?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Grant Gittes&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/grantgittes/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Marcel Kornacker&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/marcelkornacker/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Beon de Nood&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/beondenood/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Chinmaya Joshi&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/cshjoshi/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;David Mytton&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/davidmytton/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Shea Tate-Di Donna&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/sheatatedidonna/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Jason Rowley&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/jasondrowley/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Azul Garza&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/AzulGarza?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Renée Rosillo&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.linkedin.com/in/reneerosillo/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;linkedin.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Tetrix&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.tetrix.co/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;tetrix.co&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Tetrix Jobs&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.tetrix.co/careers?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;tetrix.co&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Arcjet&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://arcjet.com/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;arcjet.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Pixeltable&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.pixeltable.com/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;pixeltable.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Phemeral.dev&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://phemeral.dev/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;phemeral.dev&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;CapiscIO&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://capisc.io/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;capisc.io&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode #551 deep-dive&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/episodes/show/551/stroll-down-startup-lane-2026#takeaways-anchor&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm/551&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode transcripts&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/episodes/transcript/551/stroll-down-startup-lane-2026&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Theme Song: Developer Rap&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;🥁 Served in a Flask 🎸&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/flasksong&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm/flasksong&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;---==  Don't be a stranger  ==---&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;YouTube&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/youtube&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-youtube&quot;&amp;gt;&amp;lt;/i&amp;gt; youtube.com/@talkpython&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Bluesky&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://bsky.app/profile/talkpython.fm&quot; target=&quot;_blank&quot; &amp;gt;@talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Mastodon&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://fosstodon.org/web/@talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-mastodon&quot;&amp;gt;&amp;lt;/i&amp;gt; @talkpython@fosstodon.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;X.com&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://x.com/talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-twitter&quot;&amp;gt;&amp;lt;/i&amp;gt; @talkpython&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on Bluesky&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://bsky.app/profile/mkennedy.codes?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;@mkennedy.codes&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on Mastodon&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://fosstodon.org/web/@mkennedy&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-mastodon&quot;&amp;gt;&amp;lt;/i&amp;gt; @mkennedy@fosstodon.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on X.com&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://x.com/mkennedy?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-twitter&quot;&amp;gt;&amp;lt;/i&amp;gt; @mkennedy&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;</description>
	<pubDate>Thu, 11 Jun 2026 20:16:11 +0000</pubDate>
</item>
<item>
	<title>Real Python: Quiz: Serialize Your Data With Python</title>
	<guid>https://realpython.com/quizzes/python-serialize-data/</guid>
	<link>https://realpython.com/quizzes/python-serialize-data/</link>
	<description>&lt;p&gt;In this quiz, you&amp;rsquo;ll test your understanding of
&lt;a href=&quot;https://realpython.com/python-serialize-data/&quot;&gt;Serialize Your Data With Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By working through this quiz, you&amp;rsquo;ll revisit how to choose between textual and binary formats, when to use schemas, and how to apply tools like &lt;code&gt;pickle&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;, the &lt;code&gt;csv&lt;/code&gt; module, Parquet, and Protocol Buffers safely and effectively.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 11 Jun 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>PyCharm: Best Python AI Frameworks in 2026</title>
	<guid>https://blog.jetbrains.com/pycharm/2026/06/best-python-ai-frameworks-in-2026/</guid>
	<link>https://blog.jetbrains.com/pycharm/2026/06/best-python-ai-frameworks-in-2026/</link>
	<description>&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/06/PC-social-BlogFeatured-1280x720-1-1.png&quot; alt=&quot;Best Python AI Frameworks in 2026&quot; class=&quot;wp-image-712585&quot; /&gt;



&lt;p&gt;Whether you’re building chatbots, training computer vision models, or analyzing business data, choosing the right AI framework can make or break your project. Python has become the dominant language for AI and machine learning development, and the ecosystem of frameworks supporting this work has matured significantly.&lt;/p&gt;



&lt;p&gt;The right framework choice depends on what you’re building. A production recommendation system has different requirements than a research prototype. A chatbot powered by large language models (LLMs) needs different tools than a fraud detection system analyzing tabular data.&lt;/p&gt;



&lt;p&gt;Let’s explore seven essential frameworks and where each excels so you can find the best AI framework for your specific project.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;What is an AI framework?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;AI frameworks are pre-built libraries and tools that handle the complex mathematics, data structures, and computational operations underlying AI and machine learning models. Rather than implementing neural networks or gradient descent from scratch, AI frameworks provide abstractions that let you focus on model architecture, data preparation, and business logic.&lt;/p&gt;



&lt;p&gt;These frameworks generally fall into three categories:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deep learning frameworks&lt;/strong&gt; like TensorFlow, PyTorch, and Keras specialize in neural networks and GPU acceleration for tasks involving images, text, and audio.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Classical and tabular machine learning frameworks&lt;/strong&gt; like scikit-learn and XGBoost focus on statistical and tree-based models for structured data, powering many real-world AI systems, including forecasting, risk-scoring, and decision-automation solutions.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;LLM and AI agent frameworks&lt;/strong&gt; like LangChain and Hugging Face provide tools for building applications powered by large language models.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Why do AI frameworks matter?&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;AI frameworks dramatically accelerate your development by providing tested, optimized implementations of complex algorithms. They offer strong community support with extensive documentation, tutorials, and troubleshooting resources. They provide production-ready tooling for deployment, monitoring, and scaling. They&amp;#8217;re optimized for specific hardware like GPUs and TPUs, delivering performance that would be difficult to achieve with custom implementations.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Open-source vs. commercial AI frameworks&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Open-source AI frameworks are the dominant model in AI development today. And they offer compelling advantages, from community-driven innovation for rapid feature development and bug fixes to transparency that enables auditing and algorithm customization. There’s also no vendor lock-in or licensing fees, making them cost-effective for both experimentation and production deployment.&lt;/p&gt;



&lt;p&gt;Commercial AI platforms also exist, with AWS SageMaker, Google Vertex AI, and Azure Machine Learning among the prominent examples. However, these platforms often use open-source frameworks underneath rather than competing with them directly. They provide managed infrastructure, automated workflows, and enterprise features on top of tools like TensorFlow and PyTorch.&lt;/p&gt;



&lt;p&gt;If you’re thinking open source means they’re unsupported, think again. All seven frameworks below have robust ecosystems, and many are backed by major tech companies. Google supports TensorFlow, Meta backs PyTorch, and organizations like Microsoft contribute significantly to various projects in the ecosystem.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Top Python AI frameworks&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;These seven frameworks represent the essential toolkit for Python AI development in 2026. Each performs strongly in specific domains, and many developers use multiple frameworks depending on project requirements.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.tensorflow.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TensorFlow&lt;/a&gt; is an open-source deep learning framework developed by Google for building and deploying machine learning models at enterprise scale. With a&lt;a href=&quot;https://6sense.com/tech/data-science-machine-learning/tensorflow-market-share&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; 37% market share&lt;/a&gt; in data science and machine learning and adoption by 25,000 companies globally, TensorFlow has proven itself in high-stakes production environments.&lt;/p&gt;



&lt;p&gt;The framework evolved significantly from TensorFlow 1.x to 2.x, with Keras integration making it far more accessible while maintaining its enterprise-grade capabilities. If you’re building large-scale image recognition systems or natural language processing pipelines, or you need to deploy across web, mobile, and edge devices through TensorFlow Lite and TensorFlow.js, TensorFlow can help.&lt;/p&gt;



&lt;p&gt;If you’re just getting started with TensorFlow, follow &lt;a href=&quot;https://blog.jetbrains.com/pycharm/2026/04/how-to-train-your-first-tensorflow-model/&quot;&gt;our step-by-step tutorial on how to train your first TensorFlow model&lt;/a&gt; using PyCharm.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of TensorFlow&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enterprise-grade scalability&lt;/strong&gt;: Built for production from day one, TensorFlow handles massive datasets and distributed training across multiple GPUs and TPUs seamlessly. You can scale from experimentation to serving millions of predictions without switching tools.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comprehensive deployment ecosystem&lt;/strong&gt;: TensorFlow Serving handles model deployment, TensorFlow Lite optimizes for mobile and edge devices, and TensorFlow.js brings models to browsers. This complete deployment story reduces friction when moving from development to production.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;TPU optimization&lt;/strong&gt;: Native support for Google’s Tensor Processing Units delivers superior performance for large-scale training workloads, offering significantly better performance per watt than traditional hardware.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Strong industry adoption&lt;/strong&gt;: Companies like Airbnb, Twitter, and Intel rely on TensorFlow for critical applications, giving you confidence in its production readiness and long-term viability.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of TensorFlow&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Steeper learning curve&lt;/strong&gt;: Despite Keras integration, TensorFlow’s complexity can overwhelm beginners, especially when you move beyond high-level APIs to custom implementations.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Verbose syntax for custom models&lt;/strong&gt;: Building custom training loops or novel architectures requires significantly more code compared with PyTorch’s more Pythonic approach.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Debugging challenges&lt;/strong&gt;: Static graph optimization, while beneficial for performance, can make runtime errors harder to trace than in frameworks with dynamic computation graphs.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;scikit-learn&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://scikit-learn.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;scikit-learn&lt;/a&gt; is an open-source Python library for classical machine learning, providing simple and efficient tools for classification, regression, clustering, and dimensionality reduction. With adoption by&lt;a href=&quot;https://6sense.com/tech/data-science-and-machine-learning/scikit-learn-market-share&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; over 16,000 companies&lt;/a&gt; worldwide, it’s your essential first stop for structured and tabular data before considering deep learning approaches.&lt;/p&gt;



&lt;p&gt;The framework supports a wide range of supervised and unsupervised learning on structured business data, along with feature engineering and data preprocessing pipelines. Companies like&lt;a href=&quot;https://scikit-learn.org/stable/testimonials/testimonials.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; J.P. Morgan use scikit-learn extensively&lt;/a&gt; for classification tasks and predictive analytics in financial decision-making.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of scikit-learn&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beginner-friendly API&lt;/strong&gt;: Consistent, intuitive syntax across all algorithms makes learning and switching between models effortless. The fit/predict pattern works the same whether you&amp;#8217;re using linear regression or random forests.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comprehensive algorithm library&lt;/strong&gt;: Its library covers virtually every classical ML algorithm – regression, classification, clustering, dimensionality reduction – with well-tested implementations ready for your projects.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Excellent for tabular data&lt;/strong&gt;: On structured data, traditional algorithms often outperform deep learning, and scikit-learn gives you the tools to maximize this advantage.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Fast prototyping&lt;/strong&gt;: Its simple syntax means you can build and test models in minutes, not hours, making it ideal for rapid experimentation.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Seamless integration&lt;/strong&gt;: scikit-learn works perfectly with NumPy, pandas, and Matplotlib, fitting naturally into your data science workflows.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of scikit-learn&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No deep learning support&lt;/strong&gt;: scikit-learn is not designed for neural networks – you’ll need to switch to TensorFlow or PyTorch for complex deep learning architectures.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Limited GPU acceleration&lt;/strong&gt;: The framework is CPU-bound and struggles with very large datasets where GPU-accelerated frameworks perform better.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Not suited for unstructured data&lt;/strong&gt;: Images, text, and audio require deep learning frameworks that can handle high-dimensional, unstructured inputs.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://pytorch.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PyTorch&lt;/a&gt; is an open-source deep learning framework developed by Meta that prioritizes flexibility and a natural Python coding experience. It’s used in&lt;a href=&quot;https://leapcell.io/blog/tensorflow-vs-pytorch-a-comparative-analysis-for-2025&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; approximately 85% of deep learning research papers&lt;/a&gt; and has a 55% adoption rate in the research community. From its academic roots, PyTorch has evolved into a production-ready powerhouse.&lt;/p&gt;



&lt;p&gt;The framework excels at cutting-edge research and experimentation with novel architectures. It supports natural language processing and generative AI models such as GPT, Llama, and Stable Diffusion, and enables computer vision research with custom model development. Its Pythonic philosophy makes it feel natural if you’re already comfortable with Python, reducing cognitive load and accelerating your development.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of PyTorch&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic computation graphs&lt;/strong&gt;: The define-by-run approach allows runtime model modifications, making debugging and experimentation intuitive. You can use standard Python control flow and debugging tools you already know.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Pythonic and readable&lt;/strong&gt;: PyTorch code feels like native Python, not a separate language. This flattens your learning curve and makes code more maintainable.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Research-first innovation&lt;/strong&gt;: Latest techniques and models appear in PyTorch first, driven by its dominance in academic research.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Strong ecosystem&lt;/strong&gt;: Hugging Face Transformers, PyTorch Lightning, and extensive community packages provide specialized tools for virtually any task you’ll encounter.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of PyTorch&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deployment complexity&lt;/strong&gt;: While TorchServe has improved the situation, PyTorch historically has had weaker production tooling compared to TensorFlow’s mature deployment ecosystem.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Manual training loops&lt;/strong&gt;: Greater control means more boilerplate code for standard training patterns, though libraries like PyTorch Lightning address this.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Keras&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://keras.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Keras&lt;/a&gt; is a high-level deep learning API designed for fast experimentation with neural networks. With&lt;a href=&quot;https://github.com/keras-team/keras&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; over 60,000 GitHub stars&lt;/a&gt; and integration as TensorFlow’s default interface, Keras has become synonymous with rapid prototyping and ease of use. The release of Keras 3.0 changed the game by adding multi-backend support for TensorFlow, JAX, and PyTorch.&lt;/p&gt;



&lt;p&gt;The framework is ideal for rapidly prototyping neural network architectures, working on educational projects to learn deep learning fundamentals, or tackling deep learning tasks that don’t require low-level customization.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of Keras&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Simplest API in deep learning&lt;/strong&gt;: You can build sophisticated models in just a few lines of code with the Sequential or Functional API, offering the lowest barrier to entry in deep learning.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Multi-backend flexibility&lt;/strong&gt;: Keras 3.0 runs on TensorFlow, JAX, or PyTorch – write once, run anywhere. This future-proofs your code and lets you switch backends as your needs change.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Built-in best practices&lt;/strong&gt;: The API guides you toward sound model architecture decisions and incorporates best practices by default.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Fast experimentation&lt;/strong&gt;: You can iterate quickly without wrestling with framework complexity, focusing on model design rather than implementation details.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of Keras&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited low-level control&lt;/strong&gt;: The abstraction layer sacrifices fine-grained control needed for cutting-edge research or novel architectures.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Performance overhead&lt;/strong&gt;: The additional abstraction can introduce latency compared to native framework calls, though this is often negligible for most applications.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Less suitable for custom architectures&lt;/strong&gt;: Highly novel model designs may require you to drop down to the underlying framework.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;LangChain&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.langchain.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;LangChain&lt;/a&gt; is an open-source framework that helps you build applications powered by large language models, providing core components for prompt management, chains, memory, and agent orchestration. It acts as an abstraction layer to easily connect LLMs to external data sources and computational tools. With over &lt;a href=&quot;https://github.com/langchain-ai/langchain&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;120,000 GitHub stars&lt;/a&gt;, the framework has become essential infrastructure for the AI agent revolution.&lt;/p&gt;



&lt;p&gt;LangChain is most commonly used for building conversational AI and chatbots with memory and context, retrieval-augmented generation (RAG) systems for enterprise knowledge bases, and multi-agent systems with autonomous workflows.&lt;/p&gt;



&lt;p&gt;If you want to go beyond the basics, read our &lt;a href=&quot;https://blog.jetbrains.com/pycharm/2026/02/langchain-tutorial-2026/&quot;&gt;&lt;em&gt;LangChain Python Tutorial: A Complete Guide for 2026&lt;/em&gt;&lt;/a&gt;. It takes a deeper look at what LangChain offers and walks through real-world use cases for building AI agents in Python.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of LangChain&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Comprehensive LLM orchestration&lt;/strong&gt;: Handles everything from prompt management to chains, memory, and tool use, giving you a complete infrastructure for LLM applications in one package.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Provider-agnostic&lt;/strong&gt;: Works seamlessly with OpenAI, Anthropic, Hugging Face, and local models, letting you avoid vendor lock-in and switch providers as your needs change.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Rich agent capabilities&lt;/strong&gt;: LangGraph enables complex, stateful workflows with human-in-the-loop patterns, supporting sophisticated agentic behaviors.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Production-ready tooling&lt;/strong&gt;: LangSmith provides monitoring, debugging, and tracing specifically designed for LLM applications, addressing the unique challenges you’ll face in production.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of LangChain&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learning curve for abstractions&lt;/strong&gt;: LangChain Expression Language (LCEL) and framework-specific concepts take time to master, especially if you’re new to LLM orchestration.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Abstraction overhead&lt;/strong&gt;: Additional layers between you and LLM APIs can sometimes obscure what’s happening, making debugging more challenging.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Fast-moving target&lt;/strong&gt;: Frequent updates mean your code can become outdated quickly, requiring ongoing maintenance to stay current.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Hugging Face&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://huggingface.co/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hugging Face&lt;/a&gt; is an open-source platform and library ecosystem for natural language processing and machine learning, with over one million models and 250,000 datasets to power your next project. It’s become a central hub for the AI community, with its &lt;a href=&quot;https://github.com/huggingface/transformers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Transformers library earning 150,000+ GitHub stars&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;The platform is particularly effective at accessing and fine-tuning pre-trained transformer models like BERT, GPT, and Llama, building NLP applications without training models from scratch, and sharing and deploying custom models to the community.&lt;/p&gt;



&lt;p&gt;For a practical example, read &lt;a href=&quot;https://blog.jetbrains.com/pycharm/2025/08/fine-tuning-and-deploying-gpt-models-using-hugging-face-transformers/&quot;&gt;&lt;em&gt;A Practical Guide to Fine-Tuning and Deploying GPT Models Using Hugging Face Transformers&lt;/em&gt;&lt;/a&gt;. It walks through using a pre-trained GPT model, fine-tuning it on custom data, and deploying the result with FastAPI.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of Hugging Face&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Massive model repository&lt;/strong&gt;: With hundreds of thousands of pre-trained models available, you rarely need to train from scratch. Models for virtually every task and language are ready for you to use.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Transformers library dominance&lt;/strong&gt;: This is the de facto standard for NLP, computer vision, and multimodal models, with support for the latest architectures as soon as they’re published.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Framework interoperability&lt;/strong&gt;: Models work with PyTorch, TensorFlow, and JAX, giving you maximum flexibility in your development workflow.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Inference infrastructure&lt;/strong&gt;: Hosted inference APIs and Spaces make deployment straightforward without managing your own infrastructure.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of Hugging Face&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dependency complexity&lt;/strong&gt;: The large dependency tree can lead to version conflicts and package management challenges, especially in complex environments.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Model quality variance&lt;/strong&gt;: Community-contributed models vary in quality and may not be production-ready without thorough vetting and testing on your part.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Platform dependency&lt;/strong&gt;: Heavy reliance on Hugging Face Hub creates some platform lock-in, though you can download models and host them independently.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;XGBoost&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://xgboost.readthedocs.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;XGBoost&lt;/a&gt; is an optimized gradient boosting library designed for speed and performance on structured data. The algorithm continues to dominate machine learning competitions alongside other gradient-boosted decision tree libraries, earning its reputation through battle-tested performance on real-world problems.&lt;/p&gt;



&lt;p&gt;You can use the framework for predictive modeling on structured business data, including sales forecasting, risk assessment, and feature importance analysis for model interpretability. Its gradient-boosting approach achieves outstanding precision on structured data, powering reliable insights for business applications.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Advantages of XGBoost&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Superior accuracy on tabular data&lt;/strong&gt;: XGBoost consistently outperforms deep learning on structured datasets, making it your default choice for business analytics and forecasting.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Built-in regularization&lt;/strong&gt;: L1 and L2 regularization prevents overfitting better than basic gradient boosting, producing more robust models for your production systems.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Efficient computation&lt;/strong&gt;: Handles large datasets efficiently with parallel processing and intelligent tree pruning, making it practical for production use.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Missing value handling&lt;/strong&gt;: Automatically learns optimal strategies for missing data, reducing your preprocessing burden.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Feature importance scores&lt;/strong&gt;: Built-in interpretability helps you understand model decisions, crucial for business applications and regulatory compliance.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Disadvantages of XGBoost&lt;/h4&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Not suitable for unstructured data&lt;/strong&gt;: Images, text, and audio require deep learning approaches. XGBoost is designed specifically for tabular data.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Hyperparameter complexity&lt;/strong&gt;: There are many parameters to tune for optimal performance, though tools like Optuna can automate this process for you.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Limited interpretability compared with simple models&lt;/strong&gt;: While more explainable than deep neural networks, XGBoost’s ensemble structure is harder to interpret than linear or rule-based models, even with feature importance and SHAP analysis.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;How to choose an AI framework&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Selecting the best AI framework depends on your specific project characteristics, but in practice, the choice is rarely binary. Many successful teams use multiple frameworks together. A common and effective pattern is to use scikit-learn for preprocessing and feature engineering, PyTorch for research and model development, TensorFlow for production deployment, and LangChain for LLM-powered features.&lt;/p&gt;



&lt;p&gt;Your decision will likely come down to data type, team expertise, and where your model needs to run. Use this table as a starting point:&lt;/p&gt;



&lt;table class=&quot;has-black-color has-text-color&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Decision factor&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Suitable Frameworks&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;By modeling approach and prediction type&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Single-value or label prediction (regression or classification using classical ML)&lt;/td&gt;&lt;td&gt;scikit-learn, XGBoost&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Image and video modeling with neural networks&lt;/td&gt;&lt;td&gt;TensorFlow, PyTorch, Keras&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Text and NLP with transformer models&lt;/td&gt;&lt;td&gt;Hugging Face, PyTorch, TensorFlow&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLM-powered and agent-based applications&lt;/td&gt;&lt;td&gt;LangChain, Hugging Face&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;By level of abstraction and control required&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-level APIs and rapid iteration&lt;/td&gt;&lt;td&gt;Keras, scikit-learn&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fine-grained control over training and architectures&lt;/td&gt;&lt;td&gt;PyTorch, TensorFlow&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Research-driven experimentation and custom workflows&lt;/td&gt;&lt;td&gt;PyTorch&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Managed LLM orchestration and tooling&lt;/td&gt;&lt;td&gt;LangChain&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;By deployment target&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Production at scale&lt;/td&gt;&lt;td&gt;TensorFlow&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Research/Experimentation&lt;/td&gt;&lt;td&gt;PyTorch&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Mobile/Edge&lt;/td&gt;&lt;td&gt;TensorFlow Lite&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Web applications&lt;/td&gt;&lt;td&gt;TensorFlow.js&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLM applications&lt;/td&gt;&lt;td&gt;LangChain&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;By task and project objective&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Classical prediction and forecasting systems&lt;/td&gt;&lt;td&gt;scikit-learn, XGBoost&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Neural network–based modelling&lt;/td&gt;&lt;td&gt;TensorFlow, PyTorch, Keras&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Building and training novel architectures&lt;/td&gt;&lt;td&gt;PyTorch&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Scalable production deployment&lt;/td&gt;&lt;td&gt;TensorFlow&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLM-powered features and workflows&lt;/td&gt;&lt;td&gt;LangChain, Hugging Face&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;



&lt;p&gt;If your choice comes down to PyTorch or TensorFlow, read our dedicated &lt;a href=&quot;https://blog.jetbrains.com/pycharm/2026/05/pytorch-vs-tensorflow-choosing-framework-2026/&quot;&gt;&lt;em&gt;PyTorch vs. TensorFlow: Choosing the Right Framework in 2026&lt;/em&gt;&lt;/a&gt; guide, where we compare learning curves, deployment options, and use cases to help you choose the right deep learning framework.&lt;/p&gt;</description>
	<pubDate>Thu, 11 Jun 2026 11:28:08 +0000</pubDate>
</item>
<item>
	<title>Seth Michael Larson: Linting is important for code review: screen included</title>
	<guid>https://sethmlarson.dev/linting-screen-during-code-review?utm_campaign=rss</guid>
	<link>https://sethmlarson.dev/linting-screen-during-code-review?utm_campaign=rss</link>
	<description>&lt;p&gt;Today I was reviewing a pull request for some Python code
when I saw a semicolon in the diff.
&lt;!-- more --&gt;
Screenshot
provided below, which as we all know is the best way to share
text on the internet:&lt;/p&gt;

&lt;p&gt;
&lt;center&gt;
&lt;img alt=&quot;Picture of code with a semicolon (;)&quot; src=&quot;https://storage.googleapis.com/sethmlarson-dev-static-assets/IMG_5329_small.jpeg&quot; /&gt;
&lt;br /&gt;&lt;small&gt;&lt;em&gt;&lt;/em&gt;&lt;/small&gt;
&lt;/center&gt;
&lt;/p&gt;

&lt;p&gt;I was just about to leave a comment, but then I scrolled the page a bit and... &lt;/p&gt;

&lt;p&gt;
&lt;center&gt;
&lt;img alt=&quot;Same picture of code, but the dot on top of the semicolon has shifted away revealing it is only a piece of dirt on the screen above a comma (,)&quot; src=&quot;https://storage.googleapis.com/sethmlarson-dev-static-assets/IMG_5332_small.jpeg&quot; /&gt;
&lt;br /&gt;&lt;small&gt;&lt;em&gt;&lt;/em&gt;&lt;/small&gt;
&lt;/center&gt;
&lt;/p&gt;

&lt;p&gt;Ah. Time to clean my laptop screen then... 🧼🫧&lt;/p&gt;
&lt;br /&gt;&lt;hr /&gt;&lt;p&gt;Thanks for reading ♥ I would love to hear your thoughts! Contact me via &lt;a href=&quot;https://mastodon.social/@sethmlarson&quot;&gt;Mastodon&lt;/a&gt;, &lt;a href=&quot;https://bsky.app/profile/sethmlarson.dev&quot;&gt;Bluesky&lt;/a&gt;, or &lt;a href=&quot;mailto:sethmichaellarson@gmail.com&quot;&gt;email&lt;/a&gt;. Browse the &lt;a href=&quot;https://sethmlarson.dev/&quot;&gt;blog archive&lt;/a&gt;. Check out my &lt;a href=&quot;https://sethmlarson.dev/blogroll&quot;&gt;blogroll&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;br /&gt;</description>
	<pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Django Weblog: DSF 2026 Fundraising Goals</title>
	<guid>https://www.djangoproject.com/weblog/2026/jun/10/dsf-2026-fundraising-goals/</guid>
	<link>https://www.djangoproject.com/weblog/2026/jun/10/dsf-2026-fundraising-goals/</link>
	<description>&lt;p&gt;Django has grown far beyond a web framework. It powers businesses, nonprofits, startups, educational institutions, and critical infrastructure around the world. The Django Software Foundation exists to support that ecosystem, and none of that work is possible without funding. This year, the board set an ambitious new fundraising goal, and I want to be transparent about what we are aiming for and why it matters.&lt;/p&gt;
&lt;p&gt;Before talking about where we want to go, it's important to recognize that everything the DSF does today is possible because of the organizations and individuals who already support Django. Their contributions fund the work that keeps Django healthy, secure, and sustainable, and we are deeply grateful for that support. &lt;/p&gt;
&lt;h2 id=&quot;s-our-2026-goal-500000&quot;&gt;&lt;strong&gt;Our 2026 Goal: $500,000&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This year, we are raising our annual fundraising goal from $300,000 to $500,000.&lt;/p&gt;
&lt;p&gt;That is a meaningful increase, and it reflects where the foundation needs to be. To reach this goal, we need to raise an additional $16,000 per month in recurring support.&lt;/p&gt;
&lt;p&gt;Reaching this goal will require both new supporters and increased support from existing donors. Doing so will help us maintain the programs the community relies on while creating room for future growth.&lt;/p&gt;
&lt;h2 id=&quot;s-what-the-money-funds&quot;&gt;&lt;strong&gt;What the Money Funds&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Before asking for support, it is only fair to explain where the money goes.&lt;/p&gt;
&lt;p&gt;The largest line item in our budget is the &lt;a href=&quot;https://www.djangoproject.com/fundraising/#fellowship-program&quot;&gt;Django Fellows program&lt;/a&gt;. Our three Fellows dedicate their time to triaging tickets, reviewing pull requests, managing releases, handling security issues, and doing the essential work that keeps Django moving forward. Without sustained funding, we cannot maintain this program.&lt;/p&gt;
&lt;p&gt;Beyond the Fellows, the DSF:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manages the Django trademark and legal protections  &lt;/li&gt;
&lt;li&gt;Funds the infrastructure that keeps djangoproject.com and related services running  &lt;/li&gt;
&lt;li&gt;Provides grants to DjangoCon events around the world, including DjangoCon US, DjangoCon Europe, and DjangoCon Africa  &lt;/li&gt;
&lt;li&gt;Funds regional Django Days, sprints, and community events  &lt;/li&gt;
&lt;li&gt;Supports Django Girls events through grants  &lt;/li&gt;
&lt;li&gt;Invests in community programs like Djangonaut Space&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Taken together, $500,000 in annual funding would allow us to sustain our three Fellows, maintain operational support for the DSF, create a clear path to hiring an Executive Director, and expand our ability to support the Django ecosystem at scale.&lt;/p&gt;
&lt;h2 id=&quot;s-hiring-an-executive-director&quot;&gt;Hiring an Executive Director&lt;/h2&gt;
&lt;p&gt;For most of its history, the DSF has been powered almost entirely by volunteers, with board members handling fundraising, grants, trademarks, and operations on top of their day jobs. That commitment has carried the foundation a long way, but it also limits how much we can take on.&lt;/p&gt;
&lt;p&gt;That is why we are working toward hiring an Executive Director this year. An Executive Director would give the foundation dedicated, day-to-day leadership: someone who can build lasting relationships with sponsors, grow our fundraising programs, strengthen support for our volunteers and working groups, and turn the board's long-term plans into steady progress.&lt;/p&gt;
&lt;p&gt;We are optimistic about what this role would unlock. With dedicated operational support, the DSF could pursue larger partnerships, launch new programs, and respond more quickly to the community's needs. Reaching our fundraising goal is a key part of making that a reality.&lt;/p&gt;
&lt;h2 id=&quot;s-ways-to-support-django&quot;&gt;&lt;strong&gt;Ways to Support Django&lt;/strong&gt;&lt;/h2&gt;
&lt;h3 id=&quot;s-sponsored-fellow-the-highest-impact-way-to-support-django&quot;&gt;&lt;strong&gt;Sponsored Fellow: The Highest-Impact Way to Support Django&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This year, the DSF is introducing a Sponsored Fellow corporate membership tier, a new way for organizations to make a direct, visible investment in Django's future.&lt;/p&gt;
&lt;p&gt;As a Sponsored Fellow sponsor, your company directly funds one of the Django Fellows who keep the framework running every day. In return, you receive the highest level of recognition the DSF offers. Depending on the partnership, that can include your company's logo and information featured in Django release announcements, recognition through the Fellows' work at conferences and community events, advertising opportunities across DSF communications, and visibility across DSF publications and promotional materials throughout the year.&lt;/p&gt;
&lt;p&gt;Django releases reach tens of thousands of developers. The Fellows represent Django at DjangoCon events around the world. If you want your company's name and logo in front of the global Django community, this is the most direct path to get there.&lt;/p&gt;
&lt;p&gt;This tier is designed for organizations that depend on Django at scale and want to do more than write a check. It is a partnership, and we will work with you to make sure your sponsorship is visible and meaningful.&lt;/p&gt;
&lt;p&gt;To learn more or start a conversation about the Sponsored Fellow tier, reach out through our &lt;a href=&quot;https://www.djangoproject.com/sponsor/&quot;&gt;Contact the DSF&lt;/a&gt; page.&lt;/p&gt;
&lt;h3 id=&quot;s-corporate-membership&quot;&gt;&lt;strong&gt;Corporate Membership&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Corporate membership is a proven way for organizations to support the DSF. Tiers range from Bronze at $2,000 per year up to Platinum at $150,000 per year. Member organizations receive recognition on djangoproject.com, benefits in our community channels, and the knowledge that they are directly funding the framework their teams depend on.&lt;/p&gt;
&lt;p&gt;To learn more or get started, visit &lt;a href=&quot;https://www.djangoproject.com/foundation/corporate-membership/&quot;&gt;djangoproject.com/foundation/corporate-membership/&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;s-individual-donations&quot;&gt;&lt;strong&gt;Individual Donations&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Individual donations add up. Whether it is a one-time gift or a small monthly contribution, every bit helps us reach our monthly target and plan ahead with more confidence.&lt;/p&gt;
&lt;p&gt;You can donate via our &lt;a href=&quot;https://www.djangoproject.com/fundraising/&quot;&gt;donate page&lt;/a&gt; or through &lt;a href=&quot;https://opencollective.com/django&quot;&gt;Open Collective&lt;/a&gt;, which we added last year to make recurring donations easier.&lt;/p&gt;
&lt;h3 id=&quot;s-employer-donation-matching&quot;&gt;&lt;strong&gt;Employer Donation Matching&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Many companies offer donation matching programs that can double or even triple the impact of an individual contribution. If your employer has a matching program, the DSF is typically eligible. Check with your HR or finance team and put that benefit to work.&lt;/p&gt;
&lt;h3 id=&quot;s-github-sponsors&quot;&gt;&lt;strong&gt;GitHub Sponsors&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;We have also raised our &lt;a href=&quot;https://github.com/sponsors/django&quot;&gt;GitHub Sponsors&lt;/a&gt; goal to $15,000 per month to better reflect the level of ongoing support Django needs. We are currently over $9,000 per month, so we are well on our way, but there is still ground to cover. If you already sponsor Django through GitHub, thank you. If you have been thinking about it, now is a great time to start.&lt;/p&gt;
&lt;p&gt;Thanks to all our existing sponsors and donors, Django has been able to sustain community initiatives over the past several years.&lt;/p&gt;
&lt;h3 id=&quot;s-spread-the-word&quot;&gt;&lt;strong&gt;Spread the Word&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;If you cannot contribute financially right now, you can still help by spreading the word. Share this post. Mention Django's funding needs the next time someone asks how to give back to open source. Tell your employer about corporate membership.&lt;/p&gt;
&lt;h2 id=&quot;s-a-note-on-transparency&quot;&gt;&lt;strong&gt;A Note on Transparency&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We publish monthly balance snapshots in our &lt;a href=&quot;https://github.com/django/dsf-minutes&quot;&gt;board minutes&lt;/a&gt;. The foundation started 2026 with around $222,000 in operating reserves. We take stewardship of those funds seriously, and you should always be able to see where we stand. Those reserves help ensure continuity of operations and provide financial stability for the foundation's ongoing commitments.&lt;/p&gt;
&lt;h2 id=&quot;s-looking-ahead&quot;&gt;&lt;strong&gt;Looking Ahead&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;A significant portion of our funding comes directly from the community through individual donations, memberships, sponsorships, and fundraising campaigns. That ongoing support is one of the clearest signals that Django still matters to the people who build with it every day, and we are deeply grateful for it.&lt;/p&gt;
&lt;p&gt;Every Django release, security advisory, ticket review, and mentoring interaction represents countless hours of work from people who care deeply about the framework and community. The DSF exists to make sure that work remains sustainable and that contributors have the support they need to keep Django healthy for everyone who depends on it.&lt;/p&gt;
&lt;p&gt;Raising our goal is not about growth for growth's sake. It is about stability, sustainability, and making sure the project, the Fellows, and the broader community have what they need for the years ahead.&lt;/p&gt;
&lt;p&gt;We believe $500,000 is achievable. If you have ever benefited from Django, professionally or personally, now is a great time to give back.&lt;/p&gt;
&lt;p&gt;Thank you for being part of this community.&lt;/p&gt;</description>
	<pubDate>Wed, 10 Jun 2026 20:00:00 +0000</pubDate>
</item>
<item>
	<title>Mike Driscoll: How to Get TIFF MetaData with Python</title>
	<guid>https://blog.pythonlibrary.org/2026/06/10/how-to-get-tiff-metadata-with-python/</guid>
	<link>https://blog.pythonlibrary.org/2026/06/10/how-to-get-tiff-metadata-with-python/</link>
	<description>&lt;p&gt;In previous &lt;a href=&quot;https://blog.pythonlibrary.org/2010/03/28/getting-photo-metadata-exif-using-python/&quot;&gt;articles&lt;/a&gt; on this website, you learned how to extract EXIF data from JPG image files. This week, you will learn how to get similar data from the TIFF image format.&lt;/p&gt;
&lt;p&gt;The TIFF format also has its metadata. Pillow provides a similar dictionary for TIFF images in its &lt;code&gt;TiffTags&lt;/code&gt; module. If you need a TIFF image, you can use this one, which is a cover from one of the author&amp;#8217;s other books on &lt;strong&gt;ReportLab&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;aligncenter size-full wp-image-12796&quot; src=&quot;https://blog.pythonlibrary.org/wp-content/uploads/2026/06/reportlab.png&quot; alt=&quot;ReportLab cover&quot; width=&quot;546&quot; height=&quot;762&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can create your own TIFF metadata extractor utility by making a new file named &lt;code&gt;tiff_metadata.py&lt;/code&gt; and adding this code to it:&lt;/p&gt;
&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;# tiff_metadata.py

from PIL import Image
from PIL.TiffTags import TAGS


def get_metadata(image_file_path):
    image = Image.open(image_file_path)
    metadata = {}
    for tag in image.tag.items():
        metadata[TAGS.get(tag[0])] = tag[1]
    return metadata


if __name__ == &quot;__main__&quot;:
    metadata = get_metadata(&quot;reportlab_cover.tiff&quot;)
    print(metadata)&lt;/pre&gt;
&lt;p dir=&quot;auto&quot;&gt;Here you import the &lt;code&gt;TAGS&lt;/code&gt; dictionary from the &lt;code&gt;PIL.TiffTags&lt;/code&gt; submodule. Then in &lt;code&gt;get_metadata()&lt;/code&gt;, you access the tag elements in the image by iterating over the contents of &lt;code&gt;tag.items()&lt;/code&gt;. To make that information more readable, you use the &lt;code&gt;TAGS&lt;/code&gt; dictionary that you imported.&lt;/p&gt;
&lt;p dir=&quot;auto&quot;&gt;Here is a sample of the output you will get when you run this code:&lt;/p&gt;
&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;{'ImageWidth': (400,),
 'ImageLength': (562,),
 'BitsPerSample': (8, 8, 8),
 'Compression': (1,),
 'PhotometricInterpretation': (2,),
 'FillOrder': (1,),
 'StripOffsets': (82, 130882, 261682, 392482, 523282, 654082),
 'Orientation': (1,),
 'SampleFormat': (1, 1, 1),
 'SamplesPerPixel': (3,),
 'RowsPerStrip': (109,),
 'StripByteCounts': (130800, 130800, 130800, 130800, 130800, 20400),
 'XResolution': ((300, 1),),
 'YResolution': ((300, 1),),
 'PlanarConfiguration': (1,),
 'ResolutionUnit': (2,),
 'ExifIFD': (8,),
 'Software': ('Pixelmator 3.9',),
 'DateTime': ('2020:10:27 12:10:37',),
}&lt;/pre&gt;
&lt;p&gt;You can see that the value entries above are all tuples. This is because of how the data is returned from the tag data. If you would like a challenge, you can attempt to clean up this data a bit in your version of the metadata extraction utility.&lt;/p&gt;
&lt;h2 class=&quot;header-anchor-post&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;div class=&quot;pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent&quot;&gt;
&lt;div class=&quot;pencraft pc-display-contents pc-reset pubTheme-yiXxQA&quot;&gt;
&lt;div id=&quot;§wrapping-up&quot; class=&quot;pencraft pc-reset header-anchor offset-top&quot;&gt;&lt;span&gt;EXIF and TIFF metadata are really useful for encoding lots of information in your images. However, most people don’t even know that data is there! Knowing how to access your photo’s metadata allows you to do all kinds of programmatic tasks, such as resizing, sorting files by various parameters, and much more.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can use Pillow and Python to do all kinds of other image processing, so this is just scratching the surface. Download Pillow today and start learning!&lt;/p&gt;
&lt;h2 class=&quot;header-anchor-post&quot;&gt;&lt;strong&gt;Want to Learn More?&lt;/strong&gt;&lt;/h2&gt;
&lt;div class=&quot;pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent&quot;&gt;
&lt;div class=&quot;pencraft pc-display-contents pc-reset pubTheme-yiXxQA&quot;&gt;&lt;span&gt;You can learn more about what you can do with Python and Pillow in Mike’s book, &lt;/span&gt;&lt;strong&gt;Pillow: Image Processing with Python&lt;/strong&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Purchase at &lt;a href=&quot;https://driscollis.gumroad.com/l/pypillow&quot;&gt;Gumroad&lt;/a&gt;, &lt;a href=&quot;https://leanpub.com/pillow&quot;&gt;Leanpub&lt;/a&gt;, or &lt;a href=&quot;https://amzn.to/3ZvLfav&quot;&gt;Amazon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The post &lt;a href=&quot;https://blog.pythonlibrary.org/2026/06/10/how-to-get-tiff-metadata-with-python/&quot;&gt;How to Get TIFF MetaData with Python&lt;/a&gt; appeared first on &lt;a href=&quot;https://blog.pythonlibrary.org&quot;&gt;Mouse Vs Python&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Wed, 10 Jun 2026 19:15:42 +0000</pubDate>
</item>

</channel>
</rss>
