Then there is the problem of there not being a standard dependency management system. Your `setup.py` can specify version constraints. You either over-constrain in there or have to add a whole separate process for locking your constraint.
- You could use `pip-compile` to get a platform-specific locking of constraints, requiring you to run this for every platform and python version you support. At least, since you duplicate `setup.py` into a `requirements.in`, you can override transitive dependencies.
- You could use `pipenv` and just capture what you happened to install, from constraints or directly, from a specific machine
- You could use Poetry which solves most of these problems except they've put their heads in the sand regarding how bad versioning is within the Python ecosystem and refuse to support overriding transitive dependencies despite being modeled off of Rust's Cargo which does support it despite the Rust ecosystem being good with versioning [1]
If you're setting just constraints but not a specific version, then you're not pinning.