Commit 792a4b5d authored by Gary Poster's avatar Gary Poster

add explanatory comments; extend test to show that scripts honor explicit PYTHONPATH

parent 3f3925dd
...@@ -32,16 +32,20 @@ if sys.platform == 'win32': ...@@ -32,16 +32,20 @@ if sys.platform == 'win32':
else: else:
quote = str quote = str
# In order to be more robust in the face of system Pythons, we want to run # In order to be more robust in the face of system Pythons, we want to
# with site-packages loaded. This is somewhat tricky, in particular because # run without site-packages loaded. This is somewhat tricky, in
# Python 2.6's distutils imports site, so starting with the -S flag is not # particular because Python 2.6's distutils imports site, so starting
# sufficient. # with the -S flag is not sufficient. However, we'll start with that:
if 'site' in sys.modules: if 'site' in sys.modules:
# We will restart with python -S. # We will restart with python -S.
args = sys.argv[:] args = sys.argv[:]
args[0:0] = [sys.executable, '-S'] args[0:0] = [sys.executable, '-S']
args = map(quote, args) args = map(quote, args)
os.execv(sys.executable, args) os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:] clean_path = sys.path[:]
import site import site
sys.path[:] = clean_path sys.path[:] = clean_path
......
...@@ -30,16 +30,20 @@ if sys.platform == 'win32': ...@@ -30,16 +30,20 @@ if sys.platform == 'win32':
else: else:
quote = str quote = str
# In order to be more robust in the face of system Pythons, we want to run # In order to be more robust in the face of system Pythons, we want to
# with site-packages loaded. This is somewhat tricky, in particular because # run without site-packages loaded. This is somewhat tricky, in
# Python 2.6's distutils imports site, so starting with the -S flag is not # particular because Python 2.6's distutils imports site, so starting
# sufficient. # with the -S flag is not sufficient. However, we'll start with that:
if 'site' in sys.modules: if 'site' in sys.modules:
# We will restart with python -S. # We will restart with python -S.
args = sys.argv[:] args = sys.argv[:]
args[0:0] = [sys.executable, '-S'] args[0:0] = [sys.executable, '-S']
args = map(quote, args) args = map(quote, args)
os.execv(sys.executable, args) os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:] clean_path = sys.path[:]
import site import site
sys.path[:] = clean_path sys.path[:] = clean_path
......
...@@ -903,6 +903,11 @@ class Buildout(UserDict.DictMixin): ...@@ -903,6 +903,11 @@ class Buildout(UserDict.DictMixin):
if not __debug__: if not __debug__:
args.insert(0, '-O') args.insert(0, '-O')
args.insert(0, zc.buildout.easy_install._safe_arg(sys.executable)) args.insert(0, zc.buildout.easy_install._safe_arg(sys.executable))
# We want to make sure that our new site.py is used for rerunning
# buildout, so we put the partsdir in PYTHONPATH for our restart.
# This overrides any set PYTHONPATH, but since we generally are
# trying to run with a completely "clean" python (only the standard
# library) then that should be fine.
env = os.environ.copy() env = os.environ.copy()
env['PYTHONPATH'] = partsdir env['PYTHONPATH'] = partsdir
if is_jython: if is_jython:
......
...@@ -99,6 +99,9 @@ def _get_system_paths(executable): ...@@ -99,6 +99,9 @@ def _get_system_paths(executable):
"print repr([os.path.normpath(p) for p in sys.path if p])"]) "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. # Windows needs some (as yet to be determined) part of the real env.
env = os.environ.copy() env = os.environ.copy()
# We need to make sure that PYTHONPATH, which will often be set
# to include a custom buildout-generated site.py, is not set, or
# else we will not get an accurate sys.path for the executable.
env.pop('PYTHONPATH', None) env.pop('PYTHONPATH', None)
env.update(kwargs) env.update(kwargs)
_proc = subprocess.Popen( _proc = subprocess.Popen(
...@@ -1487,6 +1490,10 @@ def _get_module_file(executable, name): ...@@ -1487,6 +1490,10 @@ def _get_module_file(executable, name):
"fp.close; " "fp.close; "
"print path" % (name,)] "print path" % (name,)]
env = os.environ.copy() env = os.environ.copy()
# We need to make sure that PYTHONPATH, which will often be set to
# include a custom buildout-generated site.py, is not set, or else
# we will not get an accurate value for the "real" site.py and
# sitecustomize.py.
env.pop('PYTHONPATH', None) env.pop('PYTHONPATH', None)
_proc = subprocess.Popen( _proc = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
......
...@@ -2294,6 +2294,51 @@ This also works for the generated interpreter. ...@@ -2294,6 +2294,51 @@ This also works for the generated interpreter.
3 3
<BLANKLINE> <BLANKLINE>
If you have a PYTHONPATH in your environment, it will be honored, after
the buildout-generated path.
>>> original_pythonpath = os.environ.get('PYTHONPATH')
>>> os.environ['PYTHONPATH'] = 'foo'
>>> test = (
... "import subprocess, sys; subprocess.call("
... "[sys.executable, '-c', "
... "'import sys, pprint; pprint.pprint(sys.path)'])")
>>> 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. As you can see, /sample_buildout/foo is included
right after the "parts" directory that contains site.py and sitecustomize.py.
You can also see, actually more easily than in the other example, that we
have the desired eggs available.
>>> print system(join(interpreter_bin_dir, 'demo')), # doctest: +ELLIPSIS
['',
'/interpreter/parts/interpreter',
'/sample-buildout/foo',
...
'/interpreter/eggs/demo-0.3-pyN.N.egg',
'/interpreter/eggs/demoneeded-1.1-pyN.N.egg']
This also works for the generated interpreter, with identical results.
>>> print call_py(join(interpreter_bin_dir, 'py'), test),
... # doctest: +ELLIPSIS
['',
'/interpreter/parts/interpreter',
'/sample-buildout/foo',
...
'/interpreter/eggs/demo-0.3-pyN.N.egg',
'/interpreter/eggs/demoneeded-1.1-pyN.N.egg']
>>> # Cleanup
>>> if original_pythonpath:
... os.environ['PYTHONPATH'] = original_pythonpath
... else:
... del os.environ['PYTHONPATH']
...
""" """
def bootstrap_makes_buildout_that_works_with_system_python(): def bootstrap_makes_buildout_that_works_with_system_python():
......
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