Not long after I got punished with a commit bit, originally to do gnome@ and desktop@ stuff, another committer noticed that a Python package port they were maintaining stopped shipping a setup.py. Responding to the query posed in IRC, I got intrigued as to why this was, considering that setup.py is as ubiquitous as configure and Makefile.in or CMakeLists.txt or meson.build in many C projects. Turns out, a Python Enhancement Proposal, hereafter PEP, was adopted to overhaul how Python packages are built, in this case PEP 517, which most visibly obviated setup.py. A quick skim of PEP 517, some of its supporting PEPs and some examples later, and I became convinced that this was superior to setup.py. But what is a setup.py anyway? The ports system generally follows a build process typical of C projects: do-configure, do-build, do-install. The setup.py support in the ports framework itself follows this pattern with USE_PYTHON=distutils. In fact, what makes setup.py tick and provides all the structure is distutils, a now-deprecated module in the base Python distribution removed in 3.12. (All of its functionality has been subsumed into setuptools, an external Python package, and we use it as such despite not changing the USE_PYTHON.) distutils provides an execution structure reminiscent of configure and Makefiles: setup.py configure, setup.py build, setup.py install. As time wore on, the Python community developed better tooling around packaging such that direct setup.py invocation became deprecated despite its facilities being completely functional (not least for our benefit), but serious architectural issues developed when individual Python projects needed more elaborate build processes and dependency specifiers, amongst other things. Parallel to all this, PEP 427 introduced the wheel Python packaging format, replacing eggs specific to distutils/setuptools. [quote the "Rationale" section from PEP 427 mostly] Also in parallel, parts of the Python community wanted something simpler build backends for their project than setuptools, which can feel like doing too much. Enter PEP 517. Rather than writing out effectively a complete configure and Makefile, PEP 517 and supporting cast introduce a declarative pyproject.toml. This design is agnostic to any particular build backend, allowing individual projects to choose which one (and their plugins) best suits them, or even homebrew one of their own in-tree. As long as a source distribution and binary distribution, both as wheels, can result, the build backend is compliant. In the ports framework, chiefly to ease the learning curve between distutils and PEP 517, care was taken to ensure that most things felt similar. With USE_PYTHON=pep517 set, do-configure is eliminated, as any configure "step" is part of the build backend's machinery. do-build calls on py-build to parse pyproject.toml, validate that the appropriate dependencies are present, then execute the specified build backend. The build backend is specified as a regular BUILD_DEPENDS. We only want a resulting binary distribution here, which is the default. Once the binary wheel is written, do-install calls on py-installer to install the package into the stage directory.