Commit 89cc72e5 authored by Gary Poster's avatar Gary Poster

set up PYTHONPATH for scripts too, so subprocesses are good to go by default.

parent 9ed408ec
......@@ -355,7 +355,9 @@ class Buildout(UserDict.DictMixin):
if options.get('offline') == 'true':
ws = zc.buildout.easy_install.working_set(
distributions, options['executable'],
[options['develop-eggs-directory'], options['eggs-directory']]
[options['develop-eggs-directory'],
options['eggs-directory']],
include_site_packages=False,
)
else:
ws = zc.buildout.easy_install.install(
......@@ -365,7 +367,8 @@ class Buildout(UserDict.DictMixin):
executable=options['executable'],
path=[options['develop-eggs-directory']],
newest=self.newest,
allow_hosts=self._allow_hosts
allow_hosts=self._allow_hosts,
include_site_packages=False,
)
# Now copy buildout and setuptools eggs, and record destination eggs:
......@@ -1034,7 +1037,8 @@ def _install_and_load(spec, group, entry, buildout):
path=path,
working_set=pkg_resources.working_set,
newest=buildout.newest,
allow_hosts=buildout._allow_hosts
allow_hosts=buildout._allow_hosts,
include_site_packages=False,
)
__doing__ = 'Loading %s recipe entry %s:%s.', group, spec, entry
......
......@@ -99,6 +99,7 @@ def _get_system_paths(executable):
"print repr([os.path.normpath(p) for p in sys.path if p])"])
# Windows needs some (as yet to be determined) part of the real env.
env = os.environ.copy()
env.pop('PYTHONPATH', None)
env.update(kwargs)
_proc = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
......@@ -337,9 +338,6 @@ class Installer:
self._site_packages))
if self._include_site_packages:
path.extend(self._site_packages)
# else we could try to still include the buildout_and_setuptools_path
# if the elements are not in site_packages, but we're not bothering
# with this optimization for now, in the name of code simplicity.
if dest is not None and dest not in path:
path.insert(0, dest)
self._path = path
......@@ -1184,9 +1182,9 @@ def sitepackage_safe_scripts(
generated.append(_generate_site(
site_py_dest, working_set, executable, extra_paths,
include_site_packages, relative_paths))
script_initialization = (
'\nimport site # imports custom buildout-generated site.py\n%s' % (
script_initialization,))
script_initialization = _script_initialization_template % dict(
site_py_dest=site_py_dest,
script_initialization=script_initialization)
if not script_initialization.endswith('\n'):
script_initialization += '\n'
generated.extend(_generate_scripts(
......@@ -1197,6 +1195,15 @@ def sitepackage_safe_scripts(
interpreter, dest, executable, site_py_dest, relative_paths))
return generated
_script_initialization_template = '''
import site # imports custom buildout-generated site.py
import os
path = %(site_py_dest)r
if os.environ.get('PYTHONPATH'):
path = os.pathsep.join([path, os.environ['PYTHONPATH']])
os.environ['PYTHONPATH'] = path
%(script_initialization)s'''
# Utilities for the script generation functions.
# These are shared by both ``scripts`` and ``sitepackage_safe_scripts``
......
......@@ -1499,6 +1499,11 @@ The demo script runs the entry point defined in the demo egg:
<BLANKLINE>
<BLANKLINE>
import site # imports custom buildout-generated site.py
import os
path = '/interpreter/parts/interpreter'
if os.environ.get('PYTHONPATH'):
path = os.pathsep.join([path, os.environ['PYTHONPATH']])
os.environ['PYTHONPATH'] = path
<BLANKLINE>
import eggrecipedemo
<BLANKLINE>
......@@ -1528,7 +1533,7 @@ Let's see ``script_arguments`` and ``script_initialization`` in action.
>>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
... reqs=['demo'], script_arguments='1, 2',
... script_initialization='import os\nos.chdir("foo")')
... script_initialization='import os\nos.chdir("foo")')
>>> cat(demo_path) # doctest: +NORMALIZE_WHITESPACE
#!/usr/local/bin/python2.4 -S
......@@ -1539,6 +1544,11 @@ Let's see ``script_arguments`` and ``script_initialization`` in action.
<BLANKLINE>
import site # imports custom buildout-generated site.py
import os
path = '/interpreter/parts/interpreter'
if os.environ.get('PYTHONPATH'):
path = os.pathsep.join([path, os.environ['PYTHONPATH']])
os.environ['PYTHONPATH'] = path
import os
os.chdir("foo")
<BLANKLINE>
import eggrecipedemo
......
......@@ -2254,8 +2254,50 @@ include-site-packages.
"""
def bootstrap_makes_buildout_that_works_with_system_python():
def subprocesses_have_same_environment_by_default():
"""
The scripts generated by sitepackage_safe_scripts set the PYTHONPATH so that,
if the environment is maintained (the default behavior), subprocesses get
the same Python packages.
First, we set up a script and an interpreter.
>>> interpreter_dir = tmpdir('interpreter')
>>> interpreter_parts_dir = os.path.join(
... interpreter_dir, 'parts', 'interpreter')
>>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin')
>>> mkdir(interpreter_bin_dir)
>>> mkdir(interpreter_dir, 'eggs')
>>> mkdir(interpreter_dir, 'parts')
>>> mkdir(interpreter_parts_dir)
>>> ws = zc.buildout.easy_install.install(
... ['demo'], join(interpreter_dir, 'eggs'), links=[link_server],
... index=link_server+'index/')
>>> test = (
... "import subprocess, sys; subprocess.call("
... "[sys.executable, '-c', "
... "'import eggrecipedemo; print eggrecipedemo.x'])")
>>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
... reqs=['demo'], interpreter='py',
... script_initialization=test + '; sys.exit(0)')
This works for the script.
>>> print system(join(interpreter_bin_dir, 'demo'))
3
<BLANKLINE>
This also works for the generated interpreter.
>>> print call_py(join(interpreter_bin_dir, 'py'), test)
3
<BLANKLINE>
"""
def bootstrap_makes_buildout_that_works_with_system_python():
r"""
In order to work smoothly with a system Python, bootstrapping creates
the buildout script with
zc.buildout.easy_install.sitepackage_safe_scripts. If it did not, a
......@@ -2274,15 +2316,11 @@ First let's write a dummy recipe.
>>> write(sample_buildout, 'recipes', 'dummy.py',
... '''
... import logging, os, zc.buildout
...
... class Dummy:
...
... def __init__(self, buildout, name, options):
... pass
...
... def install(self):
... return ()
...
... def update(self):
... pass
... ''')
......@@ -2340,6 +2378,67 @@ Now, it is handled smoothly.
Installing dummy.
<BLANKLINE>
Here's the same story with a namespace package, which has some additional
complications behind the scenes. First, a recipe, in the "tellmy" namespace.
>>> mkdir(sample_buildout, 'ns')
>>> mkdir(sample_buildout, 'ns', 'tellmy')
>>> write(sample_buildout, 'ns', 'tellmy', '__init__.py',
... "__import__('pkg_resources').declare_namespace(__name__)\n")
>>> mkdir(sample_buildout, 'ns', 'tellmy', 'recipes')
>>> write(sample_buildout, 'ns', 'tellmy', 'recipes', '__init__.py', ' ')
>>> write(sample_buildout, 'ns', 'tellmy', 'recipes', 'dummy.py',
... '''
... import logging, os, zc.buildout
... class Dummy:
... def __init__(self, buildout, name, options):
... pass
... def install(self):
... return ()
... def update(self):
... pass
... ''')
>>> write(sample_buildout, 'ns', 'setup.py',
... '''
... from setuptools import setup
... setup(
... name="tellmy.recipes",
... packages=['tellmy', 'tellmy.recipes'],
... install_requires=['setuptools'],
... namespace_packages=['tellmy'],
... entry_points = {'zc.buildout':
... ['dummy = tellmy.recipes.dummy:Dummy']},
... )
... ''')
Now, a buildout that uses it.
>>> create_sample_namespace_eggs(sample_eggs, site_packages_path)
>>> rmdir('develop-eggs')
>>> from zc.buildout.testing import make_buildout
>>> make_buildout(executable=py_path)
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... develop = ns
... recipes
... parts = dummy
... find-links = %(link_server)s
... executable = %(py_path)s
...
... [dummy]
... recipe = tellmy.recipes:dummy
... ''' % globals())
Now we actually run the buildout.
>>> print system(buildout)
Develop: '/sample-buildout/ns'
Develop: '/sample-buildout/recipes'
Uninstalling dummy.
Installing dummy.
<BLANKLINE>
"""
if sys.version_info > (2, 4):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment