This is, in part, a follow up to my post a few weeks ago.
I want to touch on the things we need to improve to have robust plumbing supporting openstack’s CI and devstack needs.
Extras
We want to be able to use ‘extras’ to declare the dependencies needed for different backends. This is a setuptools requirement syntax where a project can advertise additional dependencies for different use cases, which users (or other depending projects) can then trigger using '[]'
. E.g. 'pip install requests[security]'
says ‘install requests and the additional ‘security’ extras. We don’t know yet whether we will use 'nova[mysql]'
or 'nova oslo.db[mysql]'
, but something like that. To use this we need to:
- teach pbr about reflecting requirements into the
'extras_require'
keyword to setup (because while setuptools supports it in setup.py, we want a constant value setup.py with everything about individual projects declarative). James Polley has a patch for pbr. - Fix pip to handle
'pip install ./nova[mysql]'
. This is issue 1236 – which has an open PR that may fix it. We should help review and test it.
Testing different setups may well need a similar facility, but its not clear yet how to best express that. We may need to standardise on using an extra called 'test'
and just ensure our tox.ini
knows to install that. That would be nice anyway, to get away from having to know about 'test_requirements.txt'
.
pip dependency resolution
Currently pip has a very straight forward resolution algorithm: Only user supplied requirements can conflict at all, and the first mention of any distribution causes a distribution to be selected that matches that mention – all other mentions are simply ignored. This is issue 988, and its one of a cluster that affect OpenStack. The impact on OpenStack is that we have things install ok with pip, and then break in CI, because an incompatible version is installed. I have a patch up for this. Early adopters solicited!
incremental installations need dependency resolution
Say you’ve installed Neutron
, which depends on oslo.db >=1.10
. And you then install an older Nova
which depends on oslo.db <1.10
. What should happen? Ideally an error in this case, because the requirements are disjoint. And if they do overlap, the installed version should be adjusted to be compatible. Right now, no error occurs and oslo.db
will be downgraded breaking Neutron
. This is pip issue 2687. Currently no-one is working on this, and since it requires dependency resolution, fixing 988 first makes a lot of sense. It should be possible to at least make things error with a much more shallow patch though, if someone wished to work on it right now – or you could build on top of my resolver branch. This has also been a cause of numerous CI failures when we do releases, typically right around the time the servers branch. One thing that might be nice for us, since we know a full set of working packages, is to be able to say upfront to pip what versions are compatible, and then let only the needed things be brought in. pip issue 2731
PEP-426 environment markers need polish
PEP-426 introduced a micro-language for describing the situations when a particular dependency applies. For instance, to use argparse on Python < 2.7, you can say "python_version<'2.7'" as a marker for the argparse entry in your requirements. But there are some rough edges.
- Some comparison operators are missing.
- The documentation and user guidance needs improvement.
- Environment markers can’t be used inside individual requirements, only as a filter on
extra_requires
. To express the argparse example above today (using a working operator), you need to pass the following tosetup()
.extra_requires={':python_version=="2.6"': ['argparse']}
It would be more straightforward to permit the syntax pip supports, where each requirement can be annotated with a marker.
install_requires=['argparse:python_version=="2.6"']
This might be setuptools issue 353.
- pbr doesn’t reflect environment markers from its input files (requirements.txt etc) into setup keyword argument. James Polley has a patch for this (the same one enabling extras support in
setup.cfg
).
pip handling setup_requires
We run into setup_requires
in two places in OpenStack; firstly we use that ourselves for pbr, but to avoid triggering easy_install we manually install pbr everywhere ourselves. Secondly, projects that are in the transitive dependencies of OpenStack use setup_requires
, and we end up triggering easy_install for them. easy_install is a concern for us because of the decreased reliability and issues with corporate egress firewalls, and its security is not as robust as pips – and there’s no reason it should be, with pip being such a good tool.
However pip can’t handle setup_requires
today. Doing so requires changes to setuptools and to pip.
- setuptools needs some way to report to pip what the
setup_requires
are without triggering easy_install. Ronny Pfannschmidt has mentioned he may be working on this, but I’m not sure if there is a patch ready or not. A possible further enhancement would be to put thesetup_requires
insetup.cfg
in a totally declarative fashion, but this may require environment marker support first, since the current procedural approach is very flexible and can take Python version and platform into account. - pip needs to be able to temporarily put things that it won’t be installing into the PYTHONPATH for packages it is building. The current internals are not suited for this (the target and source and needs of requirements being downloaded are all confounded). However once my resolver patch lands, there will be a nice cache layer that can deliver a ready-to-install directory for any requirement, which should make a simple recursive implementation quite reasonable. The resolver work will probably need further refactoring to make the resolver be decoupled from the user supplied requirements, but compared to the ground already covered, that should be straight forward. One thing folk tackling this should be aware of is an open question around location requirements. Say someone is installing
foo
from a git repository. Andfoo
is also a setup requirement of some other packagebar
being installed at the same time. Should thatfoo
from git be used for the setup ofbar
? I’m not sure of the answer (what if the version of foo is incompatible with version bar needs?) – but one is needed :).
So thats about it – if you’re interested in helping the plumbing that supports OpenStacks CI and devstack systems, please pick one of these issues and help out. Test patches, review code, write a patch, or just tell me why we don’t need to do something :)
Image may be NSFW.
Clik here to view.
Clik here to view.
