The Python packaging ecosystem is 25+ years old, and was largely informally specified until ~12 years ago. Most of the complexity in Python packaging can be traced back to (1) a large degree of pre-existing permissive behavior that needed to be encoded in early standards to get standardization off the ground, and (2) the fact that Python packaging is still largely federated, with multiple independent groups performing tool development (and interpreting the standards).
(2) has historically also been a strength of Python packaging, and has been a big source of modernization efforts over the years that (IMO) have made packaging much better: things like pyproject.toml, build backends, etc.
(I think there have been a few recap talks at PyCon over the years on packaging's history. There are definitely people way more qualified than me to provide a more detailed summary :-)).
One example, Semantic Versioning and odd/even versioning, where 3.1 is considered unstable, versus 3.2 is considered stable, versus 3.3 unstable, etc. This was standardized only in 2010, so we can't blame Python developers for not foreseeing that in 2000.
The odd vs even versions rule you describe, while followed by a few projects, is not part of Semantic Versioning (aka SemVer) - there's no mention of it whatsoever in the spec at https://semver.org/.
Indeed it is basically incompatible with SemVer given that SemVer has its own way of marking unstable versions (or, equivalently, pre-release versions; SemVer conflates the two concepts). Unstable/pre-release versions under SemVer are indicated by a hyphenated suffix after the patch version - e.g. 1.2.3-alpha
Right -- one of Python (packaging's) small ironies is that people sometimes forget how old the Python ecosystem is, in part because the ecosystem and language have managed to keep up with the times :-)
(If we use similarly-aged interpreted languages as a benchmark, I would say that Python packaging has modernized admirably in some aspects: compare CPAN, for example.)
- Minimal standardization of ways to cache pre-built artifacts for modules with binary/XS components (no widely adopted wheel equivalent).
- Extremely poor support in cpan-the-tool for multiple local::lib environments.
- Abject lack of standardization on how hermetic/isolated (or not) builds involving linking to native libraries/compiling code should be. Talking super simple stuff here: what path-related envs to inherit, when module build scripts should hardcode vs. use system-path-discoverable versions of common C toolchain components, stuff like that.
- Standardization on build tools ("backends" in Python parlance) is poor. Module::Build is "the future", but lots of stuff seems not to use it. ExtUtils::MakeMaker is ... not good, and alternatives seem to be all over the place in terms of supportedness (I've heard Dist::Zilla is good, never tried it; spent plenty of time with SWIG hassles though). This is a low bar, and Perl trips over it. To be fair, so does Python.
- No uninstallation support (because there's no standardized manifest format). Sure, cpanminus exists (mirroring the annoyance that is e.g. conda competing with pip in Python), and even then uninstallation is dicey.
- Uninstallation troubles hint at the larger issue: CPAN packages are, if you zoom out far enough, shell/perl scripts that perform arbitrary system modifications. As jsiracusa used to say when we worked together, "they're file sprayers, not packages". If you want anything more predictable (or less dangerous) than that, you're out of luck unless you follow a very narrow path which many packages and deployment environments may not be compatible with.
- TMTOWTDI doesn't help here; even simple pure-perl modules have piss poor consistency re: how they install, so answering questions like "what will installation of Some::Module make available" is harder than it needs to be because maintainers are by turns over-clever and using dated methodologies for packaging their code.
- For reproducibility, cpan-the-tool's stance on lockfiles and hashes seems to be "what the fuck is a lockfile?". Given poor CPAN-wide compliance with Semver or equivalent conventions, that makes builds that need to happen in different environments (e.g. local, docker, CI, production) needlessly complicated.
- MacOS support for many common libraries with XS/native components is very poor even by Python's (nightmarishly bad until c. 2019, when tools matured even though the advent of ARM macs made it feel like they didn't) standard.
I sincerely hope that stuff has improved in the Perl community since I last tangled with CPAN issues on the regular (around 5.18/5.20). But given the increasing number of lonely tumbleweeds drifting around CPAN and the Perl community's tendencies in general, I won't hold my breath.
(2) has historically also been a strength of Python packaging, and has been a big source of modernization efforts over the years that (IMO) have made packaging much better: things like pyproject.toml, build backends, etc.
(I think there have been a few recap talks at PyCon over the years on packaging's history. There are definitely people way more qualified than me to provide a more detailed summary :-)).