<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Python Developer Tooling Handbook – Python Tooling Explained</title>
    <link>https://pydevtools.com/handbook/explanation/</link>
    <description>Background and context articles that explain the why behind Python tools, packaging standards, and ecosystem decisions.</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Mon, 27 Apr 2026 11:32:36 -0400</lastBuildDate>
    
	  <atom:link href="https://pydevtools.com/handbook/explanation/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>uv: A Complete Guide to Python&#39;s Fastest Package Manager</title>
      <link>https://pydevtools.com/handbook/explanation/uv-complete-guide/</link>
      <pubDate>Mon, 04 May 2026 08:09:53 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/uv-complete-guide/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; replaces a half-dozen traditional Python tools with a single binary: interpreter installation, virtual environments, dependency management, version locking, CLI tools, and code formatting. In benchmarks, it creates virtual environments 50x faster than &lt;code&gt;python -m venv&lt;/code&gt; and installs packages 5-40x faster than pip depending on cache state.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;Note&lt;/p&gt;</description>
    </item>
    <item>
      <title>ty: A Complete Guide to Python&#39;s Fastest Type Checker</title>
      <link>https://pydevtools.com/handbook/explanation/ty-complete-guide/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/ty-complete-guide/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/ty/&#34;&gt;ty&lt;/a&gt; is a Python type checker and language server built by Astral, the team behind &lt;a href=&#34;https://pydevtools.com/handbook/reference/ruff/&#34;&gt;Ruff&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt;. It checks Python code for type errors an order of magnitude faster than &lt;a href=&#34;https://pydevtools.com/handbook/reference/mypy/&#34;&gt;mypy&lt;/a&gt;. The same binary that runs &lt;code&gt;ty check&lt;/code&gt; in CI also serves as a full language server, powering editor features like completions and go-to-definition.&lt;/p&gt;
&lt;h2&gt;Why ty exists&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;why-ty-exists&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#why-ty-exists&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ty&amp;rsquo;s &lt;strong&gt;gradual guarantee&lt;/strong&gt; makes incremental type adoption safe: adding annotations to your code will never introduce new errors. You can annotate a function&amp;rsquo;s return type and ty won&amp;rsquo;t flag callers that were already passing the wrong type just because the annotation appeared. Each annotation only narrows existing errors rather than creating new ones.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ruff: A Complete Guide to Python&#39;s Fastest Linter and Formatter</title>
      <link>https://pydevtools.com/handbook/explanation/ruff-complete-guide/</link>
      <pubDate>Wed, 06 May 2026 06:22:32 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/ruff-complete-guide/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/ruff/&#34;&gt;Ruff&lt;/a&gt; replaces flake8, &lt;a href=&#34;https://pydevtools.com/handbook/reference/black/&#34;&gt;Black&lt;/a&gt;, isort, pyupgrade, pydocstyle, and dozens of other Python code quality tools with a single binary. It re-implements over 1,000 lint rules from dozens of existing tools and runs 10-100x faster than the tools it replaces.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://astral.sh&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Astral&lt;/a&gt; (the team behind &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/ty/&#34;&gt;ty&lt;/a&gt;) builds and maintains Ruff.&lt;/p&gt;
&lt;h2&gt;Why Ruff exists&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;why-ruff-exists&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#why-ruff-exists&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ruff gives Python developers a single tool for linting, formatting, import sorting, and code modernization. One dev dependency, one configuration section in &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyproject.toml/&#34;&gt;pyproject.toml&lt;/a&gt;, one CI step. It ships as a standalone binary with no runtime dependencies, so installation is fast and there are no version conflicts to manage.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Claude Code for Python: A Complete Guide</title>
      <link>https://pydevtools.com/handbook/explanation/claude-code-complete-guide/</link>
      <pubDate>Wed, 06 May 2026 06:23:27 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/claude-code-complete-guide/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://code.claude.com/docs/en/overview&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Claude Code&lt;/a&gt; is a terminal-based AI assistant that reads your files, runs commands, edits code, and iterates on errors. Describe what you want in plain English, and Claude Code determines which files to read, which commands to run, and what code to write. When something breaks, it reads the error, adjusts, and tries again.&lt;/p&gt;
&lt;p&gt;This guide covers how to use Claude Code for Python development specifically. Each section is self-contained, so skip to whatever is relevant.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Doesn&#39;t the Authoritative Python Packaging Guide Mention the Best Thing that&#39;s Happened to Python Packaging?</title>
      <link>https://pydevtools.com/handbook/explanation/uv-not-in-ppug/</link>
      <pubDate>Thu, 27 Feb 2025 14:56:00 +0000</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/uv-not-in-ppug/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://docs.astral.sh/uv/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;uv&lt;/a&gt; is the most widely adopted new Python tool in years, yet the &lt;a href=&#34;https://packaging.python.org/en/latest/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python Packaging User Guide&lt;/a&gt; (PPUG) at &lt;a href=&#34;https://packaging.python.org/en/latest/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;packaging.python.org&lt;/a&gt; makes no mention of it. The reason has less to do with uv and more to do with how Python packaging governance works.&lt;/p&gt;
&lt;h2&gt;What uv Does&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-uv-does&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-uv-does&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;uv delivers 10-100x faster package operations than pip while consolidating functionality previously spread across multiple utilities (pip, pip-tools, virtualenv, pyenv, and more) into a single tool. Since its introduction in early 2024, it has become the default recommendation in many Python teams and communities.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Can you trust uv long-term?</title>
      <link>https://pydevtools.com/handbook/explanation/can-you-trust-uv-long-term/</link>
      <pubDate>Tue, 28 Apr 2026 16:07:27 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/can-you-trust-uv-long-term/</guid>
      <description>&lt;p&gt;In March 2026, OpenAI &lt;a href=&#34;https://pydevtools.com/blog/openai-acquires-astral/&#34;&gt;acquired Astral&lt;/a&gt;, the venture-backed startup behind &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt;. Before betting a team&amp;rsquo;s workflow on a tool whose owner&amp;rsquo;s priorities just changed, the reasonable question is what happens if Astral&amp;rsquo;s output slows or stops.&lt;/p&gt;
&lt;p&gt;The handbook recommends uv. This page lays out why that recommendation survives the trust question, what would have to change before it doesn&amp;rsquo;t, and what to do today to keep your migration costs low.&lt;/p&gt;
&lt;h2&gt;Look at what you actually adopt&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;look-at-what-you-actually-adopt&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#look-at-what-you-actually-adopt&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;uv is dual-licensed under &lt;a href=&#34;https://github.com/astral-sh/uv/blob/main/README.md#license&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Apache 2.0 and MIT&lt;/a&gt;. That license cannot be revoked. Every release that has shipped is permanently available to fork, modify, or redistribute. Anyone, including you, can freeze the source tree at any commit and keep using it. No future owner can take that away.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Getting Started with Python Using Codex</title>
      <link>https://pydevtools.com/handbook/explanation/codex-complete-guide/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/codex-complete-guide/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://developers.openai.com/codex/cli&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Codex CLI&lt;/a&gt; is OpenAI&amp;rsquo;s terminal-based coding agent. It reads your repository, edits files, runs commands, and iterates on errors, all from your terminal. Describe what you want in plain English, and Codex decides which files to read, which commands to run, and what code to write.&lt;/p&gt;
&lt;p&gt;What separates Codex from other terminal agents is how it sandboxes every command the model runs. Codex isolates execution with OS-level enforcement (Seatbelt on macOS, Landlock and seccomp on Linux), not just application-layer checks. This means you can grant Codex more autonomy without worrying that a bad command will reach beyond your project directory or make network calls you didn&amp;rsquo;t authorize.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Do I need a project to use uv?</title>
      <link>https://pydevtools.com/handbook/explanation/do-i-need-a-project-to-use-uv/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/do-i-need-a-project-to-use-uv/</guid>
      <description>&lt;p&gt;If your Python life is a folder full of short scripts that glue APIs together and rename files, &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt;&amp;rsquo;s first move can look like overkill: &lt;code&gt;uv init&lt;/code&gt;, then a &lt;code&gt;pyproject.toml&lt;/code&gt;. uv works fine for scripts, but it assumes a different mental model from the &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;&lt;code&gt;pip install&lt;/code&gt;&lt;/a&gt; habit most script authors carry, and forcing the old habit onto uv is where people get stuck.&lt;/p&gt;
&lt;p&gt;The short answer: no, you don&amp;rsquo;t need a project. You have four options, and the right one depends on what the script is.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Do you still need tox or nox if you use uv?</title>
      <link>https://pydevtools.com/handbook/explanation/do-you-still-need-tox-or-nox-if-you-use-uv/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/do-you-still-need-tox-or-nox-if-you-use-uv/</guid>
      <description>&lt;p&gt;For many projects, no. &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; can run your test suite against multiple Python versions without any extra tool. But &lt;a href=&#34;https://pydevtools.com/handbook/reference/tox/&#34;&gt;tox&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/nox/&#34;&gt;nox&lt;/a&gt; do more than version switching, and the gap between &amp;ldquo;run pytest on 3.12&amp;rdquo; and &amp;ldquo;test five Python versions against two dependency sets in parallel&amp;rdquo; is where they still matter.&lt;/p&gt;
&lt;h2&gt;What uv handles on its own&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-uv-handles-on-its-own&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-uv-handles-on-its-own&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;uv run --python&lt;/code&gt; selects a Python version and executes a command in your project&amp;rsquo;s environment. If that version is not installed, uv downloads it automatically:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Do you still need tox or nox if you use uv?</title>
      <link>https://pydevtools.com/handbook/explanation/do-you-still-need-tox-or-nox-with-uv/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/do-you-still-need-tox-or-nox-with-uv/</guid>
      <description>&lt;p&gt;Before uv, setting up multi-version testing meant installing Python interpreters by hand, configuring pyenv, and hoping tox found them all. uv removes that friction: &lt;code&gt;uv run --python 3.12 pytest&lt;/code&gt; downloads Python 3.12 if it&amp;rsquo;s missing and runs your tests in one command. Teams that discover this often ask whether tox or nox are still worth the dependency.&lt;/p&gt;
&lt;p&gt;The short answer: uv replaces the plumbing (Python installs, virtual environment creation, dependency installation), not the orchestration. Whether you still need an orchestrator depends on what you&amp;rsquo;re asking it to do.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Does Poetry Support Python Standards for Dependency Management?</title>
      <link>https://pydevtools.com/handbook/explanation/poetry-python-dependency-management/</link>
      <pubDate>Tue, 07 Apr 2026 14:40:41 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/poetry-python-dependency-management/</guid>
      <description>&lt;p&gt;Poetry 2.0 supports standard &lt;a href=&#34;https://peps.python.org/pep-0621/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PEP 621&lt;/a&gt; project metadata in &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyproject.toml/&#34;&gt;pyproject.toml&lt;/a&gt;. Before version 2.0, Poetry used only its own &lt;code&gt;tool.poetry&lt;/code&gt; configuration format, but &lt;a href=&#34;https://python-poetry.org/blog/announcing-poetry-2.0.0&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the 2.0 release&lt;/a&gt; adopted the standard &lt;code&gt;project&lt;/code&gt; section.&lt;/p&gt;
&lt;p&gt;Poetry now offers two configuration approaches. You can use &lt;code&gt;project.dependencies&lt;/code&gt; for standard dependency declarations or &lt;code&gt;tool.poetry.dependencies&lt;/code&gt; for Poetry-specific features, and you can combine both when needed.&lt;/p&gt;
&lt;p&gt;Standard metadata makes projects more portable between build tools and aligns with emerging packaging standards.&lt;/p&gt;
&lt;h2&gt;Related Handbook Pages&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;related-handbook-pages&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#related-handbook-pages&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/poetry/&#34;&gt;Poetry reference page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pydevtools.com/handbook/how-to/how-to-migrate-from-poetry-to-uv/&#34;&gt;How to migrate from Poetry to uv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 class=&#34;pdt-learn-more&#34;&gt;Learn More&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;learn-more&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#learn-more&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://python-poetry.org/blog/announcing-poetry-2.0.0&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Poetry 2.0 Release Blog Post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://peps.python.org/pep-0621/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PEP 621 Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://packaging.python.org/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python Packaging User Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://python-poetry.org/docs/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Poetry Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Enough Git to Supervise Your AI Coding Agent</title>
      <link>https://pydevtools.com/handbook/explanation/enough-git-to-supervise-your-ai-coding-agent/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/enough-git-to-supervise-your-ai-coding-agent/</guid>
      <description>&lt;p&gt;AI coding agents like &lt;a href=&#34;https://pydevtools.com/handbook/explanation/claude-code-complete-guide/&#34;&gt;Claude Code&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/explanation/codex-complete-guide/&#34;&gt;Codex&lt;/a&gt;, Cursor, and GitHub Copilot run Git commands on your behalf. You don&amp;rsquo;t need to memorize those commands, but you do need to understand what they mean. Otherwise you&amp;rsquo;re approving operations you can&amp;rsquo;t verify.&lt;/p&gt;
&lt;p&gt;When your agent says &amp;ldquo;I&amp;rsquo;ve committed the changes and pushed to GitHub,&amp;rdquo; you should know where those changes went and how to undo them if something is wrong. This article provides that mental model. A companion how-to guide walks through &lt;a href=&#34;https://pydevtools.com/handbook/how-to/how-to-put-your-python-project-on-github/&#34;&gt;putting your project on GitHub&lt;/a&gt; for the first time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How do I ship a Python application to end users?</title>
      <link>https://pydevtools.com/handbook/explanation/how-do-i-ship-a-python-application-to-end-users/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-do-i-ship-a-python-application-to-end-users/</guid>
      <description>&lt;p&gt;Python usually ships an environment rather than a native executable. It ships as code plus an interpreter plus dependencies, which is why distribution gets harder the moment the users are not Python developers themselves. The real question is not whether Python can be shipped well. It can. The question is which delivery shape fits the audience: an install command, a bundled app, a container image, or something that stops being Python at all.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How do pyenv and uv compare for Python interpreter management?</title>
      <link>https://pydevtools.com/handbook/explanation/how-do-pyenv-and-uv-compare-for-python-interpreter-management/</link>
      <pubDate>Tue, 07 Apr 2026 14:40:41 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-do-pyenv-and-uv-compare-for-python-interpreter-management/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/pyenv/&#34;&gt;pyenv&lt;/a&gt; manages Python versions and gets out of the way; &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; manages Python versions as part of controlling your entire workflow. That difference in scope shapes every other trade-off between the two tools.&lt;/p&gt;
&lt;h2&gt;Design Philosophy&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;design-philosophy&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#design-philosophy&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;pyenv&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pyenv&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pyenv&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;pyenv embodies the Unix principle of &amp;ldquo;do one thing well.&amp;rdquo; Its sole purpose is managing Python interpreter installations and version switching. This focused approach means pyenv integrates seamlessly with existing workflows; after selecting a Python version, developers use familiar tools like &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/venv/&#34;&gt;venv&lt;/a&gt; for package management and virtual environments.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How do Python type checkers compare?</title>
      <link>https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare/</link>
      <pubDate>Fri, 08 May 2026 03:19:33 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-do-mypy-pyright-and-ty-compare/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/mypy/&#34;&gt;mypy&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyright/&#34;&gt;pyright&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/ty/&#34;&gt;ty&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyrefly/&#34;&gt;Pyrefly&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/basedpyright/&#34;&gt;Basedpyright&lt;/a&gt;, and &lt;a href=&#34;https://pydevtools.com/handbook/reference/zuban/&#34;&gt;Zuban&lt;/a&gt; all analyze type annotations to catch bugs before runtime. They read the same type-hint annotations (from &lt;a href=&#34;https://peps.python.org/pep-0484/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PEP 484&lt;/a&gt;, the standard that introduced Python&amp;rsquo;s type system in 2014) and largely agree on the parts of the spec a working program uses. They disagree on speed, default strictness, treatment of unannotated code, editor integration, and licensing, and those disagreements are what make the choice matter.&lt;/p&gt;
&lt;p&gt;Here is the shape of the field in 2026:&lt;/p&gt;</description>
    </item>
    <item>
      <title>How do Ruff and Pylint compare?</title>
      <link>https://pydevtools.com/handbook/explanation/how-do-ruff-and-pylint-compare/</link>
      <pubDate>Fri, 01 May 2026 06:58:47 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-do-ruff-and-pylint-compare/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/ruff/&#34;&gt;Ruff&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/pylint/&#34;&gt;Pylint&lt;/a&gt; are Python code analysis tools with overlapping but distinct capabilities.&lt;/p&gt;
&lt;h2&gt;Core Differences&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;core-differences&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#core-differences&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Speed and Architecture&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;speed-and-architecture&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#speed-and-architecture&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ruff&amp;rsquo;s Rust implementation delivers dramatically faster performance than Pylint&amp;rsquo;s Python codebase. This speed advantage becomes particularly noticeable in large codebases where Ruff can analyze files orders of magnitude faster.&lt;/p&gt;
&lt;h3&gt;Rule Coverage&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;rule-coverage&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#rule-coverage&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While Pylint implements approximately 409 rules, Ruff now exceeds 1,000 total rules, with around 209 overlapping with Pylint&amp;rsquo;s ruleset. However, these numbers continue to change, especially as Ruff undergoes rapid development.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How do uv and Poetry compare?</title>
      <link>https://pydevtools.com/handbook/explanation/how-do-uv-and-poetry-compare/</link>
      <pubDate>Fri, 10 Apr 2026 13:36:01 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-do-uv-and-poetry-compare/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/poetry/&#34;&gt;Poetry&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; both manage Python projects through &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyproject.toml/&#34;&gt;pyproject.toml&lt;/a&gt;, create lockfiles, and handle virtual environments. Poetry has been the default recommendation for years; uv, built by Astral, arrived in 2024 with broader scope and faster dependency resolution. They differ in how.&lt;/p&gt;
&lt;h2&gt;Scope&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;scope&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#scope&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Poetry handles dependency management, virtual environments, building, and publishing. Everything else it delegates. A different Python version requires &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyenv/&#34;&gt;pyenv&lt;/a&gt;. Running a CLI tool without installing it globally requires &lt;a href=&#34;https://pydevtools.com/handbook/reference/pipx/&#34;&gt;pipx&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How Does Hot Reloading Work in Python?</title>
      <link>https://pydevtools.com/handbook/explanation/how-does-hot-reloading-work-in-python/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-does-hot-reloading-work-in-python/</guid>
      <description>&lt;p&gt;Every Django developer knows &lt;code&gt;runserver&lt;/code&gt; restarts when you save a file. Every FastAPI developer knows &lt;code&gt;uvicorn --reload&lt;/code&gt;. But ask &amp;ldquo;how do I auto-reload my Python script?&amp;rdquo; and the answer fractures. There is no &lt;code&gt;--watch&lt;/code&gt; flag built into the &lt;code&gt;python&lt;/code&gt; command, no universal file-watching convention that works across all Python projects.&lt;/p&gt;
&lt;p&gt;This fragmentation is not an oversight. It reflects how Python loads and manages code at runtime, and why different development contexts require different reload strategies.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How Python Package Formats Evolved: From tar.gz to .whl</title>
      <link>https://pydevtools.com/handbook/explanation/how-python-package-formats-evolved/</link>
      <pubDate>Sat, 11 Apr 2026 17:25:27 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-python-package-formats-evolved/</guid>
      <description>&lt;p&gt;In 2000, installing a third-party Python package meant downloading a tarball, extracting it, and running &lt;code&gt;python setup.py install&lt;/code&gt;. There was no dependency resolution, no uninstall command, no record of what got installed where. Removing a package meant deleting files by hand and hoping none were missed.&lt;/p&gt;
&lt;p&gt;Twenty-five years later, &lt;code&gt;uv pip install numpy&lt;/code&gt; fetches a pre-built binary wheel and drops it into place in under a second. The journey between those two moments is a story of each generation solving one problem while inadvertently creating the next.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How Python tools adopt uv under the hood</title>
      <link>https://pydevtools.com/handbook/explanation/how-python-tools-adopt-uv-under-the-hood/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/how-python-tools-adopt-uv-under-the-hood/</guid>
      <description>&lt;p&gt;You don&amp;rsquo;t have to switch to &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; to get uv&amp;rsquo;s speed. &lt;a href=&#34;https://pydevtools.com/handbook/reference/pixi/&#34;&gt;Pixi&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/hatch/&#34;&gt;Hatch&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pdm/&#34;&gt;PDM&lt;/a&gt;, and &lt;a href=&#34;https://pydevtools.com/handbook/reference/tox/&#34;&gt;tox&lt;/a&gt; now use uv&amp;rsquo;s resolver and installer as their backend, which means your existing tool may already run on uv under the hood.&lt;/p&gt;
&lt;h2&gt;Which tools use uv&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;which-tools-use-uv&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#which-tools-use-uv&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Tool&lt;/th&gt;
          &lt;th&gt;What it delegates to uv&lt;/th&gt;
          &lt;th&gt;How to enable&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/pixi/&#34;&gt;Pixi&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;PyPI dependency resolution and installation&lt;/td&gt;
          &lt;td&gt;Automatic (default behavior)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/hatch/&#34;&gt;Hatch&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Dependency installation and venv creation&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;installer = &amp;quot;uv&amp;quot;&lt;/code&gt; in env config&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/pdm/&#34;&gt;PDM&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Dependency resolution and installation&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;pdm config use_uv true&lt;/code&gt; (experimental)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/tox/&#34;&gt;tox&lt;/a&gt; (via &lt;a href=&#34;https://pydevtools.com/handbook/reference/tox-uv/&#34;&gt;tox-uv&lt;/a&gt;)&lt;/td&gt;
          &lt;td&gt;Dependency installation and venv creation&lt;/td&gt;
          &lt;td&gt;Install the &lt;code&gt;tox-uv&lt;/code&gt; plugin&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/nox/&#34;&gt;nox&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Dependency installation&lt;/td&gt;
          &lt;td&gt;Enable &lt;a href=&#34;https://nox.thea.codes/en/stable/config.html#configuring-a-session-s-virtualenv&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;nox&amp;rsquo;s uv backend&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/prek/&#34;&gt;prek&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Python version and venv management for hooks&lt;/td&gt;
          &lt;td&gt;Automatic&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Pixi uses uv by default for all PyPI packages. Prek does the same for hook environments. The rest require opt-in configuration.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Is Conda actually free?</title>
      <link>https://pydevtools.com/handbook/explanation/is-conda-actually-free/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/is-conda-actually-free/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;https://pydevtools.com/handbook/reference/conda/&#34;&gt;conda&lt;/a&gt; package manager is open source and always free. The &lt;a href=&#34;https://pydevtools.com/handbook/reference/anaconda/&#34;&gt;Anaconda&lt;/a&gt; repository that ships as the default package source for Anaconda Distribution and Miniconda is not. Confusing &amp;ldquo;conda&amp;rdquo; with &amp;ldquo;Anaconda&amp;rdquo; causes organizations to either pay for licenses they don&amp;rsquo;t need or violate terms they didn&amp;rsquo;t know existed.&lt;/p&gt;
&lt;h2&gt;What costs money&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-costs-money&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-costs-money&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Anaconda, Inc. operates a curated package repository at &lt;code&gt;repo.anaconda.com&lt;/code&gt;. Accessing that repository requires a paid license for any organization (for-profit, nonprofit, or government) with more than 200 employees or contractors. The threshold counts all employees across the entire organization, including affiliates.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Modern Python Project Setup Guide for AI Assistants</title>
      <link>https://pydevtools.com/handbook/explanation/modern-python-project-setup-guide-for-ai-assistants/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/modern-python-project-setup-guide-for-ai-assistants/</guid>
      <description>&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-purple-200 hx:bg-purple-100 hx:text-purple-900 hx:dark:border-purple-200/30 hx:dark:bg-purple-900/30 hx:dark:text-purple-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;Important&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;For AI assistants: this guide is meant to be ingested directly. Paste it (or link it) into your project&amp;rsquo;s &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.cursorrules&lt;/code&gt;, or &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt; so coding agents follow the same conventions you would. A &lt;a href=&#34;index.md&#34;&gt;plain markdown version&lt;/a&gt; is available for direct ingestion into agent contexts.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Tooling for C# Developers</title>
      <link>https://pydevtools.com/handbook/explanation/python-tooling-for-csharp-developers/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/python-tooling-for-csharp-developers/</guid>
      <description>&lt;p&gt;Installing .NET gives you everything in one box. Installing Python gives you a box and a list of parts to assemble yourself. The runtime, the dependency sandbox, and the project tooling are separate concerns, maintained by separate communities, and chosen by the developer. That separation is the single biggest adjustment for someone coming from .NET.&lt;/p&gt;
&lt;p&gt;This guide maps C#/.NET concepts to their closest Python equivalents and explains where the mental models diverge.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Tooling for Go Developers</title>
      <link>https://pydevtools.com/handbook/explanation/python-tooling-for-go-developers/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/python-tooling-for-go-developers/</guid>
      <description>&lt;p&gt;Go ships one toolchain that handles compilation, dependency management, testing, formatting, and vetting. Python does not. That single difference explains most of the friction a Go developer will encounter when picking up Python, and most of that friction disappears once the mental model clicks.&lt;/p&gt;
&lt;h2&gt;What Will Feel Familiar, and What Will Not&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-will-feel-familiar-and-what-will-not&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-will-feel-familiar-and-what-will-not&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Many Go tools have Python counterparts, though the boundaries between them fall in different places.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Tooling for Java Developers</title>
      <link>https://pydevtools.com/handbook/explanation/python-tooling-for-java-developers/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/python-tooling-for-java-developers/</guid>
      <description>&lt;p&gt;Your first day writing Python, you will look for Maven and not find it. No single tool compiles code, resolves dependencies, runs tests, and packages artifacts in one standardized lifecycle. Python&amp;rsquo;s tooling is lighter and more modular, with small tools that each handle one concern. This article maps Java concepts to their Python counterparts and explains where the mental models diverge.&lt;/p&gt;
&lt;h2&gt;What Will Feel Familiar, and What Will Not&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-will-feel-familiar-and-what-will-not&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-will-feel-familiar-and-what-will-not&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Java&lt;/th&gt;
          &lt;th&gt;Python&lt;/th&gt;
          &lt;th&gt;Notes&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;SDKMAN (version installation)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;uv python install&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Python version management (the JDK bundles runtime, compiler, and tools; &lt;code&gt;uv python install&lt;/code&gt; only provides the interpreter)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Maven / Gradle&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Closest single tool for deps/envs/builds (but no standardized lifecycle phases)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;pom.xml / build.gradle&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/pyproject.toml/&#34;&gt;pyproject.toml&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Central project configuration file&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Maven Central&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pypi/&#34;&gt;PyPI&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Public package registry&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;JUnit&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/pytest/&#34;&gt;pytest&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Testing framework&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Checkstyle / SpotBugs&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/ruff/&#34;&gt;Ruff&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Linting and some bug-pattern checks (partial SpotBugs overlap)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;google-java-format&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ruff format&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Code formatting&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Java&amp;rsquo;s static type checking&lt;/td&gt;
          &lt;td&gt;mypy / pyright / ty&lt;/td&gt;
          &lt;td&gt;Optional, gradual (separate tools, not a compiler)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;mvn package&lt;/code&gt; / &lt;code&gt;mvn deploy&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;uv build&lt;/code&gt; + &lt;code&gt;uv publish&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;uv build&lt;/code&gt; creates distribution artifacts for library publishing; Python has no WAR equivalent&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;JAR (library)&lt;/td&gt;
          &lt;td&gt;wheel / sdist&lt;/td&gt;
          &lt;td&gt;Distribution formats (scoped to library packaging)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-purple-200 hx:bg-purple-100 hx:text-purple-900 hx:dark:border-purple-200/30 hx:dark:bg-purple-900/30 hx:dark:text-purple-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;Important&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Tooling for Rust Developers</title>
      <link>https://pydevtools.com/handbook/explanation/python-tooling-for-rust-developers/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/python-tooling-for-rust-developers/</guid>
      <description>&lt;p&gt;Cargo manages dependencies, builds code, runs tests, and publishes crates. Separate tools handle formatting (rustfmt, invoked via &lt;code&gt;cargo fmt&lt;/code&gt;) and linting (clippy, via &lt;code&gt;cargo clippy&lt;/code&gt;), while rustup manages toolchain installation. Python has no single tool with that scope, but &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; comes closest. This article maps Rust tooling concepts to their Python counterparts so Rust developers can orient quickly.&lt;/p&gt;
&lt;h2&gt;What Will Feel Familiar, and What Will Not&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-will-feel-familiar-and-what-will-not&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-will-feel-familiar-and-what-will-not&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most Rust workflows have a recognizable Python equivalent:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Tooling for TypeScript Developers</title>
      <link>https://pydevtools.com/handbook/explanation/python-tooling-for-typescript-developers/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/python-tooling-for-typescript-developers/</guid>
      <description>&lt;p&gt;TypeScript developers moving to Python often expect a single tool like npm that handles everything. Python splits those responsibilities differently, and the reasons behind that split affect how every tool behaves. This guide maps TypeScript/JS concepts to their Python equivalents and covers the daily workflow.&lt;/p&gt;
&lt;h2&gt;What Will Feel Familiar, and What Will Not&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-will-feel-familiar-and-what-will-not&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-will-feel-familiar-and-what-will-not&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most TypeScript/JS tools have a reasonable Python counterpart. The table below provides a rough translation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sampling vs deterministic profilers: which should I use?</title>
      <link>https://pydevtools.com/handbook/explanation/sampling-vs-deterministic-profilers/</link>
      <pubDate>Thu, 07 May 2026 13:56:14 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/sampling-vs-deterministic-profilers/</guid>
      <description>&lt;p&gt;Two different designs dominate Python profiling, and they produce two different kinds of lies about your program. A &lt;strong&gt;deterministic profiler&lt;/strong&gt; intercepts every function call, records the entry and exit, and tallies the total. A &lt;strong&gt;sampling profiler&lt;/strong&gt; peeks at the call stack on a timer and counts how often each function shows up. Both give you a list of hot functions, and the list will not always agree.&lt;/p&gt;
&lt;p&gt;The difference matters because the choice changes what you can trust about the output.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Should I run `python setup.py`?</title>
      <link>https://pydevtools.com/handbook/explanation/should-i-run-python-setuppy-commands/</link>
      <pubDate>Tue, 07 Apr 2026 14:40:41 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/should-i-run-python-setuppy-commands/</guid>
      <description>&lt;p&gt;No. Commands like &lt;code&gt;python setup.py sdist&lt;/code&gt;, &lt;code&gt;python setup.py bdist_wheel&lt;/code&gt;, and &lt;code&gt;python setup.py install&lt;/code&gt; are deprecated.&lt;/p&gt;
&lt;p&gt;Instead to build a &lt;a href=&#34;https://pydevtools.com/handbook/reference/wheel/&#34;&gt;wheel&lt;/a&gt; or &lt;a href=&#34;https://pydevtools.com/handbook/reference/sdist/&#34;&gt;sdist&lt;/a&gt;, use &lt;code&gt;python -m build&lt;/code&gt; (&lt;a href=&#34;https://pydevtools.com/handbook/reference/build/&#34;&gt;build&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;pip install build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;python -m build  # builds both sdist and wheel
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;python -m build --sdist
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;python -m build --wheel
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container  hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To install a package, use &lt;code&gt;pip install&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Should I use Homebrew to install Python?</title>
      <link>https://pydevtools.com/handbook/explanation/should-i-use-homebrew-to-install-python/</link>
      <pubDate>Mon, 04 May 2026 08:02:03 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/should-i-use-homebrew-to-install-python/</guid>
      <description>&lt;p&gt;Homebrew ships Python because dozens of its own packages depend on it. Tools like &lt;code&gt;glib&lt;/code&gt;, &lt;code&gt;cmake&lt;/code&gt;, and &lt;code&gt;awscli&lt;/code&gt; all pull in Python as a build or runtime dependency. When Homebrew installs Python, it is satisfying &lt;em&gt;its own&lt;/em&gt; dependency graph, not setting up a development environment for you.&lt;/p&gt;
&lt;p&gt;This distinction matters because Homebrew treats Python the same way it treats any other dependency: as something to keep current. Running &lt;code&gt;brew upgrade&lt;/code&gt; can bump Python from 3.12 to 3.13 without warning, removing the previous minor version&amp;rsquo;s &lt;code&gt;site-packages&lt;/code&gt; directory in the process.&lt;/p&gt;</description>
    </item>
    <item>
      <title>src layout vs flat layout: which to use and why</title>
      <link>https://pydevtools.com/handbook/explanation/src-layout-vs-flat-layout/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/src-layout-vs-flat-layout/</guid>
      <description>&lt;p&gt;A packaging mistake can pass every local &lt;a href=&#34;https://pydevtools.com/handbook/reference/pytest/&#34;&gt;pytest&lt;/a&gt; run and still break in production. The choice between flat layout and src layout decides whether your tests catch it before users do.&lt;/p&gt;
&lt;h2&gt;Compare the two layouts&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;compare-the-two-layouts&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#compare-the-two-layouts&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Flat layout places the package directory directly at the project root:&lt;/p&gt;
&lt;div class=&#34;hextra-filetree hx:mt-6 hx:select-none hx:text-sm hx:text-gray-800 hx:dark:text-gray-300 not-prose&#34;&gt;
  &lt;div class=&#34;hx:inline-block hx:rounded-lg hx:px-4 hx:py-2 hx:border hx:border-gray-200 hx:dark:border-neutral-800&#34;&gt;
    &lt;ul class=&#34;hx:flex hx:flex-col&#34;&gt;
  

&lt;li class=&#34;hx:group hx:flex hx:list-none hx:flex-col&#34;&gt;
  &lt;button class=&#34;hextra-filetree-folder hx:inline-flex hx:cursor-pointer hx:items-center hx:py-1 hx:hover:opacity-60&#34; aria-expanded=&#34;true&#34;&gt;
    &lt;span data-state=&#34;open&#34; class=&#34;hx:data-[state=open]:hidden&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z&#34;/&gt;&lt;/svg&gt;&lt;/span&gt;
    &lt;span data-state=&#34;open&#34; class=&#34;hx:data-[state=closed]:hidden&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M5 19a2 2 0 01-2-2V7a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1M5 19h14a2 2 0 002-2v-5a2 2 0 00-2-2H9a2 2 0 00-2 2v5a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;/span&gt;
    &lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;my-project&lt;/span&gt;
  &lt;/button&gt;
  &lt;ul data-state=&#34;open&#34; class=&#34;hx:ltr:pl-5 hx:rtl:pr-5 hx:data-[state=closed]:hidden&#34;&gt;
  &lt;li class=&#34;hx:flex hx:list-none&#34;&gt;
    &lt;span class=&#34;hx:inline-flex hx:cursor-default hx:items-center hx:py-1&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;pyproject.toml&lt;/span&gt;
    &lt;/span&gt;
  &lt;/li&gt;

  &lt;li class=&#34;hx:flex hx:list-none&#34;&gt;
    &lt;span class=&#34;hx:inline-flex hx:cursor-default hx:items-center hx:py-1&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;README.md&lt;/span&gt;
    &lt;/span&gt;
  &lt;/li&gt;

  

&lt;li class=&#34;hx:group hx:flex hx:list-none hx:flex-col&#34;&gt;
&lt;button class=&#34;hextra-filetree-folder hx:inline-flex hx:cursor-pointer hx:items-center hx:py-1 hx:hover:opacity-60&#34; aria-expanded=&#34;true&#34;&gt;
  &lt;span data-state=&#34;open&#34; class=&#34;hx:data-[state=open]:hidden&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z&#34;/&gt;&lt;/svg&gt;&lt;/span&gt;
  &lt;span data-state=&#34;open&#34; class=&#34;hx:data-[state=closed]:hidden&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M5 19a2 2 0 01-2-2V7a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1M5 19h14a2 2 0 002-2v-5a2 2 0 00-2-2H9a2 2 0 00-2 2v5a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;/span&gt;
  &lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;mypackage&lt;/span&gt;
&lt;/button&gt;
&lt;ul data-state=&#34;open&#34; class=&#34;hx:ltr:pl-5 hx:rtl:pr-5 hx:data-[state=closed]:hidden&#34;&gt;
&lt;li class=&#34;hx:flex hx:list-none&#34;&gt;
  &lt;span class=&#34;hx:inline-flex hx:cursor-default hx:items-center hx:py-1&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;__init__.py&lt;/span&gt;
  &lt;/span&gt;
&lt;/li&gt;

&lt;li class=&#34;hx:flex hx:list-none&#34;&gt;
  &lt;span class=&#34;hx:inline-flex hx:cursor-default hx:items-center hx:py-1&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;core.py&lt;/span&gt;
  &lt;/span&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

  

&lt;li class=&#34;hx:group hx:flex hx:list-none hx:flex-col&#34;&gt;
&lt;button class=&#34;hextra-filetree-folder hx:inline-flex hx:cursor-pointer hx:items-center hx:py-1 hx:hover:opacity-60&#34; aria-expanded=&#34;true&#34;&gt;
  &lt;span data-state=&#34;open&#34; class=&#34;hx:data-[state=open]:hidden&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z&#34;/&gt;&lt;/svg&gt;&lt;/span&gt;
  &lt;span data-state=&#34;open&#34; class=&#34;hx:data-[state=closed]:hidden&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M5 19a2 2 0 01-2-2V7a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1M5 19h14a2 2 0 002-2v-5a2 2 0 00-2-2H9a2 2 0 00-2 2v5a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;/span&gt;
  &lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;tests&lt;/span&gt;
&lt;/button&gt;
&lt;ul data-state=&#34;open&#34; class=&#34;hx:ltr:pl-5 hx:rtl:pr-5 hx:data-[state=closed]:hidden&#34;&gt;
&lt;li class=&#34;hx:flex hx:list-none&#34;&gt;
  &lt;span class=&#34;hx:inline-flex hx:cursor-default hx:items-center hx:py-1&#34;&gt;&lt;svg width=1em xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z&#34;/&gt;&lt;/svg&gt;&lt;span class=&#34;hx:ltr:ml-1 hx:rtl:mr-1&#34;&gt;test_core.py&lt;/span&gt;
  &lt;/span&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Src layout nests the package under a &lt;code&gt;src/&lt;/code&gt; directory:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Understanding dependency groups in uv</title>
      <link>https://pydevtools.com/handbook/explanation/understanding-dependency-groups-in-uv/</link>
      <pubDate>Tue, 07 Apr 2026 14:40:41 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/understanding-dependency-groups-in-uv/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; separates project dependencies into &lt;strong&gt;dependency groups&lt;/strong&gt; (for development workflows) and &lt;strong&gt;optional dependencies&lt;/strong&gt; (extras, for features shipped to users). Knowing which to use keeps your &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyproject.toml/&#34;&gt;pyproject.toml&lt;/a&gt; clean and your users&amp;rsquo; installs lean.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Dependency groups&lt;/th&gt;
          &lt;th&gt;Optional dependencies&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Audience&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Developers of the project&lt;/td&gt;
          &lt;td&gt;Users of the project&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Published to PyPI&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;No&lt;/td&gt;
          &lt;td&gt;Yes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;pyproject.toml section&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;[dependency-groups]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;[project.optional-dependencies]&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Install syntax&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;uv sync --group test&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;uv sync --extra viz&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Typical contents&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;pytest, ruff, sphinx&lt;/td&gt;
          &lt;td&gt;matplotlib, boto3&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Separate the tools from the product&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;separate-the-tools-from-the-product&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#separate-the-tools-from-the-product&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;[project]&lt;/code&gt; table in pyproject.toml declares the packages that every user of a library or application needs:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Understanding the Conda/Anaconda Ecosystem</title>
      <link>https://pydevtools.com/handbook/explanation/understanding-the-conda-anaconda-ecosystem/</link>
      <pubDate>Fri, 10 Apr 2026 11:13:55 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/understanding-the-conda-anaconda-ecosystem/</guid>
      <description>&lt;p&gt;Conda is not Anaconda. &lt;a href=&#34;https://pydevtools.com/handbook/reference/conda/&#34;&gt;Conda&lt;/a&gt; is a package manager; &lt;a href=&#34;https://pydevtools.com/handbook/reference/anaconda/&#34;&gt;Anaconda&lt;/a&gt; is a distribution that bundles conda with over 1,500 pre-installed packages. Confusing the two is common, and it leads to choosing the wrong installer or paying for a commercial license you don&amp;rsquo;t need.&lt;/p&gt;
&lt;p&gt;The conda ecosystem operates as a parallel system to Python&amp;rsquo;s standard packaging tools like &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pypi/&#34;&gt;PyPI&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt;, and &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-a-virtual-environment/&#34;&gt;virtual environments&lt;/a&gt;. Conda uses its own package format, repository structure, and environment management. The two ecosystems can coexist, but they work independently.&lt;/p&gt;</description>
    </item>
    <item>
      <title>uv for Non-Python Teams</title>
      <link>https://pydevtools.com/handbook/explanation/uv-for-non-python-teams/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/uv-for-non-python-teams/</guid>
      <description>&lt;p&gt;A Java shop ships a database. In the corner of the repo sits a 200-line Python script that reshapes CI logs for humans. Nobody writes Python full time, but every new hire inherits it and spends an afternoon getting &lt;code&gt;python3&lt;/code&gt; to find the right &lt;code&gt;pandas&lt;/code&gt;. That&amp;rsquo;s the tax for not being a Python shop.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; removes it. For teams whose primary language isn&amp;rsquo;t Python, uv is the whole Python toolchain: one binary that replaces &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/virtualenv/&#34;&gt;virtualenv&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyenv/&#34;&gt;pyenv&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pipx/&#34;&gt;pipx&lt;/a&gt;, and &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip-tools/&#34;&gt;pip-tools&lt;/a&gt; well enough that the Python onboarding doc shrinks to two lines.&lt;/p&gt;</description>
    </item>
    <item>
      <title>uv init: project types, flags, and examples</title>
      <link>https://pydevtools.com/handbook/explanation/understanding-uv-init-project-types/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/understanding-uv-init-project-types/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; command &lt;code&gt;uv init&lt;/code&gt; creates a new Python project with a &lt;code&gt;pyproject.toml&lt;/code&gt;, a &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-a-virtual-environment/&#34;&gt;virtual environment&lt;/a&gt;, and a &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;lockfile&lt;/a&gt;. Different flags produce different project layouts — applications, reusable libraries, packageable CLI tools, or a minimal scaffold — each suited to a specific use case.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Flag&lt;/th&gt;
          &lt;th&gt;Build System&lt;/th&gt;
          &lt;th&gt;Structure&lt;/th&gt;
          &lt;th&gt;Entry Point&lt;/th&gt;
          &lt;th&gt;Distribution&lt;/th&gt;
          &lt;th&gt;Use Case&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--app&lt;/code&gt; (default)&lt;/td&gt;
          &lt;td&gt;No&lt;/td&gt;
          &lt;td&gt;Flat&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Not intended&lt;/td&gt;
          &lt;td&gt;Web apps, scripts&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--lib&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Yes&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;src/&lt;/code&gt; layout&lt;/td&gt;
          &lt;td&gt;None&lt;/td&gt;
          &lt;td&gt;PyPI packages&lt;/td&gt;
          &lt;td&gt;Reusable libraries&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--package&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Yes&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;src/&lt;/code&gt; layout&lt;/td&gt;
          &lt;td&gt;Console script&lt;/td&gt;
          &lt;td&gt;Installable apps&lt;/td&gt;
          &lt;td&gt;CLI tools&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--bare&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;No&lt;/td&gt;
          &lt;td&gt;Minimal&lt;/td&gt;
          &lt;td&gt;None&lt;/td&gt;
          &lt;td&gt;Manual setup&lt;/td&gt;
          &lt;td&gt;Custom projects&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--no-package&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;No&lt;/td&gt;
          &lt;td&gt;Flat&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Explicitly blocked&lt;/td&gt;
          &lt;td&gt;Internal apps&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Common uv init commands&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;common-uv-init-commands&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#common-uv-init-commands&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;uv init my-project&lt;/code&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;uv-init-my-project&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#uv-init-my-project&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The default form creates a new directory and an application project inside it:&lt;/p&gt;</description>
    </item>
    <item>
      <title>uv vs pixi vs conda for Scientific Python</title>
      <link>https://pydevtools.com/handbook/explanation/uv-vs-pixi-vs-conda-for-scientific-python/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/uv-vs-pixi-vs-conda-for-scientific-python/</guid>
      <description>&lt;p&gt;Your scientific Python project needs CUDA, GDAL, or HDF5, and &lt;code&gt;pip install&lt;/code&gt; cannot help. Which tool should manage those native dependencies alongside your Python code? The answer depends on where your packages live: &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pypi/&#34;&gt;PyPI&lt;/a&gt;, conda-forge, or both.&lt;/p&gt;
&lt;p&gt;Three tools cover the spectrum. &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; installs from PyPI. &lt;a href=&#34;https://pydevtools.com/handbook/reference/pixi/&#34;&gt;pixi&lt;/a&gt; installs from conda-forge and PyPI together. &lt;a href=&#34;https://pydevtools.com/handbook/reference/conda/&#34;&gt;conda&lt;/a&gt; installs from conda channels.&lt;/p&gt;
&lt;h2&gt;What each tool can install&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-each-tool-can-install&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-each-tool-can-install&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;uv resolves packages from PyPI, plus Git URLs, local paths, and private indexes. It cannot install non-Python dependencies like the CUDA toolkit, GDAL, or HDF5.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Versioning Python packages: SemVer, CalVer, and PEP 440</title>
      <link>https://pydevtools.com/handbook/explanation/versioning-python-packages-semver-calver-and-pep-440/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/versioning-python-packages-semver-calver-and-pep-440/</guid>
      <description>&lt;p&gt;Every Python package that lands on PyPI carries a version string. Three names show up whenever teams argue about what should be in it: &lt;a href=&#34;https://peps.python.org/pep-0440/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PEP 440&lt;/a&gt;, Semantic Versioning (SemVer), and Calendar Versioning (CalVer). They describe different layers, and confusing them produces the kind of debate that burns an hour of standup and ships nothing.&lt;/p&gt;
&lt;p&gt;PEP 440 is the grammar. It defines what a legal Python version string looks like and how releases sort. Every installer, from &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt; to &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; to &lt;a href=&#34;https://pydevtools.com/handbook/reference/poetry/&#34;&gt;Poetry&lt;/a&gt;, enforces it. SemVer and CalVer are policies. They tell maintainers &lt;em&gt;what the numbers should mean&lt;/em&gt;, not whether they&amp;rsquo;re allowed. A project can follow either policy (or neither) and still be valid PEP 440.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What are Optional Dependencies and Dependency Groups?</title>
      <link>https://pydevtools.com/handbook/explanation/what-are-optional-dependencies-and-dependency-groups/</link>
      <pubDate>Tue, 07 Apr 2026 14:40:41 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-are-optional-dependencies-and-dependency-groups/</guid>
      <description>&lt;h2&gt;Optional Dependencies: End-User Features&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;optional-dependencies-end-user-features&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#optional-dependencies-end-user-features&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Optional dependencies, defined in &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyproject.toml/&#34;&gt;pyproject.toml&lt;/a&gt; under &lt;code&gt;[project.optional-dependencies]&lt;/code&gt; (part of the &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pep-621-compatibility/&#34;&gt;PEP 621&lt;/a&gt; standard), are designed to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Package optional features that some users may want&lt;/li&gt;
&lt;li&gt;Allow users to install specific feature sets using the &lt;code&gt;pip install package[extra]&lt;/code&gt; syntax&lt;/li&gt;
&lt;li&gt;Get published to PyPI along with the package&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;project&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;optional-dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;boto3&amp;gt;=1.26.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;s3fs&amp;gt;=2023.1.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;visualization&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;matplotlib&amp;gt;=3.7.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;seaborn&amp;gt;=0.12.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container  hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This allows users to choose the features they need:&lt;/p&gt;</description>
    </item>
    <item>
      <title>What Are Wheel Variants?</title>
      <link>https://pydevtools.com/handbook/explanation/what-are-wheel-variants/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-are-wheel-variants/</guid>
      <description>&lt;p&gt;A default NumPy &lt;a href=&#34;https://pydevtools.com/handbook/reference/wheel/&#34;&gt;wheel&lt;/a&gt; for &lt;code&gt;x86_64&lt;/code&gt; has to run on every x86-64 CPU that has ever shipped, with the baseline instruction set fixed when AMD64 was defined in 2003. Every SIMD instruction Intel and AMD have added since then is off-limits to the installer, because a wheel filename has no place to declare &amp;ldquo;needs AVX2&amp;rdquo; or &amp;ldquo;needs SSE4&amp;rdquo;. On scientific workloads, Ralf Gommers of Quansight put the performance left on the table at &lt;a href=&#34;https://talkpython.fm/episodes/show/544/wheel-next-packaging-peps&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;10x to 20x&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What Happens When You Run `uv run`</title>
      <link>https://pydevtools.com/handbook/explanation/what-happens-when-you-run-uv-run/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-happens-when-you-run-uv-run/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; doesn&amp;rsquo;t replace Python. It orchestrates Python. When you type &lt;code&gt;uv run pytest&lt;/code&gt;, uv sets up the right environment and then hands off to a real Python interpreter to do the actual work. The command is equivalent to activating a virtual environment and running &lt;code&gt;python -m pytest&lt;/code&gt; inside it, except uv handles every setup step automatically.&lt;/p&gt;
&lt;p&gt;That setup involves finding your project, choosing a Python interpreter, creating or reusing a virtual environment, checking the lockfile, and syncing packages. Each step short-circuits if the work is already done, which is why &lt;code&gt;uv run&lt;/code&gt; feels instant on repeated invocations but takes longer the first time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a .python-version file?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-python-version-file/</link>
      <pubDate>Tue, 07 Apr 2026 14:40:41 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-python-version-file/</guid>
      <description>&lt;p&gt;A &lt;code&gt;.python-version&lt;/code&gt; file is a simple text file that specifies which Python version should be used for a particular project or directory. When present, Python version management tools like &lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/pyenv/&#34;&gt;pyenv&lt;/a&gt; automatically use the specified Python version when working in that directory.&lt;/p&gt;
&lt;p&gt;The file contains a single line with a Python version specification, e.g.,&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;3.11.5&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container  hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This approach provides environment-specific Python version control without requiring manual activation or configuration each time you work on a project.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a build backend?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-build-backend/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-build-backend/</guid>
      <description>&lt;p&gt;A build backend is a library that turns your Python source code into distributable packages: &lt;a href=&#34;https://pydevtools.com/handbook/reference/wheel/&#34;&gt;wheels&lt;/a&gt; and &lt;a href=&#34;https://pydevtools.com/handbook/reference/sdist/&#34;&gt;sdists&lt;/a&gt;. It reads your project metadata, processes your source tree, and produces the archives that get uploaded to &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pypi/&#34;&gt;PyPI&lt;/a&gt; or installed locally.&lt;/p&gt;
&lt;p&gt;Build backends work in tandem with &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-a-build-frontend/&#34;&gt;build frontends&lt;/a&gt;. The frontend is the tool a developer invokes (&lt;a href=&#34;https://pydevtools.com/handbook/reference/uv/&#34;&gt;uv&lt;/a&gt;, &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt;, &lt;code&gt;python -m build&lt;/code&gt;). It typically creates an isolated build environment, installs the backend and its dependencies, and calls standardized hook functions. The backend does the actual work of producing artifacts. All &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pep-517/&#34;&gt;PEP 517&lt;/a&gt;-compliant backends implement the same hook API; the mandatory hooks are &lt;code&gt;build_wheel&lt;/code&gt; and &lt;code&gt;build_sdist&lt;/code&gt;, so any compliant frontend can invoke any backend without special-case code.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a build frontend?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-build-frontend/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-build-frontend/</guid>
      <description>&lt;p&gt;A build frontend is a tool that invokes build backends to create Python packages. It provides the user interface and orchestrates the build process while delegating the build work to build backends.&lt;/p&gt;
&lt;h2&gt;Common Build Frontends&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;common-build-frontends&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#common-build-frontends&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt;: Default package installer, builds during installation&lt;/li&gt;
&lt;li&gt;build: Dedicated PEP 517 builder from PyPA&lt;/li&gt;
&lt;li&gt;uv: High-performance alternative to &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;poetry/&lt;a href=&#34;https://pydevtools.com/handbook/reference/hatch/&#34;&gt;hatch&lt;/a&gt;/&lt;a href=&#34;https://pydevtools.com/handbook/reference/pdm/&#34;&gt;pdm&lt;/a&gt;: Full-featured project management tools with build capabilities&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Key Responsibilities&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;key-responsibilities&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#key-responsibilities&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Discovering and loading build backends&lt;/li&gt;
&lt;li&gt;Managing build environments&lt;/li&gt;
&lt;li&gt;Handling build configuration&lt;/li&gt;
&lt;li&gt;Processing build output (wheels/sdists)&lt;/li&gt;
&lt;li&gt;Reporting build progress and errors&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;Build frontends implement &lt;a href=&#34;https://pydevtools.com/handbook/explanation/what-is-pep-517/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PEP 517&amp;rsquo;s standardized interface&lt;/a&gt; for interacting with build backends, ensuring consistent behavior across different tools.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Example Usage&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;example-usage&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#example-usage&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using the &lt;code&gt;build&lt;/code&gt; frontend to create distributions:&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a lockfile?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-lock-file/</link>
      <pubDate>Fri, 24 Apr 2026 16:46:22 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-lock-file/</guid>
      <description>&lt;p&gt;A lockfile is a text file enumerating the specific version of every dependency used by a project; it serves as a contract that guarantees reproducible environments across different systems and time periods.&lt;/p&gt;
&lt;p&gt;A lockfile might record:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exact versions of all direct and transitive dependencies&lt;/li&gt;
&lt;li&gt;Cryptographic hashes to verify package integrity&lt;/li&gt;
&lt;li&gt;Platform-specific requirements and constraints&lt;/li&gt;
&lt;li&gt;Metadata about how dependencies were resolved&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This creates a &amp;ldquo;single source of truth&amp;rdquo; for project dependencies that can be reliably reproduced.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a PEP?</title>
      <link>https://pydevtools.com/handbook/explanation/pep/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/pep/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://peps.python.org&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Python Enhancement Proposals&lt;/a&gt; (PEPs) are the foundational documents that guide Python&amp;rsquo;s evolution. They propose new language features, collect community input on issues, and document Python design decisions. They record the language&amp;rsquo;s history and future direction through carefully deliberated proposals.&lt;/p&gt;
&lt;p&gt;Not all PEPs are accepted. Rejected PEPs often contain valuable discussion and insights about Python&amp;rsquo;s design philosophy.&lt;/p&gt;
&lt;h2&gt;Core Purpose and Process&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;core-purpose-and-process&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#core-purpose-and-process&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;PEPs serve multiple functions in Python&amp;rsquo;s ecosystem:&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a Python application?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-python-application/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-python-application/</guid>
      <description>&lt;p&gt;A Python application is a self-contained program designed to be used directly by end users, in contrast to a Python package, which is designed to be imported and reused by other Python code.&lt;/p&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; open&gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Application vs Package Comparison&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    &lt;p&gt;Applications and packages serve different purposes:&lt;/p&gt;
&lt;p&gt;Applications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a main entry point (e.g., &lt;code&gt;main.py&lt;/code&gt; or command-line interface)&lt;/li&gt;
&lt;li&gt;Focus on end-user functionality&lt;/li&gt;
&lt;li&gt;Often include configuration files and user settings&lt;/li&gt;
&lt;li&gt;May bundle dependencies for deployment&lt;/li&gt;
&lt;li&gt;Typically not imported by other Python code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Packages:&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a Python Interpreter?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-python-interpreter/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-python-interpreter/</guid>
      <description>&lt;p&gt;A Python interpreter is the executable program that reads &lt;code&gt;.py&lt;/code&gt; files and runs them. When someone says &amp;ldquo;I have Python 3.12 installed,&amp;rdquo; they mean a &lt;code&gt;python3.12&lt;/code&gt; binary exists somewhere on their system that can execute Python code. Every Python project needs an interpreter, and most of the complexity in Python tooling comes from managing which interpreter runs where.&lt;/p&gt;
&lt;h2&gt;Where interpreters come from&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;where-interpreters-come-from&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#where-interpreters-come-from&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Python interpreters arrive on a system through several channels:&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a Python language server?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-python-language-server/</link>
      <pubDate>Tue, 05 May 2026 06:56:59 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-python-language-server/</guid>
      <description>&lt;p&gt;Type a dot after a variable in your editor and a list of methods appears. Hover a function and its signature shows up in a tooltip. Right-click an import and &amp;ldquo;Go to definition&amp;rdquo; jumps to the source. Most Python developers have used these features for years without knowing the name of the program behind them.&lt;/p&gt;
&lt;p&gt;That program is a &lt;strong&gt;language server&lt;/strong&gt;. It is a separate process running alongside your editor, and it is doing most of the work readers usually credit to &amp;ldquo;the editor.&amp;rdquo; Naming it explains why VS Code, Neovim, Cursor, and Zed give you the same autocomplete on the same file, and why a faster type checker makes your editor feel faster.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a Python module?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-python-module/</link>
      <pubDate>Sat, 11 Apr 2026 17:42:24 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-python-module/</guid>
      <description>&lt;p&gt;A module is the basic unit of code Python can import. Any &lt;code&gt;.py&lt;/code&gt; file is a module. So is any compiled extension, which ships as a &lt;code&gt;.so&lt;/code&gt; file on Linux and macOS or a &lt;code&gt;.pyd&lt;/code&gt; file on Windows. Anything that implements Python&amp;rsquo;s import protocol counts too, but the file cases cover what most developers ever see.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://packaging.python.org/en/latest/glossary/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PyPA glossary&lt;/a&gt; gives this concept three separate entries (Module, Pure Module, Extension Module), which is a hint that the vocabulary confuses people. This page walks through each flavor, and then untangles the bit that trips up almost every beginner: how modules relate to import packages and to the things you &lt;code&gt;pip install&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What is a Python package?</title>
      <link>https://pydevtools.com/handbook/explanation/what-is-a-python-package/</link>
      <pubDate>Tue, 28 Apr 2026 21:54:51 -0400</pubDate>
      <author>Tim Hopper</author>
      <guid>https://pydevtools.com/handbook/explanation/what-is-a-python-package/</guid>
      <description>&lt;p&gt;A Python package is a collection of related code modules (files) bundled with metadata describing how the package should be installed and used.&lt;/p&gt;
&lt;p&gt;There are three common formats for Python packages, each serving different purposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/wheel/&#34;&gt;Wheels&lt;/a&gt;: Pre-built binary distributions that can be quickly installed with &lt;a href=&#34;https://pydevtools.com/handbook/reference/pip/&#34;&gt;pip&lt;/a&gt; or uv.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/sdist/&#34;&gt;Source distributions (sdists)&lt;/a&gt;: Raw source code that may need to be built during installation&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pydevtools.com/handbook/reference/conda/&#34;&gt;Conda&lt;/a&gt; packages: A format specific to the Conda ecosystem that can include non-Python components&lt;/li&gt;
&lt;/ul&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; open&gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Package vs Application Comparison&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    &lt;p&gt;Packages and applications serve different purposes:&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>
