[Jython-checkins] jython: New site.py.
frank.wierzbicki
jython-checkins at python.org
Thu Mar 22 04:25:03 CET 2012
http://hg.python.org/jython/rev/ea1ffd84a6df
changeset: 6468:ea1ffd84a6df
user: Frank Wierzbicki <fwierzbicki at gmail.com>
date: Wed Mar 21 20:24:55 2012 -0700
summary:
New site.py.
files:
Lib/site.py | 337 ++++++++++++++++++++-----
Lib/test/test_site.py | 397 ++++++++++++++++++++++++++++++
2 files changed, 663 insertions(+), 71 deletions(-)
diff --git a/Lib/site.py b/Lib/site.py
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -61,28 +61,51 @@
import sys
import os
import __builtin__
-ModuleType = type(os)
+import traceback
+
+import platform as _platform
+
+_is_jython = _platform.python_implementation == "Jython"
+if _is_jython:
+ _ModuleType = type(os)
+
+# Prefixes for site-packages; add additional prefixes like /usr/local here
+PREFIXES = [sys.prefix, sys.exec_prefix]
+# Enable per user site-packages directory
+# set it to False to disable the feature or True to force the feature
+ENABLE_USER_SITE = None
+
+# for distutils.commands.install
+# These values are initialized by the getuserbase() and getusersitepackages()
+# functions, through the main() function when Python starts.
+USER_SITE = None
+USER_BASE = None
def makepath(*paths):
dir = os.path.join(*paths)
- if dir == '__classpath__' or dir.startswith('__pyclasspath__'):
- return dir, dir
- dir = os.path.abspath(dir)
+ if _is_jython and (dir == '__classpath__' or
+ dir.startswith('__pyclasspath__')):
+ return dir, dir
+ try:
+ dir = os.path.abspath(dir)
+ except OSError:
+ pass
return dir, os.path.normcase(dir)
+
def abs__file__():
"""Set all module' __file__ attribute to an absolute path"""
for m in sys.modules.values():
- if not isinstance(m, ModuleType) or hasattr(m, '__loader__'):
- # only modules need the abspath in Jython. and don't mess
- # with a PEP 302-supplied __file__
- continue
+ if hasattr(m, '__loader__') or (
+ _is_jython and not isinstance(m, _ModuleType)):
+ continue # don't mess with a PEP 302-supplied __file__
f = getattr(m, '__file__', None)
if f is None:
continue
m.__file__ = os.path.abspath(f)
+
def removeduppaths():
""" Remove duplicate entries from sys.path along with making them
absolute"""
@@ -106,11 +129,14 @@
def addbuilddir():
"""Append ./build/lib.<platform> in case we're running in the build dir
(especially for Guido :-)"""
- from distutils.util import get_platform
+ from sysconfig import get_platform
s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
- s = os.path.join(os.path.dirname(sys.path[-1]), s)
+ if hasattr(sys, 'gettotalrefcount'):
+ s += '-pydebug'
+ s = os.path.join(os.path.dirname(sys.path.pop()), s)
sys.path.append(s)
+
def _init_pathinfo():
"""Return a set containing all existing directory entries from sys.path"""
d = set()
@@ -123,9 +149,12 @@
continue
return d
+
def addpackage(sitedir, name, known_paths):
- """Add a new path to known_paths by combining sitedir and 'name' or execute
- sitedir if it starts with 'import'"""
+ """Process a .pth file within the site-packages directory:
+ For each line in the file, either combine it with sitedir to a path
+ and add that to known_paths, or execute it if it starts with 'import '.
+ """
if known_paths is None:
_init_pathinfo()
reset = 1
@@ -136,24 +165,32 @@
f = open(fullname, "rU")
except IOError:
return
- try:
- for line in f:
+ with f:
+ for n, line in enumerate(f):
if line.startswith("#"):
continue
- if line.startswith("import"):
- exec line
- continue
- line = line.rstrip()
- dir, dircase = makepath(sitedir, line)
- if not dircase in known_paths and os.path.exists(dir):
- sys.path.append(dir)
- known_paths.add(dircase)
- finally:
- f.close()
+ try:
+ if line.startswith(("import ", "import\t")):
+ exec line
+ continue
+ line = line.rstrip()
+ dir, dircase = makepath(sitedir, line)
+ if not dircase in known_paths and os.path.exists(dir):
+ sys.path.append(dir)
+ known_paths.add(dircase)
+ except Exception as err:
+ print >>sys.stderr, "Error processing line {:d} of {}:\n".format(
+ n+1, fullname)
+ for record in traceback.format_exception(*sys.exc_info()):
+ for line in record.splitlines():
+ print >>sys.stderr, ' '+line
+ print >>sys.stderr, "\nRemainder of file ignored"
+ break
if reset:
known_paths = None
return known_paths
+
def addsitedir(sitedir, known_paths=None):
"""Add 'sitedir' argument to sys.path if missing and handle .pth files in
'sitedir'"""
@@ -169,49 +206,135 @@
names = os.listdir(sitedir)
except os.error:
return
- names.sort()
- for name in names:
- if name.endswith(os.extsep + "pth"):
- addpackage(sitedir, name, known_paths)
+ dotpth = os.extsep + "pth"
+ names = [name for name in names if name.endswith(dotpth)]
+ for name in sorted(names):
+ addpackage(sitedir, name, known_paths)
if reset:
known_paths = None
return known_paths
+
+def check_enableusersite():
+ """Check if user site directory is safe for inclusion
+
+ The function tests for the command line flag (including environment var),
+ process uid/gid equal to effective uid/gid.
+
+ None: Disabled for security reasons
+ False: Disabled by user (command line option)
+ True: Safe and enabled
+ """
+ if sys.flags.no_user_site:
+ return False
+
+ if hasattr(os, "getuid") and hasattr(os, "geteuid"):
+ # check process uid == effective uid
+ if os.geteuid() != os.getuid():
+ return None
+ if hasattr(os, "getgid") and hasattr(os, "getegid"):
+ # check process gid == effective gid
+ if os.getegid() != os.getgid():
+ return None
+
+ return True
+
+def getuserbase():
+ """Returns the `user base` directory path.
+
+ The `user base` directory can be used to store data. If the global
+ variable ``USER_BASE`` is not initialized yet, this function will also set
+ it.
+ """
+ global USER_BASE
+ if USER_BASE is not None:
+ return USER_BASE
+ from sysconfig import get_config_var
+ USER_BASE = get_config_var('userbase')
+ return USER_BASE
+
+def getusersitepackages():
+ """Returns the user-specific site-packages directory path.
+
+ If the global variable ``USER_SITE`` is not initialized yet, this
+ function will also set it.
+ """
+ global USER_SITE
+ user_base = getuserbase() # this will also set USER_BASE
+
+ if USER_SITE is not None:
+ return USER_SITE
+
+ from sysconfig import get_path
+ import os
+
+ if sys.platform == 'darwin':
+ from sysconfig import get_config_var
+ if get_config_var('PYTHONFRAMEWORK'):
+ USER_SITE = get_path('purelib', 'osx_framework_user')
+ return USER_SITE
+
+ USER_SITE = get_path('purelib', '%s_user' % os.name)
+ return USER_SITE
+
+def addusersitepackages(known_paths):
+ """Add a per user site-package to sys.path
+
+ Each user has its own python directory with site-packages in the
+ home directory.
+ """
+ # get the per user site-package path
+ # this call will also make sure USER_BASE and USER_SITE are set
+ user_site = getusersitepackages()
+
+ if ENABLE_USER_SITE and os.path.isdir(user_site):
+ addsitedir(user_site, known_paths)
+ return known_paths
+
+def getsitepackages():
+ """Returns a list containing all global site-packages directories
+ (and possibly site-python).
+
+ For each directory present in the global ``PREFIXES``, this function
+ will find its `site-packages` subdirectory depending on the system
+ environment, and will return a list of full paths.
+ """
+ sitepackages = []
+ seen = set()
+
+ for prefix in PREFIXES:
+ if not prefix or prefix in seen:
+ continue
+ seen.add(prefix)
+
+ if sys.platform in ('os2emx', 'riscos') or _is_jython:
+ sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
+ elif os.sep == '/':
+ sitepackages.append(os.path.join(prefix, "lib",
+ "python" + sys.version[:3],
+ "site-packages"))
+ sitepackages.append(os.path.join(prefix, "lib", "site-python"))
+ else:
+ sitepackages.append(prefix)
+ sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
+ if sys.platform == "darwin":
+ # for framework builds *only* we add the standard Apple
+ # locations.
+ from sysconfig import get_config_var
+ framework = get_config_var("PYTHONFRAMEWORK")
+ if framework:
+ sitepackages.append(
+ os.path.join("/Library", framework,
+ sys.version[:3], "site-packages"))
+ return sitepackages
+
def addsitepackages(known_paths):
"""Add site-packages (and possibly site-python) to sys.path"""
- prefixes = [sys.prefix]
- if sys.exec_prefix != sys.prefix:
- prefixes.append(sys.exec_prefix)
- for prefix in prefixes:
- if prefix:
- if sys.platform in ('os2emx', 'riscos') or sys.platform[:4] == 'java':
- sitedirs = [os.path.join(prefix, "Lib", "site-packages")]
- elif os.sep == '/':
- sitedirs = [os.path.join(prefix,
- "lib",
- "python" + sys.version[:3],
- "site-packages"),
- os.path.join(prefix, "lib", "site-python")]
- else:
- sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
- if sys.platform == 'darwin':
- # for framework builds *only* we add the standard Apple
- # locations. Currently only per-user, but /Library and
- # /Network/Library could be added too
- if 'Python.framework' in prefix:
- home = os.environ.get('HOME')
- if home:
- sitedirs.append(
- os.path.join(home,
- 'Library',
- 'Python',
- sys.version[:3],
- 'site-packages'))
- for sitedir in sitedirs:
- if os.path.isdir(sitedir):
- addsitedir(sitedir, known_paths)
- return None
+ for sitedir in getsitepackages():
+ if os.path.isdir(sitedir):
+ addsitedir(sitedir, known_paths)
+ return known_paths
def setBEGINLIBPATH():
"""The OS/2 EMX port has optional extension modules that do double duty
@@ -231,8 +354,10 @@
def setquit():
- """Define new built-ins 'quit' and 'exit'.
- These are simply strings that display a hint on how to exit.
+ """Define new builtins 'quit' and 'exit'.
+
+ These are objects which make the interpreter exit when called.
+ The repr of each object contains a hint at how it works.
"""
if os.sep == ':':
@@ -339,7 +464,7 @@
class _Helper(object):
- """Define the built-in 'help'.
+ """Define the builtin 'help'.
This is a wrapper around pydoc.help (with a twist).
"""
@@ -395,15 +520,40 @@
import sitecustomize
except ImportError:
pass
+ except Exception:
+ if sys.flags.verbose:
+ sys.excepthook(*sys.exc_info())
+ else:
+ print >>sys.stderr, \
+ "'import sitecustomize' failed; use -v for traceback"
+
+
+def execusercustomize():
+ """Run custom user specific code, if available."""
+ try:
+ import usercustomize
+ except ImportError:
+ pass
+ except Exception:
+ if sys.flags.verbose:
+ sys.excepthook(*sys.exc_info())
+ else:
+ print>>sys.stderr, \
+ "'import usercustomize' failed; use -v for traceback"
def main():
+ global ENABLE_USER_SITE
+
abs__file__()
- paths_in_sys = removeduppaths()
+ known_paths = removeduppaths()
if (os.name == "posix" and sys.path and
os.path.basename(sys.path[-1]) == "Modules"):
addbuilddir()
- paths_in_sys = addsitepackages(paths_in_sys)
+ if ENABLE_USER_SITE is None:
+ ENABLE_USER_SITE = check_enableusersite()
+ known_paths = addusersitepackages(known_paths)
+ known_paths = addsitepackages(known_paths)
if sys.platform == 'os2emx':
setBEGINLIBPATH()
setquit()
@@ -412,6 +562,8 @@
aliasmbcs()
setencoding()
execsitecustomize()
+ if ENABLE_USER_SITE:
+ execusercustomize()
# Remove sys.setdefaultencoding() so that users cannot change the
# encoding after initialization. The test for presence is needed when
# this module is run as a script, because this code is executed twice.
@@ -420,11 +572,54 @@
main()
-def _test():
- print "sys.path = ["
- for dir in sys.path:
- print " %r," % (dir,)
- print "]"
+def _script():
+ help = """\
+ %s [--user-base] [--user-site]
+
+ Without arguments print some useful information
+ With arguments print the value of USER_BASE and/or USER_SITE separated
+ by '%s'.
+
+ Exit codes with --user-base or --user-site:
+ 0 - user site directory is enabled
+ 1 - user site directory is disabled by user
+ 2 - uses site directory is disabled by super user
+ or for security reasons
+ >2 - unknown error
+ """
+ args = sys.argv[1:]
+ if not args:
+ print "sys.path = ["
+ for dir in sys.path:
+ print " %r," % (dir,)
+ print "]"
+ print "USER_BASE: %r (%s)" % (USER_BASE,
+ "exists" if os.path.isdir(USER_BASE) else "doesn't exist")
+ print "USER_SITE: %r (%s)" % (USER_SITE,
+ "exists" if os.path.isdir(USER_SITE) else "doesn't exist")
+ print "ENABLE_USER_SITE: %r" % ENABLE_USER_SITE
+ sys.exit(0)
+
+ buffer = []
+ if '--user-base' in args:
+ buffer.append(USER_BASE)
+ if '--user-site' in args:
+ buffer.append(USER_SITE)
+
+ if buffer:
+ print os.pathsep.join(buffer)
+ if ENABLE_USER_SITE:
+ sys.exit(0)
+ elif ENABLE_USER_SITE is False:
+ sys.exit(1)
+ elif ENABLE_USER_SITE is None:
+ sys.exit(2)
+ else:
+ sys.exit(3)
+ else:
+ import textwrap
+ print textwrap.dedent(help % (sys.argv[0], os.pathsep))
+ sys.exit(10)
if __name__ == '__main__':
- _test()
+ _script()
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_site.py
@@ -0,0 +1,397 @@
+"""Tests for 'site'.
+
+Tests assume the initial paths in sys.path once the interpreter has begun
+executing have not been removed.
+
+"""
+import unittest
+from test.test_support import run_unittest, TESTFN, EnvironmentVarGuard
+from test.test_support import captured_output, is_jython
+import __builtin__
+import os
+import sys
+import re
+import encodings
+import subprocess
+import sysconfig
+from copy import copy
+
+# Need to make sure to not import 'site' if someone specified ``-S`` at the
+# command-line. Detect this by just making sure 'site' has not been imported
+# already.
+if "site" in sys.modules:
+ import site
+else:
+ raise unittest.SkipTest("importation of site.py suppressed")
+
+if site.ENABLE_USER_SITE and not os.path.isdir(site.USER_SITE):
+ # need to add user site directory for tests
+ os.makedirs(site.USER_SITE)
+ site.addsitedir(site.USER_SITE)
+
+class HelperFunctionsTests(unittest.TestCase):
+ """Tests for helper functions.
+
+ The setting of the encoding (set using sys.setdefaultencoding) used by
+ the Unicode implementation is not tested.
+
+ """
+
+ def setUp(self):
+ """Save a copy of sys.path"""
+ self.sys_path = sys.path[:]
+ self.old_base = site.USER_BASE
+ self.old_site = site.USER_SITE
+ self.old_prefixes = site.PREFIXES
+ self.old_vars = copy(sysconfig._CONFIG_VARS)
+
+ def tearDown(self):
+ """Restore sys.path"""
+ sys.path[:] = self.sys_path
+ site.USER_BASE = self.old_base
+ site.USER_SITE = self.old_site
+ site.PREFIXES = self.old_prefixes
+ sysconfig._CONFIG_VARS = self.old_vars
+
+ def test_makepath(self):
+ # Test makepath() have an absolute path for its first return value
+ # and a case-normalized version of the absolute path for its
+ # second value.
+ path_parts = ("Beginning", "End")
+ original_dir = os.path.join(*path_parts)
+ abs_dir, norm_dir = site.makepath(*path_parts)
+ self.assertEqual(os.path.abspath(original_dir), abs_dir)
+ if original_dir == os.path.normcase(original_dir):
+ self.assertEqual(abs_dir, norm_dir)
+ else:
+ self.assertEqual(os.path.normcase(abs_dir), norm_dir)
+
+ def test_init_pathinfo(self):
+ dir_set = site._init_pathinfo()
+ for entry in [site.makepath(path)[1] for path in sys.path
+ if path and os.path.isdir(path)]:
+ self.assertIn(entry, dir_set,
+ "%s from sys.path not found in set returned "
+ "by _init_pathinfo(): %s" % (entry, dir_set))
+
+ def pth_file_tests(self, pth_file):
+ """Contain common code for testing results of reading a .pth file"""
+ self.assertIn(pth_file.imported, sys.modules,
+ "%s not in sys.modules" % pth_file.imported)
+ self.assertIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
+ self.assertFalse(os.path.exists(pth_file.bad_dir_path))
+
+ def test_addpackage(self):
+ # Make sure addpackage() imports if the line starts with 'import',
+ # adds directories to sys.path for any line in the file that is not a
+ # comment or import that is a valid directory name for where the .pth
+ # file resides; invalid directories are not added
+ pth_file = PthFile()
+ pth_file.cleanup(prep=True) # to make sure that nothing is
+ # pre-existing that shouldn't be
+ try:
+ pth_file.create()
+ site.addpackage(pth_file.base_dir, pth_file.filename, set())
+ self.pth_file_tests(pth_file)
+ finally:
+ pth_file.cleanup()
+
+ def make_pth(self, contents, pth_dir='.', pth_name=TESTFN):
+ # Create a .pth file and return its (abspath, basename).
+ pth_dir = os.path.abspath(pth_dir)
+ pth_basename = pth_name + '.pth'
+ pth_fn = os.path.join(pth_dir, pth_basename)
+ pth_file = open(pth_fn, 'w')
+ self.addCleanup(lambda: os.remove(pth_fn))
+ pth_file.write(contents)
+ pth_file.close()
+ return pth_dir, pth_basename
+
+ def test_addpackage_import_bad_syntax(self):
+ # Issue 10642
+ pth_dir, pth_fn = self.make_pth("import bad)syntax\n")
+ with captured_output("stderr") as err_out:
+ site.addpackage(pth_dir, pth_fn, set())
+ self.assertRegexpMatches(err_out.getvalue(), "line 1")
+ self.assertRegexpMatches(err_out.getvalue(),
+ re.escape(os.path.join(pth_dir, pth_fn)))
+ # XXX: the previous two should be independent checks so that the
+ # order doesn't matter. The next three could be a single check
+ # but my regex foo isn't good enough to write it.
+ self.assertRegexpMatches(err_out.getvalue(), 'Traceback')
+ self.assertRegexpMatches(err_out.getvalue(), r'import bad\)syntax')
+ self.assertRegexpMatches(err_out.getvalue(), 'SyntaxError')
+
+ def test_addpackage_import_bad_exec(self):
+ # Issue 10642
+ pth_dir, pth_fn = self.make_pth("randompath\nimport nosuchmodule\n")
+ with captured_output("stderr") as err_out:
+ site.addpackage(pth_dir, pth_fn, set())
+ self.assertRegexpMatches(err_out.getvalue(), "line 2")
+ self.assertRegexpMatches(err_out.getvalue(),
+ re.escape(os.path.join(pth_dir, pth_fn)))
+ # XXX: ditto previous XXX comment.
+ self.assertRegexpMatches(err_out.getvalue(), 'Traceback')
+ self.assertRegexpMatches(err_out.getvalue(), 'ImportError')
+
+ @unittest.skipIf(is_jython, "FIXME: not on Jython yet.")
+ @unittest.skipIf(sys.platform == "win32", "Windows does not raise an "
+ "error for file paths containing null characters")
+ def test_addpackage_import_bad_pth_file(self):
+ # Issue 5258
+ pth_dir, pth_fn = self.make_pth("abc\x00def\n")
+ with captured_output("stderr") as err_out:
+ site.addpackage(pth_dir, pth_fn, set())
+ self.assertRegexpMatches(err_out.getvalue(), "line 1")
+ self.assertRegexpMatches(err_out.getvalue(),
+ re.escape(os.path.join(pth_dir, pth_fn)))
+ # XXX: ditto previous XXX comment.
+ self.assertRegexpMatches(err_out.getvalue(), 'Traceback')
+ self.assertRegexpMatches(err_out.getvalue(), 'TypeError')
+
+ def test_addsitedir(self):
+ # Same tests for test_addpackage since addsitedir() essentially just
+ # calls addpackage() for every .pth file in the directory
+ pth_file = PthFile()
+ pth_file.cleanup(prep=True) # Make sure that nothing is pre-existing
+ # that is tested for
+ try:
+ pth_file.create()
+ site.addsitedir(pth_file.base_dir, set())
+ self.pth_file_tests(pth_file)
+ finally:
+ pth_file.cleanup()
+
+ @unittest.skipIf(is_jython, "FIXME: not on Jython yet.")
+ @unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 "
+ "user-site (site.ENABLE_USER_SITE)")
+ def test_s_option(self):
+ usersite = site.USER_SITE
+ self.assertIn(usersite, sys.path)
+
+ env = os.environ.copy()
+ rc = subprocess.call([sys.executable, '-c',
+ 'import sys; sys.exit(%r in sys.path)' % usersite],
+ env=env)
+ self.assertEqual(rc, 1, "%r is not in sys.path (sys.exit returned %r)"
+ % (usersite, rc))
+
+ env = os.environ.copy()
+ rc = subprocess.call([sys.executable, '-s', '-c',
+ 'import sys; sys.exit(%r in sys.path)' % usersite],
+ env=env)
+ self.assertEqual(rc, 0)
+
+ env = os.environ.copy()
+ env["PYTHONNOUSERSITE"] = "1"
+ rc = subprocess.call([sys.executable, '-c',
+ 'import sys; sys.exit(%r in sys.path)' % usersite],
+ env=env)
+ self.assertEqual(rc, 0)
+
+ env = os.environ.copy()
+ env["PYTHONUSERBASE"] = "/tmp"
+ rc = subprocess.call([sys.executable, '-c',
+ 'import sys, site; sys.exit(site.USER_BASE.startswith("/tmp"))'],
+ env=env)
+ self.assertEqual(rc, 1)
+
+ @unittest.skipIf(is_jython, "FIXME: not on Jython yet.")
+ def test_getuserbase(self):
+ site.USER_BASE = None
+ user_base = site.getuserbase()
+
+ # the call sets site.USER_BASE
+ self.assertEqual(site.USER_BASE, user_base)
+
+ # let's set PYTHONUSERBASE and see if it uses it
+ site.USER_BASE = None
+ import sysconfig
+ sysconfig._CONFIG_VARS = None
+
+ with EnvironmentVarGuard() as environ:
+ environ['PYTHONUSERBASE'] = 'xoxo'
+ self.assertTrue(site.getuserbase().startswith('xoxo'),
+ site.getuserbase())
+
+ def test_getusersitepackages(self):
+ site.USER_SITE = None
+ site.USER_BASE = None
+ user_site = site.getusersitepackages()
+
+ # the call sets USER_BASE *and* USER_SITE
+ self.assertEqual(site.USER_SITE, user_site)
+ self.assertTrue(user_site.startswith(site.USER_BASE), user_site)
+
+ def test_getsitepackages(self):
+ site.PREFIXES = ['xoxo']
+ dirs = site.getsitepackages()
+
+ if sys.platform in ('os2emx', 'riscos'):
+ self.assertEqual(len(dirs), 1)
+ wanted = os.path.join('xoxo', 'Lib', 'site-packages')
+ self.assertEqual(dirs[0], wanted)
+ elif (sys.platform == "darwin" and
+ sysconfig.get_config_var("PYTHONFRAMEWORK")):
+ # OS X framework builds
+ site.PREFIXES = ['Python.framework']
+ dirs = site.getsitepackages()
+ self.assertEqual(len(dirs), 3)
+ wanted = os.path.join('/Library',
+ sysconfig.get_config_var("PYTHONFRAMEWORK"),
+ sys.version[:3],
+ 'site-packages')
+ self.assertEqual(dirs[2], wanted)
+ elif os.sep == '/':
+ # OS X non-framwework builds, Linux, FreeBSD, etc
+ self.assertEqual(len(dirs), 2)
+ wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3],
+ 'site-packages')
+ self.assertEqual(dirs[0], wanted)
+ wanted = os.path.join('xoxo', 'lib', 'site-python')
+ self.assertEqual(dirs[1], wanted)
+ else:
+ # other platforms
+ self.assertEqual(len(dirs), 2)
+ self.assertEqual(dirs[0], 'xoxo')
+ wanted = os.path.join('xoxo', 'lib', 'site-packages')
+ self.assertEqual(dirs[1], wanted)
+
+class PthFile(object):
+ """Helper class for handling testing of .pth files"""
+
+ def __init__(self, filename_base=TESTFN, imported="time",
+ good_dirname="__testdir__", bad_dirname="__bad"):
+ """Initialize instance variables"""
+ self.filename = filename_base + ".pth"
+ self.base_dir = os.path.abspath('')
+ self.file_path = os.path.join(self.base_dir, self.filename)
+ self.imported = imported
+ self.good_dirname = good_dirname
+ self.bad_dirname = bad_dirname
+ self.good_dir_path = os.path.join(self.base_dir, self.good_dirname)
+ self.bad_dir_path = os.path.join(self.base_dir, self.bad_dirname)
+
+ def create(self):
+ """Create a .pth file with a comment, blank lines, an ``import
+ <self.imported>``, a line with self.good_dirname, and a line with
+ self.bad_dirname.
+
+ Creation of the directory for self.good_dir_path (based off of
+ self.good_dirname) is also performed.
+
+ Make sure to call self.cleanup() to undo anything done by this method.
+
+ """
+ FILE = open(self.file_path, 'w')
+ try:
+ print>>FILE, "#import @bad module name"
+ print>>FILE, "\n"
+ print>>FILE, "import %s" % self.imported
+ print>>FILE, self.good_dirname
+ print>>FILE, self.bad_dirname
+ finally:
+ FILE.close()
+ os.mkdir(self.good_dir_path)
+
+ def cleanup(self, prep=False):
+ """Make sure that the .pth file is deleted, self.imported is not in
+ sys.modules, and that both self.good_dirname and self.bad_dirname are
+ not existing directories."""
+ if os.path.exists(self.file_path):
+ os.remove(self.file_path)
+ if prep:
+ self.imported_module = sys.modules.get(self.imported)
+ if self.imported_module:
+ del sys.modules[self.imported]
+ else:
+ if self.imported_module:
+ sys.modules[self.imported] = self.imported_module
+ if os.path.exists(self.good_dir_path):
+ os.rmdir(self.good_dir_path)
+ if os.path.exists(self.bad_dir_path):
+ os.rmdir(self.bad_dir_path)
+
+class ImportSideEffectTests(unittest.TestCase):
+ """Test side-effects from importing 'site'."""
+
+ def setUp(self):
+ """Make a copy of sys.path"""
+ self.sys_path = sys.path[:]
+
+ def tearDown(self):
+ """Restore sys.path"""
+ sys.path[:] = self.sys_path
+
+ def test_abs__file__(self):
+ # Make sure all imported modules have their __file__ attribute
+ # as an absolute path.
+ # Handled by abs__file__()
+ site.abs__file__()
+ for module in (sys, os, __builtin__):
+ try:
+ self.assertTrue(os.path.isabs(module.__file__), repr(module))
+ except AttributeError:
+ continue
+ # We could try everything in sys.modules; however, when regrtest.py
+ # runs something like test_frozen before test_site, then we will
+ # be testing things loaded *after* test_site did path normalization
+
+ def test_no_duplicate_paths(self):
+ # No duplicate paths should exist in sys.path
+ # Handled by removeduppaths()
+ site.removeduppaths()
+ seen_paths = set()
+ for path in sys.path:
+ self.assertNotIn(path, seen_paths)
+ seen_paths.add(path)
+
+ def test_add_build_dir(self):
+ # Test that the build directory's Modules directory is used when it
+ # should be.
+ # XXX: implement
+ pass
+
+ def test_setting_quit(self):
+ # 'quit' and 'exit' should be injected into __builtin__
+ self.assertTrue(hasattr(__builtin__, "quit"))
+ self.assertTrue(hasattr(__builtin__, "exit"))
+
+ def test_setting_copyright(self):
+ # 'copyright' and 'credits' should be in __builtin__
+ self.assertTrue(hasattr(__builtin__, "copyright"))
+ self.assertTrue(hasattr(__builtin__, "credits"))
+
+ def test_setting_help(self):
+ # 'help' should be set in __builtin__
+ self.assertTrue(hasattr(__builtin__, "help"))
+
+ def test_aliasing_mbcs(self):
+ if sys.platform == "win32":
+ import locale
+ if locale.getdefaultlocale()[1].startswith('cp'):
+ for value in encodings.aliases.aliases.itervalues():
+ if value == "mbcs":
+ break
+ else:
+ self.fail("did not alias mbcs")
+
+ def test_setdefaultencoding_removed(self):
+ # Make sure sys.setdefaultencoding is gone
+ self.assertTrue(not hasattr(sys, "setdefaultencoding"))
+
+ def test_sitecustomize_executed(self):
+ # If sitecustomize is available, it should have been imported.
+ if "sitecustomize" not in sys.modules:
+ try:
+ import sitecustomize
+ except ImportError:
+ pass
+ else:
+ self.fail("sitecustomize not imported automatically")
+
+def test_main():
+ run_unittest(HelperFunctionsTests, ImportSideEffectTests)
+
+if __name__ == "__main__":
+ test_main()
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list