After literal decades of work, #setuptools maintainers are finally retiring #pkg_resources in v82.0.0. I've been diligent to migrate every package I came across that used it for years, but it's very likely still being used in the wild, so here's a bit of context if you see failing builds in the coming days and don't understand what's happening;
#pkg_resources was shipped alongside #setuptools, which has been the de-facto standard (and only option up until ~2018 (#PEP517)) build backend for #Python packages. #setuptools was *never* part of the standard library, however it used to be (and still is, in many cases) distributed with it for convenience, so many projects have depended on it for ages, some of which have never explicitly declared it as a dependency (neither build-time or runtime). #pkg_resources had the same exact problems, but worse, because you couldn't even find it on #PyPI under its own name. I suspect many Python dev will only learn about this now that the package is suddenly missing.
In many cases, solutions include:
- migrating to importlib.metadata (python>=3.8), or its third party counterpart #importlib_metadata if somehow you still need to support Python 3.7 or older
- migrating to importlib.resources (Python>=3.11), or #importlib_resources for older Pythons
- dropping #setuptools / #pkg_resources completely: if all you need is a dead-simple, well maintained build backend for pure-Python projects, I highly recommend #flit_core. It's trivial to use, only supports static metadata and has never blown my face away after years using it every chance I get.

If you read this far, please boost for reach. Thanks !

#packaging #dependency #dependency_hell #softwaredevelopment

<+ionen> I feel like I'm updating uv/uv-build more often than I use it and it takes like 10000x longer to build than the package I use it for

Who would have thought that the #RustLang fad will make people force others to install humongous tools that don't bring any benefit to them.

#Python #PEP517

0 days since random #Python package switched #PEP517 backend and published an incomplete source distribution.

Heya folks! I wanted to share some of the work I've been doing on ypkg, our package building tool. Today's achievement was re-writing the entry point of the program into a proper CLI using Typer. Doing this was necessary for the work I've done making ypkg #PEP517 compatible. It's not glamorous, but it is necessary.

You can follow along with the PR if you want: https://github.com/getsolus/ypkg/pull/114

#Solus #Linux #Packaging

- Evan

Dziś ktoś pytał w temacie walki z ostrzeżeniami o "przestarzałej" funkcjonalności w #setuptools (w #Gentoo zbieramy je i wypisujemy ponownie, więc ludzie faktycznie mogą je zauważyć). Myślę, że moją najlepszą podpowiedzią było: użyj innego systemu budowania.

#Python #PEP517

Someone asked about fixing #setuptools deprecation warnings today (#Gentoo collects and reprints them, so people actually notice). I think my best hint is: use another build system.

#Python #PEP517

Biblioteki eclass związane z Pythonem w #Gentoo są całkiem aktualne. Stosują się do aktualnych zaleceń i standardów, i usuwają na bieżąco rzeczy przestarzałe. Niemniej, mają za sobą długą historię, i najlepiej chyba to widać po nazewnictwie.

Biblioteki te powstały w celu zastąpienia wcześniejszych "distutils" i "python". Dlatego też nazwałem je odpowiednio "distutils-r1" i "python-r1", podążając za schematem rewizji dla ebuildów. Dla spójności, pozostałe biblioteki również doczekały się sufiksu "-r1": "python-any-r1", "python-single-r1" i "python-utils-r1" — mimo że nigdy nie istniały w wersji "r0".

Wkrótce poznałem swój pierwszy błąd. Uczyniłem bibliotekę odpowiedzialną za budowanie paczek dla wielu implementacji "domyślną", prawdopodobnie w oparciu o ówczesne rekomendacje pisania ebuildów. Jednak z czasem odkryłem, że w większości przypadków (tam, gdzie nie używamy "distutils-r1") nie potrzeba takiej funkcjonalności, a ebuildy stają się niepotrzebne skomplikowane. Gdybym wybierał nazwy dzisiaj, najpewniej nazwałbym ją "python-multi", żeby podkreślić zastosowanie. A "domyślnej" albo by nie było w ogóle, albo byłaby nią "python-single".

Z "distutils-r1" jest jeszcze gorzej. Oczywiście, kiedy powstawała, distutils wciąż istniało, a niektórzy ludzie (jak ja) preferowali je nad zależnością od setuptools. A dziś zostało już całkiem pochłonięte przez setuptools, a za sprawą #PEP517 nawet "setuptools" nie jest już dobrą nazwą. No i ludzie dziwią się, że np. dla systemu budowania Hatchling mają używać "distutils-r1".

No i to już jest coś, co mogłem zrobić lepiej. Wprowadzenie wsparcia PEP517 była sporą zmianą, i zamiast dodawać zmienną DISTUTILS_USE_PEP517 (nazwa ze sprzecznością), mogłem utworzyć nową bibliotekę. Dlaczego tego nie zrobiłem? Cóż, jeden i drugi tryb dzieliły ze sobą sporo kodu, i nie było sensu go duplikować. Oczywiście, z czasem wspólnego kodu było trochę mniej, i w końcu wsparcie starego trybu wyleciało — ale to już po ptakach.

(1/2)

So #Gentoo #Python eclasses are pretty modern, in the sense that they tend to follow the best practices and standards, and eventually deal with deprecations. Nevertheless, they have a long history and carry quite some historical burden, particularly regarding to naming.

The key point is that the eclasses were conceived as a replacement for the old eclasses: "distutils" and "python". Hence, much like we revision ebuilds, I've named the matching eclasses "distutils-r1" and "python-r1". For consistency, I've also used the "-r1" suffix for the remaining eclasses introduced at the time: "python-any-r1", "python-single-r1" and "python-utils-r1" — even though there were never "r0"s.

It didn't take long to realize my first mistake. I've made the multi-impl eclass effectively the "main" eclass, probably largely inspired by the previous Gentoo recommendations. However, in the end I've found out that for the most use cases (i.e. where "distutils-r1" is not involved), there is no real need for multi-impl, and it makes things much harder. So if I were naming them today, I would have named it "python-multi", to indicate the specific use case — and either avoid designating a default at all, or made "python-single" the default.

What aged even worse is the "distutils-r1" eclass. Admittedly, back when it was conceived, distutils was still largely a thing — and there were people (like me) who avoided unnecessary dependency on setuptools. Of course, nowadays it has been entirely devoured by setuptools, and with #PEP517 even "setuptools" wouldn't be a good name anymore. Nowadays, people are getting confused why they are supposed to use "distutils-r1" for, say, Hatchling.

Admittedly, this is something I could have done differently — PEP517 support was a major migration, and involved an explicit switch. Instead of adding DISTUTILS_USE_PEP517 (what a self-contradictory name) variable, I could have forked the eclass. Why didn't I do that? Because there used to be a lot of code shared between the two paths. Of course, over time they diverged more, and eventually I've dropped the legacy support — but the opportunity to rename was lost.

In fact, as a semi-related fact, I've recognized another design problem with the eclass earlier — I should have gone for two eclasses rather than one: a "python-phase" eclass with generic sub-phase support, and a "distutils" (or later "python-pep517") implementing default sub-phases for the common backends. And again, this is precisely how I could have solved the code reuse problem when I introduced PEP517 support.

But then, I didn't anticipate how the eclasses would end up looking like in the end — and I can't really predict what new challenges the Python ecosystem is going to bring us. And I think it's too late to rename or split stuff — too much busywork on everyone.

Ciekawostki o Pythonowym "limited API" i "stable ABI".

1. #CPython ma "limited API". Jak się tego używa, to kompilowane rozszerzenia są zgodne ze wskazaną wersją i wersjami nowszymi. Takie rozszerzenia dostają sufiks `.abi3.so` (albo podobny) zamiast np. `.cpython-313-x86_64-linux-gnu.so`.

2. Wsparcie podzielone jest między CPythona i systemy budowania #PEP517. Np. w #setuptools podaje się `py_limited_api=`, i wówczas przy budowaniu dodawane są odpowiednie flagi kompilatora i podmieniany jest sufiks rozszerzeń. #Meson ma coś podobnego.

3. Ale wersja "freethreading" aktualnie nie obsługuje "stable ABI", więc przy budowaniu z "limited API" dostaje się błąd kompilacji. Podobnie, setuptools rzuca błąd jeżeli z interpreterem freethreading podamy `py_limited_api`, a Meson po prostu pozwala się wysypać kompilacji. Tak więc autorzy paczek muszą sami sprawdzać, czy użyto kompilatora "freethreading", i wyłączyć wówczas "limited API".

4. Bliżej nieokreślona przyszła wersja CPythona naprawi to wsparcie. Nie przyglądałem się tematowi dokładnie, ale podejrzewam, że będzie to tylko możliwe, jeżeli będziemy budować rozszerzenia dla tej bądź nowszej wersji. Więc ludzie pewnie będą musieli budować dwie wersje — tę dla starszych CPythonów, i dla nowszych + "freethreading". No i oczywiście będzie trzeba odpowiednio zaktualizować warunkowe załączanie "limited API".

5. No i jest jeszcze #PyPy. PyPy nie ma "stable ABI", ale pozwala budować rozszerzenia z "limited API". Setuptools i Meson po prostu wykrywają, że interpreter nie obsługuje sufiksu `.abi3.so`, i buduje rozszerzenia z normalnym sufiksem.

#Python

Some fun facts about #Python limited API / stable ABI.

1. #CPython supports "limited API". When you use it, you get extensions that are compatible with the specified CPython version and versions newer than that. To indicate this compatibility, such extensions use `.abi3.so` suffix (or equivalent) rather than the usual `.cpython-313-x86_64-linux-gnu.so` or alike.

2. The actual support is split between CPython itself and #PEP517 build systems. For example, if you use #setuptools and specify `py_limited_api=` argument to the extension, setuptools will pass appropriate C compiler flags and swap extension suffix. There's a similar support in #meson, and probably other build systems.

3. Except that CPython freethreading builds don't support stable ABI right now, so building with "limited API" triggers an explicit error from the headers. Setuptools have opted for building explicit about this: it emits an error if you try to use `py_limited_api` on a freethreading interpreter. Meson currently just gives the compile error. This implies that package authors need to actively special-case freethreading builds and enable "limited API" conditionally.

4. A some future versions of CPython will support "limited API" in freethreading builds. I haven't been following the discussions closely, but I suspect that it will only be possible when you target that version or newer. So I guess people will need to be building two stable ABI wheels for a time — one targeting older Python versions, and one targeting newer versions plus freethreading. On top of that, all these projects will need to update their "no 'limited API' on freethreading" conditions.

5. And then there's #PyPy. PyPy does not feature a stable ABI, but it allows you to build extensions using "limited API". So setuptools and meson just detect that there is no `.abi3.so` on PyPy, and use regular suffix for the extensions built with "limited API".