What's up Python? Mypy gets better, uv faster, FastApi easier, Emscripten formal...er
June, 2025
Summary
Emscripten Support is added back and formalized
Mypy 1.16 Released, fixing 2 very annoying typing warts
uv now comes with a build-backend, and it's fast.
FastAPI's author is launching his company
Emscripten Support is now formalized
In Python 3.12, Emscripten and WASI were Tier 3 platforms, meaning they had to have at least one code dev committed to supporting them. This was dropped in 3.13, and in October, Brett Cannon passed the mantle to Russell Keith-Magee to reinstate the target.
PEP 776 is the draft of the official document to describe how Emscripten is going to be supported from now on.
Now, I assume some of you are wondering: what the heck is Emscripten?
It's the compiler toolchain that lets you turn C/C++ code into something that runs in a Web browser, and it's the foundation of pyodide and pyscript.
Try the Jupyter notebook here. It's running Python in your web browser. The code doesn't touch the server.
That's possible thanks to Emscripten.
It's a very technical PEP, so I won't get into the details of it, but it's a very good thing: Python is getting a more robust position in the Web Client side of the story.
E.G.: I plan to add executable Python snippets on this blog, and I certainly don't want to give you access to my server in doing so, no matter how nice you are. I know, I still haven't left Substack. Don't remind me.
Mypy 1.16 Released, and it's good stuff
I don't comment on all mypy releases, but this one deserves a (uv
) pip install mypy --upgrade
.
First, it fixes a super annoying limitation of mypy where it was mad at you for daring to use a different type for a @property
getter and setter. Now this works:
class User:
_id: int
@property
def badge_id(self) -> int:
return self._id
@foo.setter
def badge_id(self, x: str | int) -> None:
self._value = int(x)
If you are wondering, the workaround was creating a full blown descriptor, which was a pain in the butt, if you even knew about it.
The other very good thing is more of a matter of taste, but it's very much to my taste: flexible variable redefinition.
In short, you can do when you declare a variable:
if stuff:
x = n
else:
x = str(n)
Before that, you had to manually declare the type of x
as a union before the condition, or mypy would scream.
Don't get me wrong, I get this is the clean thing to do in a very serious code base to avoid people editing the code later to introduce a bug by mistake.
But when I code for myself, I want to use my dynamic language with the benefit of the dynamic language. Type checks are just the cherry on top, not the main dish.
So I'm very happy that I can now opt in for this style. Which you have to, by passing the --allow-redefinition-new
and --local-partial-type
flags.
Finally, mypy introduces a --exclude-gitignore
which does exactly what you think and hopefully will become the standard in the future.
uv now comes with its own build backend
When you want to create a package and put it on PyPI so other devs can install and use your code, you need to build a wheel.
The typical modern way to do that is to use a PEP518-compliant build system such as hatchling, setuptool, or flit.
uv
does provide an uv build
command to create your own package, but it does so using so-called "build backends", delegating the work to another software, by default, Hatchling.
So you had to know all this, have the right package installed, and you needed a special configuration in pyproject.toml
looking like this:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
uv init
would do that for you if you remembered to pass --package
at the very beginning of your project.
However, it will soon be unnecessary for the vast majority of users. Astral just added their own build backend, which means you don't need to install anything, as it's provided out of the box. It's also, per Charlie Marsh, 10-35x faster. Your Github Action will go Brrrrr.
Now that this backend is stable, you can use it after uv self update
. You need to configure it this way:
[build-system]
requires = ["uv_build>=0.7.19,<0.8.0"]
build-backend = "uv_build"
In the future, it will become the default one, meaning you'll need zero configuration to build a pure Python package.
I say pure Python since it doesn't support compiled code yet.
To quote Charlie:
One underrated implication here: we can now build and publish your package without running or even installing Python. In pure Rust, we can build your Python package, install it, publish it to a registry, etc.
It's quite interesting because:
It's Python version agnostic, and works no matter your flavor of Python.
You can have a build tool installed at the system level instead of one in each venv, which is almost always necessary otherwise.
You get super-duper build isolation.
In CI, you can trigger the build with zero Python env setup for very lightweight actions
In short, it's one less Python chicken-and-egg problem to worry about. And that's a big advantage of uv
.
Cloudy with a chance of FastAPI
There is a trend that makes me smile these days, and it’s having a solid open-source contributor starting a company based on their work.
I know it's not a common feeling, but personally, I love it. I trust those people more with my data, and I feel like they deserve to make money after helping so much: it's so hard to keep high-quality FOSS running.
Recently, we had astral and pydantic.
And now Sebastián Ramírez has started FastAPI Labs.
You guessed it, the idea is to provide a turnkey solution for deploying FastAPI called FastAPI Cloud. The whole sales pitch is to publish with just a single command and get automatic deployment, HTTPS, and autoscaling.
I like this road of offering a service on top of a product because, and I quote @tiangolo here:
building a cloud had this very nice property: there's not much overlap between the open source parts and the commercial product itself, so there's no conflict of "what goes to open source and what do we charge for", it's all clear.
Even better, the more people who are able to successfully use FastAPI and Python in general, the more potential clients for the product, so there's an intrinsic incentive to keep the open source projects healthy and serve even more users, with good docs and good features.
Now, unlike with Logfire, I'm not going to jump on this because that's something I don't need. I craft all my servers very intentionally, and each of my setups are very much optimized for my different projects. In fact, I rarely use containers because I want to squeeze the juice from the infra, given I use a slow language and delegate the perfs to basically everything else.
But despite all the Heroku and PythonAnywhere of this world, many people still find it complicated to deploy their Python project. And yes, I get the irony considering we used to just dump PHP files using FTP in 2000 and be done with it, and that it's still possible today.
It's also a business model less threatened by the AI craze (although on my side, we successfully used Claude code to deploy whole servers as an alternative to Ansible or PyInfra, wild!).
I wish good luck to a beautiful project from a team I have a lot of respect for.
I'm afraid it's a waiting list now, so if you are interested in it, you'll have put your email there.