Packaging Python software with pbr
julien.danjou.info
julien.danjou.info
I'd much more recommend reading through https://python-packaging.readthedocs.io/en/latest/index.html to actually understand how packaging works.
That said... packaging stuff in Python could really do with being a lot simpler. Pbr just doesn't seem to make it simpler, it just moves the problem to a different file.
with codecs.open('requirements.txt') as f:
requirements = f.read().splitlines()
...
install_requires=requirements,
I don't think it's worth the dependency. But perhaps for others it is.In case anyone sees this, at a minimum you need to use
from pip.req import parse_requirements
parse_requirements('path/to/requirements.txt')
to be safe here.from my understanding, when you build the package, your computer extracts the relevant required packages, and sends up that data to pypi, which then in turn sends that data back to users when they install
At least thats how I think it works
if you used any other package manager, it would need to resolve dependencies from the additional info in the package index, resulting in pip being downloaded and installed before the desired package is installed
If you control requirements.txt, there is nothing "not robust" about parsing it in setup.py.
You can also use `dependency_links` in your setup.py to specify this, which allows deps on github etc.
Define my dependencies
- setup.py
- requirements_dev.in
run piptools pip-compile to generate a locked set of dependencies
- requirements.txt
- requirements_dev.txt
It gives me some of the benefit of Rust's Cargo.toml / Cargo.lock in the python world (and actually respects all package's dependency version declarations unlike other tools like pyup).
If you think packaging is a matter of configuration, then PBR makes a lot of sense. It gives you a config file that you simply fill out so you don't have to worry yourself about the code.
I've used both PBR and setup.py quite a bit and I personally prefer PBR since there's less things I need to debug when things go wrong.
You fail to give any examples as to why it would be an improvement too, aside from a very vague "less things I need to debug when things go wrong". Which I'd argue against since now I also need to potentially worry about things going wrong in PBR, which is one more thing I need to debug. This seems to be the general theme with pbr, there's no clear reasons for why it's better and when asked about it you get these kind of hand-wavy answers.
If you actually have some concrete examples as to what it improves and why I'm all ears.
Trying to paper over the (real) problems with the Python packaging toolchain by generating setup.py from a config file strikes me as a vanity project.
Are you really implying that learning INI would be a burden?
That along with setuptools-scm and pip-tools have for me solved most of the issues that pbr addresses.
First of all, requirements.txt is for development requirements. Runtime ones belong in setup.py.
Also, the "extras" feature is already in setup.py via extras_require.
I see no need to use this nonstandard tool when the standard tooling works.
requirements/
/base.txt
/test.txt
/docs.txt
Then in setup.py just read these requirements.txt. I just find this easier to manage all the dependencies from a single point. During development and testing code, you'd assume base.txt is what is going to production. It takes some care to commit this file, nonetheless.I could keep a freeze version if I really want to have a full view (for debugging purpose).
I used to think this was a good idea. Then I found a huge loophole in it: if I copy-paste code from another FLOSS project, then that code's author should still be listed, but won't have any commits.
Also, peer-programming.
> version management based on git tags
setuptools-scm already does this for us.
Finally, a big upside of setup.py, is that I can programatically generate information, whereas pbr's cfg file doesn't seem to allow that.
flavors are listed as a big deal, but much like the article says, setuptools already has this, nothing new here.
The problem with package manifests that are arbitrary scripts (Python, Ruby and probably others) is that you lose even basic introspectability into rudimentary parameters like name, version, dependencies unless your threat model allows for executing random code that people put into the setup.py. This can be mitigated by using complex static analysis carefully crafted for the specific task, but this isn't easy to implement and there is a non-insignificant amount of cases where the data cannot be legitimately decided. I'm just wondering how this is conceptually different from Pipfiles:
https://github.com/pypa/pipfile (Previous discussion https://news.ycombinator.com/item?id=13011932)
>I used to think this was a good idea. Then I found a huge loophole in it: if I copy-paste code from another FLOSS project, then that code's author should still be listed, but won't have any commits.
If you think that the other person deserves all the credit for the change, set the author with:
git commit --author="Guido van Rossum <guido@python.org>"
If you deserve the responsibility/credit/blame for the commit, give credit to the other person in such a way pbr will pick it up, by adding to your commit message: Co-authored-by: Guido van Rossum <guido@python.org>You still need to install system files for those c line. You still can't have multiple packages requiring different versions of libraries. What a mess.
I guess your second point means something like symbol versioning for Python libraries, which I'm not aware of any solution to, apart from just running things in a virtualenv.
[1] https://docs.openstack.org/infra/bindep/readme.html [2] https://github.com/openstack-infra/project-config/blob/maste...