#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.
.. 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 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
# 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
@ -212,49 +215,75 @@ def check_enableusersite():
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):
"""Add a per user site-package to sys.path
Each user has its own python directory with site-packages in the
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
env_base = os.environ.get("PYTHONUSERBASE", None)
# get the per user site-package path
# this call will also make sure USER_BASE and USER_SITE are set
user_site = getusersitepackages()
def joinuser(*args):
return os.path.expanduser(os.path.join(*args))
#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)
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).
def addsitepackages(known_paths):
"""Add site-packages (and possibly site-python) to sys.path"""
sitedirs = []
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 = []
for prefix in PREFIXES:
@ -263,35 +292,36 @@ def addsitepackages(known_paths):
seen.append(prefix)
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 == '/':
sitedirs.append(os.path.join(prefix, "lib",
sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3],
"site-packages"))
sitedirs.append(os.path.join(prefix, "lib", "site-python"))
sitepackages.append(os.path.join(prefix, "lib", "site-python"))
else:
sitedirs.append(prefix)
sitedirs.append(os.path.join(prefix, "lib", "site-packages"))
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.
if 'Python.framework' in prefix:
sitedirs.append(
sitepackages.append(
os.path.expanduser(
os.path.join("~", "Library", "Python",
sys.version[:3], "site-packages")))
sitedirs.append(
sitepackages.append(
os.path.join("/Library", "Python",
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):
addsitedir(sitedir, known_paths)
return known_paths
def setBEGINLIBPATH():
"""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.

View File

@ -35,10 +35,16 @@ class HelperFunctionsTests(unittest.TestCase):
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
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
def test_makepath(self):
# Test makepath() have an absolute path for its first return value
@ -123,6 +129,60 @@ class HelperFunctionsTests(unittest.TestCase):
env=env)
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):
"""Helper class for handling testing of .pth files"""

View File

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