eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/virtualenv.txt
changeset 307 c6bca38c1cbf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/virtualenv.txt	Sat Jan 08 11:20:57 2011 +0530
@@ -0,0 +1,257 @@
+Version 1.5.0 of buildout (and higher) provides the ability to use
+buildout directly with a system Python if you use z3c.recipe.scripts or
+other isolation-aware recipes that use the sitepackage_safe_scripts function.
+
+Some people use virtualenv to provide similar functionality.
+Unfortunately, a problem with the virtualenv executable as of this
+writing means that -S will not work properly with it (see
+https://bugs.launchpad.net/virtualenv/+bug/572545). This breaks
+buildout's approach to providing isolation.
+
+Because of this, if buildout detects an executable with a broken -S
+option, it will revert to its pre-1.5.0 behavior.  If buildout has been
+asked to provide isolation, it will warn the user that isolation will
+not be provided by buildout, but proceed.  This should give full
+backwards compatibility to virtualenv users.
+
+The only minor annoyance in the future may be recipes that explicitly
+use the new buildout functionality to provide isolation: as described
+above, the builds will proceed, but users will receive warnings that
+buildout is not providing isolation itself.  The warnings themselves can
+be squelched when running bin/buildout with the ``-s`` option or with a
+lower verbosity than usual (e.g., one or more ``-q`` options).
+
+For tests, then, we can examine several things.  We'll focus on four.
+
+- Running bootstrap with an executable broken in this way will not try to do
+  any -S tricks.
+
+- Running sitepackage_safe_scripts with a virtualenv will create an
+  old-style script.  This will affect the bin/buildout script that is
+  created, for instance.  If the sitepackage_safe_scripts function is asked
+  to provide isolation under these circumstances, it will warn that isolation
+  will not be available, but still create the desired script.
+
+- Using the easy_install Installer or install or build functions and trying
+  to request isolation will generate a warning and then the isolation request
+  will be ignored as it proceeds.
+
+- Passing -s (or -q) to the bin/buildout script will squelch warnings.
+
+Testing these involves first creating a Python that exhibits the same
+behavior as the problematic one we care about from virtualenv.  Let's do that
+first.
+
+    >>> import os, sys
+    >>> from zc.buildout.easy_install import _safe_arg
+    >>> py_path, site_packages_path = make_py()
+    >>> if sys.platform == 'win32':
+    ...     py_script_path = py_path + '-script.py'
+    ... else:
+    ...     py_script_path = py_path
+    ...
+    >>> py_file = open(py_script_path)
+    >>> py_lines = py_file.readlines()
+    >>> py_file.close()
+    >>> py_file = open(py_script_path, 'w')
+    >>> extra = '''\
+    ... new_argv = argv[:1]
+    ... for ix, val in enumerate(argv[1:]):
+    ...     if val.startswith('--'):
+    ...         new_argv.append(val)
+    ...     if val.startswith('-') and len(val) > 1:
+    ...         if 'S' in val:
+    ...             val = val.replace('S', '')
+    ...             environ['BROKEN_DASH_S'] = 'Y'
+    ...         if val != '-':
+    ...             new_argv.append(val)
+    ...         if 'c' in val:
+    ...             new_argv.extend(argv[ix+2:])
+    ...             break
+    ...     else:
+    ...         new_argv.extend(argv[ix+1:])
+    ... argv = new_argv
+    ... '''
+    >>> for line in py_lines:
+    ...     py_file.write(line)
+    ...     if line.startswith('environ = os.environ.copy()'):
+    ...         py_file.write(extra)
+    ...         print 'Rewritten.'
+    ...
+    Rewritten.
+    >>> py_file.close()
+    >>> sitecustomize_path = join(os.path.dirname(site_packages_path),
+    ...                           'parts', 'py', 'sitecustomize.py')
+    >>> sitecustomize_file = open(sitecustomize_path, 'a')
+    >>> sitecustomize_file.write('''
+    ... import os, sys
+    ... sys.executable = %r
+    ... if 'BROKEN_DASH_S' in os.environ:
+    ...     class ImportHook:
+    ...         site = None
+    ...
+    ...         @classmethod
+    ...         def find_module(klass, fullname, path=None):
+    ...             if klass.site is None and 'site' in sys.modules:
+    ...                 # Pop site out of sys.modules. This will be a
+    ...                 # close-enough approximation of site not being
+    ...                 # loaded for our tests--it lets us provoke the
+    ...                 # right errors when the fixes are absent, and
+    ...                 # works well enough when the fixes are present.
+    ...                 klass.site = sys.modules.pop('site')
+    ...             if fullname == 'ConfigParser':
+    ...                 raise ImportError(fullname)
+    ...             elif fullname == 'site':
+    ...                 # Keep the site module from being processed twice.
+    ...                 return klass
+    ...
+    ...         @classmethod
+    ...         def load_module(klass, fullname):
+    ...             if fullname == 'site':
+    ...                 return klass.site
+    ...             raise ImportError(fullname)
+    ...
+    ...     sys.meta_path.append(ImportHook)
+    ... ''' % (py_path,))
+    >>> sitecustomize_file.close()
+    >>> print call_py(
+    ...     _safe_arg(py_path),
+    ...     "import ConfigParser")
+    <BLANKLINE>
+    >>> print 'X'; print call_py(
+    ...     _safe_arg(py_path),
+    ...     "import ConfigParser",
+    ...     '-S') # doctest: +ELLIPSIS
+    X...Traceback (most recent call last):
+      ...
+    ImportError: No module named ConfigParser
+    <BLANKLINE>
+    >>> from zc.buildout.easy_install import _has_broken_dash_S
+    >>> _has_broken_dash_S(py_path)
+    True
+
+Well, that was ugly, but it seems to have done the trick.  The
+executable represented by py_path has the same problematic
+characteristic as the virtualenv one: -S results in a Python that does
+not allow the import of some packages from the standard library.  We'll
+test with this.
+
+First, let's try running bootstrap.
+
+    >>> from os.path import dirname, join
+    >>> import zc.buildout
+    >>> bootstrap_py = join(
+    ...    dirname(
+    ...     dirname(
+    ...      dirname(
+    ...       dirname(zc.buildout.__file__)
+    ...        )
+    ...      )
+    ...    ),
+    ...   'bootstrap', 'bootstrap.py')
+    >>> broken_S_buildout = tmpdir('broken_S')
+    >>> os.chdir(broken_S_buildout)
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts =
+    ... ''')
+    >>> write('bootstrap.py', open(bootstrap_py).read())
+    >>> print 'X'; print system(
+    ...     _safe_arg(py_path)+' '+
+    ...     'bootstrap.py'); print 'X' # doctest: +ELLIPSIS
+    X...
+    Generated script '/broken_S/bin/buildout'.
+    ...
+
+If bootstrap didn't look out for a broken -S, that would have failed.  Moreover,
+take a look at bin/buildout:
+
+    >>> cat('bin', 'buildout') # doctest: +NORMALIZE_WHITESPACE
+    #!/executable_buildout/bin/py
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/broken_S/eggs/setuptools-0.0-pyN.N.egg',
+      '/broken_S/eggs/zc.buildout-0.0-pyN.N.egg',
+      ]
+    <BLANKLINE>
+    import zc.buildout.buildout
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.buildout.buildout.main()
+
+That's the old-style buildout script: no changes for users with this issue.
+
+Of course, they don't get the new features either, presumably because
+they don't need or want them.  This means that if they use a recipe that
+tries to use a new feature, the behavior needs to degrade gracefully.
+
+Here's an example.  We'll switch to another buildout in which it is easier to
+use local dev versions of zc.buildout and z3c.recipe.scripts.
+
+    >>> os.chdir(dirname(dirname(buildout)))
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = eggs
+    ... find-links = %(link_server)s
+    ... include-site-packages = false
+    ...
+    ... [primed_python]
+    ... executable = %(py_path)s
+    ...
+    ... [eggs]
+    ... recipe = z3c.recipe.scripts
+    ... python = primed_python
+    ... interpreter = py
+    ... eggs = demo
+    ... ''' % globals())
+
+    >>> print system(buildout), # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Installing eggs.
+    Getting distribution for 'demo'.
+    Got demo 0.4c1.
+    Getting distribution for 'demoneeded'.
+    Got demoneeded 1.2c1.
+    Generated script '/sample-buildout/bin/demo'.
+    Generated interpreter '/sample-buildout/bin/py'.
+    ...UserWarning: Buildout has been asked to exclude or limit site-packages
+       so that builds can be repeatable when using a system Python.  However,
+       the chosen Python executable has a broken implementation of -S (see
+       https://bugs.launchpad.net/virtualenv/+bug/572545 for an example
+       problem) and this breaks buildout's ability to isolate site-packages.
+       If the executable already has a clean site-packages (e.g., using
+       virtualenv's ``--no-site-packages`` option) you may be getting
+       equivalent repeatability.  To silence this warning, use the -s argument
+       to the buildout script.  Alternatively, use a Python executable with a
+       working -S (such as a standard Python binary).
+      warnings.warn(BROKEN_DASH_S_WARNING)
+
+So, it did what we asked as best it could, but gave a big warning.  If
+you don't want those warnings for those particular recipes that use the
+new features, you can use the "-s" option to squelch the warnings.
+
+    >>> print system(buildout + ' -s'),
+    Updating eggs.
+
+A lower verbosity (one or more -q options) also quiets the warning.
+
+    >>> print system(buildout + ' -q'),
+
+Notice that, as we saw before with bin/buildout, the generated scripts
+are old-style, because the new-style feature gracefully degrades to the
+previous implementation when it encounters an executable with a broken
+dash-S.
+
+    >>> print 'X'; cat('bin', 'py') # doctest: +ELLIPSIS
+    X...
+    <BLANKLINE>
+    import sys
+    <BLANKLINE>
+    sys.path[0:0] = [
+        '/sample-buildout/eggs/demo-0.4c1-pyN.N.egg',
+        '/sample-buildout/eggs/demoneeded-1.2c1-pyN.N.egg',
+        ]
+    ...
+