Code review comment for lp:~gary/zc.buildout/python-support-4

Gary Poster (gary) wrote :

This is a completely reworked approach to using zc.buildout with a system Python (or any Python with a populated site packages directory), deprecating my previous attempt.

The basic approach revolves around writing our own site.py and sitecustomize.py that are responsible for setting up paths and any other environment changes desired. Then if the path to these rewritten files are included (via PYTHONPATH, or with -S followed by sys.path manipulation and ``import site``) you have the environment set up, using the standard Python mechanism.

Similarly to my past work, the point that got complicated was namespace packages. The solution shown here is straightforward, as you can see in the easy_install.txt discussion.

However, if you try to use a system Python, you expose its packages using ``add-site-packages=true``, and you use eggs with namespace packages, it will incur a startup cost for generated scripts that is quadratically related to the number of eggs added by zc.buildout, because of code in pkg_resources. (We also have that same behavior now in Launchpad.) While I did a number of experiments to try and bypass the inefficiencies of the pkg_resources code, I discarded them, because Launchpad is using pkg_resources and expects it to be fully set up. Other code may be the same. The right solution is to fix pkg_resources, in Setuptools or Distribute, at which point the approach I have in this branch should still work, and be much faster.

I did punt a bit in the Windows version of the new interpreter script: I could not get the standard Windows path hacks to work for sys.exec*. I used subprocess instead for Windows, and commented this section heavily.

Obviously, this is a huge branch. I did not see a good way of subdividing it beyond what I already did (~gary/zc.buildout/python-support-1-cleanup, ~gary/zc.buildout/python-support-2-bootstrap, and ~gary/zc.buildout/python-support-3-options). I did consider the following subdivision:

- First, you could look at the changes to easy_install.py and easy_install.txt. This is the heart of the changes. It refactors the existing script generation into bits I could reuse more easily, and then makes a new version script generation function (``generated_scripts``) that works as I describe above.

- Second, you could look at zc.recipe.egg and z3c.recipe.scripts. zc.recipe.egg is refactored so I could reuse bits more easily. z3c.recipe.scripts is a brand new recipe that uses generate_scripts, as described above.

- Finally, you could look at the new tests and test changes in zc.buildout. They use zc.recipe.egg and z3c.recipe.scripts to test that system installs can work as desired--essentially showing that all of the earlier work does in fact produce a system that does what we want.

I didn't feel that separating them made a lot of sense, because you could not test whether generate_scripts actually did what we wanted until we had z3c.recipe.scripts also available. The changes are all interrelated.

Something to note is that zc.recipe.egg does not have any changed behavior. Also, it is not safe to use with a system Python. If you want that behavior for scripts and interpreters, use z3c.recipe.scripts instead. This arrangement should mean that previous usage of zc.buildout is entirely backwards compatible.

I have these branches submitted to Jim Fulton for review. I have no idea how that will turn out.

The Launchpad branch that uses this code is https://code.edge.launchpad.net/~gary/launchpad/bug491705 . Tests pass on ec2.

« Back to merge proposal