#6693: New functions in site.py to get user/global site packages paths.

This commit is contained in:
Tarek Ziadé 2009-08-20 21:23:13 +00:00
parent 4e63d54b36
commit 764fc235a6
4 changed files with 160 additions and 42 deletions

View File

@ -131,6 +131,32 @@ empty, and the path manipulations are skipped; however the import of
Adds a directory to sys.path and processes its pth files. Adds a directory to sys.path and processes its pth files.
.. function:: getsitepackages()
Returns a list containing all global site-packages directories
(and possibly site-python).
.. versionadded:: 2.7
.. function:: 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.
.. versionadded:: 2.7
.. function:: 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.
.. versionadded:: 2.7
XXX Update documentation XXX Update documentation
XXX document python -m site --user-base --user-site XXX document python -m site --user-base --user-site

View File

@ -67,7 +67,10 @@ PREFIXES = [sys.prefix, sys.exec_prefix]
# Enable per user site-packages directory # Enable per user site-packages directory
# set it to False to disable the feature or True to force the feature # set it to False to disable the feature or True to force the feature
ENABLE_USER_SITE = None ENABLE_USER_SITE = None
# for distutils.commands.install # 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_SITE = None
USER_BASE = None USER_BASE = None
@ -212,49 +215,75 @@ def check_enableusersite():
return True 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
env_base = os.environ.get("PYTHONUSERBASE", None)
def joinuser(*args):
return os.path.expanduser(os.path.join(*args))
# what about 'os2emx', 'riscos' ?
if os.name == "nt":
base = os.environ.get("APPDATA") or "~"
USER_BASE = env_base if env_base else joinuser(base, "Python")
else:
USER_BASE = env_base if env_base else joinuser("~", ".local")
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
if os.name == "nt":
USER_SITE = os.path.join(user_base, "Python" + sys.version[0] +
sys.version[2], "site-packages")
else:
USER_SITE = os.path.join(user_base, "lib", "python" + sys.version[:3],
"site-packages")
return USER_SITE
def addusersitepackages(known_paths): def addusersitepackages(known_paths):
"""Add a per user site-package to sys.path """Add a per user site-package to sys.path
Each user has its own python directory with site-packages in the Each user has its own python directory with site-packages in the
home directory. home directory.
USER_BASE is the root directory for all Python versions
USER_SITE is the user specific site-packages directory
USER_SITE/.. can be used for data.
""" """
global USER_BASE, USER_SITE, ENABLE_USER_SITE # get the per user site-package path
env_base = os.environ.get("PYTHONUSERBASE", None) # this call will also make sure USER_BASE and USER_SITE are set
user_site = getusersitepackages()
def joinuser(*args): if ENABLE_USER_SITE and os.path.isdir(user_site):
return os.path.expanduser(os.path.join(*args)) addsitedir(user_site, known_paths)
#if sys.platform in ('os2emx', 'riscos'):
# # Don't know what to put here
# USER_BASE = ''
# USER_SITE = ''
if os.name == "nt":
base = os.environ.get("APPDATA") or "~"
USER_BASE = env_base if env_base else joinuser(base, "Python")
USER_SITE = os.path.join(USER_BASE,
"Python" + sys.version[0] + sys.version[2],
"site-packages")
else:
USER_BASE = env_base if env_base else joinuser("~", ".local")
USER_SITE = os.path.join(USER_BASE, "lib",
"python" + sys.version[:3],
"site-packages")
if ENABLE_USER_SITE and os.path.isdir(USER_SITE):
addsitedir(USER_SITE, known_paths)
return known_paths return known_paths
def getsitepackages():
"""Returns a list containing all global site-packages directories
(and possibly site-python).
def addsitepackages(known_paths): For each directory present in the global ``PREFIXES``, this function
"""Add site-packages (and possibly site-python) to sys.path""" will find its `site-packages` subdirectory depending on the system
sitedirs = [] environment, and will return a list of full paths.
"""
sitepackages = []
seen = [] seen = []
for prefix in PREFIXES: for prefix in PREFIXES:
@ -263,35 +292,36 @@ def addsitepackages(known_paths):
seen.append(prefix) seen.append(prefix)
if sys.platform in ('os2emx', 'riscos'): if sys.platform in ('os2emx', 'riscos'):
sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
elif os.sep == '/': elif os.sep == '/':
sitedirs.append(os.path.join(prefix, "lib", sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3], "python" + sys.version[:3],
"site-packages")) "site-packages"))
sitedirs.append(os.path.join(prefix, "lib", "site-python")) sitepackages.append(os.path.join(prefix, "lib", "site-python"))
else: else:
sitedirs.append(prefix) sitepackages.append(prefix)
sitedirs.append(os.path.join(prefix, "lib", "site-packages")) sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
if sys.platform == "darwin": if sys.platform == "darwin":
# for framework builds *only* we add the standard Apple # for framework builds *only* we add the standard Apple
# locations. # locations.
if 'Python.framework' in prefix: if 'Python.framework' in prefix:
sitedirs.append( sitepackages.append(
os.path.expanduser( os.path.expanduser(
os.path.join("~", "Library", "Python", os.path.join("~", "Library", "Python",
sys.version[:3], "site-packages"))) sys.version[:3], "site-packages")))
sitedirs.append( sitepackages.append(
os.path.join("/Library", "Python", os.path.join("/Library", "Python",
sys.version[:3], "site-packages")) sys.version[:3], "site-packages"))
return sitepackages
for sitedir in sitedirs: def addsitepackages(known_paths):
"""Add site-packages (and possibly site-python) to sys.path"""
for sitedir in getsitepackages():
if os.path.isdir(sitedir): if os.path.isdir(sitedir):
addsitedir(sitedir, known_paths) addsitedir(sitedir, known_paths)
return known_paths return known_paths
def setBEGINLIBPATH(): def setBEGINLIBPATH():
"""The OS/2 EMX port has optional extension modules that do double duty """The OS/2 EMX port has optional extension modules that do double duty
as DLLs (and must use the .DLL file extension) for other extensions. as DLLs (and must use the .DLL file extension) for other extensions.

View File

@ -35,10 +35,16 @@ class HelperFunctionsTests(unittest.TestCase):
def setUp(self): def setUp(self):
"""Save a copy of sys.path""" """Save a copy of sys.path"""
self.sys_path = sys.path[:] self.sys_path = sys.path[:]
self.old_base = site.USER_BASE
self.old_site = site.USER_SITE
self.old_prefixes = site.PREFIXES
def tearDown(self): def tearDown(self):
"""Restore sys.path""" """Restore sys.path"""
sys.path = self.sys_path sys.path = self.sys_path
site.USER_BASE = self.old_base
site.USER_SITE = self.old_site
site.PREFIXES = self.old_prefixes
def test_makepath(self): def test_makepath(self):
# Test makepath() have an absolute path for its first return value # Test makepath() have an absolute path for its first return value
@ -123,6 +129,60 @@ class HelperFunctionsTests(unittest.TestCase):
env=env) env=env)
self.assertEqual(rc, 1) self.assertEqual(rc, 1)
def test_getuserbase(self):
site.USER_BASE = None
user_base = site.getuserbase()
# the call sets site.USER_BASE
self.assertEquals(site.USER_BASE, user_base)
# let's set PYTHONUSERBASE and see if it uses it
site.USER_BASE = None
with EnvironmentVarGuard() as environ:
environ['PYTHONUSERBASE'] = 'xoxo'
self.assertTrue(site.getuserbase().startswith('xoxo'))
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.assertEquals(site.USER_SITE, user_site)
self.assertTrue(user_site.startswith(site.USER_BASE))
def test_getsitepackages(self):
site.PREFIXES = ['xoxo']
dirs = site.getsitepackages()
if sys.platform in ('os2emx', 'riscos'):
self.assertTrue(len(dirs), 1)
wanted = os.path.join('xoxo', 'Lib', 'site-packages')
self.assertEquals(dirs[0], wanted)
elif os.sep == '/':
self.assertTrue(len(dirs), 2)
wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3],
'site-packages')
self.assertEquals(dirs[0], wanted)
wanted = os.path.join('xoxo', 'lib', 'site-python')
self.assertEquals(dirs[1], wanted)
else:
self.assertTrue(len(dirs), 2)
self.assertEquals(dirs[0], 'xoxo')
wanted = os.path.join('xoxo', 'Lib', 'site-packages')
self.assertEquals(dirs[1], wanted)
# let's try the specific Apple location
if sys.platform == "darwin":
site.PREFIXES = ['Python.framework']
dirs = site.getsitepackages()
self.assertTrue(len(dirs), 4)
wanted = os.path.join('~', 'Library', 'Python',
sys.version[:3], 'site-packages')
self.assertEquals(dirs[2], os.path.expanduser(wanted))
wanted = os.path.join('/Library', 'Python', sys.version[:3],
'site-packages')
self.assertEquals(dirs[3], wanted)
class PthFile(object): class PthFile(object):
"""Helper class for handling testing of .pth files""" """Helper class for handling testing of .pth files"""

View File

@ -359,6 +359,8 @@ Core and Builtins
Library Library
------- -------
- Issue #6693: New functions in site.py to get user/global site packages paths.
- The thread.lock type now supports weak references. - The thread.lock type now supports weak references.
- Issue #1356969: Add missing info methods in Tix.HList. - Issue #1356969: Add missing info methods in Tix.HList.