From ab74c014ae514fde7487542ec96ef45235aa86b0 Mon Sep 17 00:00:00 2001 From: pxinwr Date: Mon, 21 Dec 2020 06:27:42 +0800 Subject: bpo-31904: Fix site and sysconfig modules for VxWorks RTOS (GH-21821) --- Lib/distutils/command/install.py | 13 ++- Lib/distutils/tests/test_install.py | 8 +- Lib/site.py | 24 +++-- Lib/sysconfig.py | 115 ++++++++++++--------- Lib/test/test_site.py | 5 + Lib/test/test_sysconfig.py | 19 ++-- .../2020-08-11-17-44-07.bpo-31904.cb13ea.rst | 1 + 7 files changed, 113 insertions(+), 72 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-11-17-44-07.bpo-31904.cb13ea.rst diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py index aaa300e..bdead13 100644 --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -17,7 +17,8 @@ from distutils.errors import DistutilsOptionError from site import USER_BASE from site import USER_SITE -HAS_USER_SITE = True + +HAS_USER_SITE = (USER_SITE is not None) WINDOWS_SCHEME = { 'purelib': '$base/Lib/site-packages', @@ -169,8 +170,9 @@ class install(Command): self.install_lib = None # set to either purelib or platlib self.install_scripts = None self.install_data = None - self.install_userbase = USER_BASE - self.install_usersite = USER_SITE + if HAS_USER_SITE: + self.install_userbase = USER_BASE + self.install_usersite = USER_SITE self.compile = None self.optimize = None @@ -343,8 +345,9 @@ class install(Command): # Convert directories from Unix /-separated syntax to the local # convention. self.convert_paths('lib', 'purelib', 'platlib', - 'scripts', 'data', 'headers', - 'userbase', 'usersite') + 'scripts', 'data', 'headers') + if HAS_USER_SITE: + self.convert_paths('userbase', 'usersite') # Deprecated # Well, we're not actually fully completely finalized yet: we still diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py index 51c80e0..21a7b7c 100644 --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -8,7 +8,7 @@ import site from test.support import captured_stdout, run_unittest from distutils import sysconfig -from distutils.command.install import install +from distutils.command.install import install, HAS_USER_SITE from distutils.command import install as install_module from distutils.command.build_ext import build_ext from distutils.command.install import INSTALL_SCHEMES @@ -66,6 +66,7 @@ class InstallTestCase(support.TempdirManager, check_path(cmd.install_scripts, os.path.join(destination, "bin")) check_path(cmd.install_data, destination) + @unittest.skipUnless(HAS_USER_SITE, 'need user site') def test_user_site(self): # test install with --user # preparing the environment for the test @@ -93,8 +94,9 @@ class InstallTestCase(support.TempdirManager, self.addCleanup(cleanup) - for key in ('nt_user', 'unix_user'): - self.assertIn(key, INSTALL_SCHEMES) + if HAS_USER_SITE: + for key in ('nt_user', 'unix_user'): + self.assertIn(key, INSTALL_SCHEMES) dist = Distribution({'name': 'xx'}) cmd = install(dist) diff --git a/Lib/site.py b/Lib/site.py index 3a0f619..5f1b31e 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -264,6 +264,10 @@ def _getuserbase(): if env_base: return env_base + # VxWorks has no home directories + if sys.platform == "vxworks": + return None + def joinuser(*args): return os.path.expanduser(os.path.join(*args)) @@ -311,11 +315,14 @@ def getusersitepackages(): If the global variable ``USER_SITE`` is not initialized yet, this function will also set it. """ - global USER_SITE + global USER_SITE, ENABLE_USER_SITE userbase = getuserbase() # this will also set USER_BASE if USER_SITE is None: - USER_SITE = _get_path(userbase) + if userbase is None: + ENABLE_USER_SITE = False # disable user site and return None + else: + USER_SITE = _get_path(userbase) return USER_SITE @@ -630,11 +637,14 @@ def _script(): 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) + def exists(path): + if path is not None and os.path.isdir(path): + return "exists" + else: + return "doesn't exist" + print(f"USER_BASE: {user_base!r} ({exists(user_base)})") + print(f"USER_SITE: {user_site!r} ({exists(user_site)})") + print(f"ENABLE_USER_SITE: {ENABLE_USER_SITE!r}") sys.exit(0) buffer = [] diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index e1b2f93..c1aaf79 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -51,34 +51,65 @@ _INSTALL_SCHEMES = { 'scripts': '{base}/Scripts', 'data': '{base}', }, - # NOTE: When modifying "purelib" scheme, update site._get_path() too. - 'nt_user': { - 'stdlib': '{userbase}/Python{py_version_nodot_plat}', - 'platstdlib': '{userbase}/Python{py_version_nodot_plat}', - 'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages', - 'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages', - 'include': '{userbase}/Python{py_version_nodot_plat}/Include', - 'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts', - 'data': '{userbase}', - }, - 'posix_user': { - 'stdlib': '{userbase}/{platlibdir}/python{py_version_short}', - 'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}', - 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', - 'platlib': '{userbase}/{platlibdir}/python{py_version_short}/site-packages', - 'include': '{userbase}/include/python{py_version_short}', - 'scripts': '{userbase}/bin', - 'data': '{userbase}', - }, - 'osx_framework_user': { - 'stdlib': '{userbase}/lib/python', - 'platstdlib': '{userbase}/lib/python', - 'purelib': '{userbase}/lib/python/site-packages', - 'platlib': '{userbase}/lib/python/site-packages', - 'include': '{userbase}/include', - 'scripts': '{userbase}/bin', - 'data': '{userbase}', - }, + } + + +# NOTE: site.py has copy of this function. +# Sync it when modify this function. +def _getuserbase(): + env_base = os.environ.get("PYTHONUSERBASE", None) + if env_base: + return env_base + + # VxWorks has no home directories + if sys.platform == "vxworks": + return None + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + return joinuser(base, "Python") + + if sys.platform == "darwin" and sys._framework: + return joinuser("~", "Library", sys._framework, + "%d.%d" % sys.version_info[:2]) + + return joinuser("~", ".local") + +_HAS_USER_BASE = (_getuserbase() is not None) + +if _HAS_USER_BASE: + _INSTALL_SCHEMES |= { + # NOTE: When modifying "purelib" scheme, update site._get_path() too. + 'nt_user': { + 'stdlib': '{userbase}/Python{py_version_nodot_plat}', + 'platstdlib': '{userbase}/Python{py_version_nodot_plat}', + 'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages', + 'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages', + 'include': '{userbase}/Python{py_version_nodot_plat}/Include', + 'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts', + 'data': '{userbase}', + }, + 'posix_user': { + 'stdlib': '{userbase}/{platlibdir}/python{py_version_short}', + 'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}', + 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', + 'platlib': '{userbase}/{platlibdir}/python{py_version_short}/site-packages', + 'include': '{userbase}/include/python{py_version_short}', + 'scripts': '{userbase}/bin', + 'data': '{userbase}', + }, + 'osx_framework_user': { + 'stdlib': '{userbase}/lib/python', + 'platstdlib': '{userbase}/lib/python', + 'purelib': '{userbase}/lib/python/site-packages', + 'platlib': '{userbase}/lib/python/site-packages', + 'include': '{userbase}/include', + 'scripts': '{userbase}/bin', + 'data': '{userbase}', + }, } _SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include', @@ -183,25 +214,6 @@ def _get_default_scheme(): return os.name -# NOTE: site.py has copy of this function. -# Sync it when modify this function. -def _getuserbase(): - env_base = os.environ.get("PYTHONUSERBASE", None) - if env_base: - return env_base - - def joinuser(*args): - return os.path.expanduser(os.path.join(*args)) - - if os.name == "nt": - base = os.environ.get("APPDATA") or "~" - return joinuser(base, "Python") - - if sys.platform == "darwin" and sys._framework: - return joinuser("~", "Library", sys._framework, - "%d.%d" % sys.version_info[:2]) - - return joinuser("~", ".local") def _parse_makefile(filename, vars=None): @@ -558,10 +570,11 @@ def get_config_vars(*args): SO = _CONFIG_VARS.get('EXT_SUFFIX') if SO is not None: _CONFIG_VARS['SO'] = SO - # Setting 'userbase' is done below the call to the - # init function to enable using 'get_config_var' in - # the init-function. - _CONFIG_VARS['userbase'] = _getuserbase() + if _HAS_USER_BASE: + # Setting 'userbase' is done below the call to the + # init function to enable using 'get_config_var' in + # the init-function. + _CONFIG_VARS['userbase'] = _getuserbase() # Always convert srcdir to an absolute path srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 2e70880..6060288 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -36,6 +36,7 @@ if sys.flags.no_site: import site +HAS_USER_SITE = (site.USER_SITE is not None) OLD_SYS_PATH = None @@ -195,6 +196,7 @@ class HelperFunctionsTests(unittest.TestCase): def test__getuserbase(self): self.assertEqual(site._getuserbase(), sysconfig._getuserbase()) + @unittest.skipUnless(HAS_USER_SITE, 'need user site') def test_get_path(self): if sys.platform == 'darwin' and sys._framework: scheme = 'osx_framework_user' @@ -244,6 +246,7 @@ class HelperFunctionsTests(unittest.TestCase): self.assertEqual(rc, 1, "User base not set by PYTHONUSERBASE") + @unittest.skipUnless(HAS_USER_SITE, 'need user site') def test_getuserbase(self): site.USER_BASE = None user_base = site.getuserbase() @@ -261,6 +264,7 @@ class HelperFunctionsTests(unittest.TestCase): self.assertTrue(site.getuserbase().startswith('xoxo'), site.getuserbase()) + @unittest.skipUnless(HAS_USER_SITE, 'need user site') def test_getusersitepackages(self): site.USER_SITE = None site.USER_BASE = None @@ -295,6 +299,7 @@ class HelperFunctionsTests(unittest.TestCase): wanted = os.path.join('xoxo', 'lib', 'site-packages') self.assertEqual(dirs[1], wanted) + @unittest.skipUnless(HAS_USER_SITE, 'need user site') def test_no_home_directory(self): # bpo-10496: getuserbase() and getusersitepackages() must not fail if # the current user has no home directory (if expanduser() returns the diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 352dbde..e279957 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -18,6 +18,10 @@ from sysconfig import (get_paths, get_platform, get_config_vars, get_scheme_names, get_config_var, _main) import _osx_support + +HAS_USER_BASE = sysconfig._HAS_USER_BASE + + class TestSysConfig(unittest.TestCase): def setUp(self): @@ -230,9 +234,10 @@ class TestSysConfig(unittest.TestCase): self.assertTrue(os.path.isfile(config_h), config_h) def test_get_scheme_names(self): - wanted = ('nt', 'nt_user', 'osx_framework_user', - 'posix_home', 'posix_prefix', 'posix_user') - self.assertEqual(get_scheme_names(), wanted) + wanted = ['nt', 'posix_home', 'posix_prefix'] + if HAS_USER_BASE: + wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) + self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) @skip_unless_symlink def test_symlink(self): # Issue 7880 @@ -244,7 +249,8 @@ class TestSysConfig(unittest.TestCase): # Issue #8759: make sure the posix scheme for the users # is similar to the global posix_prefix one base = get_config_var('base') - user = get_config_var('userbase') + if HAS_USER_BASE: + user = get_config_var('userbase') # the global scheme mirrors the distinction between prefix and # exec-prefix but not the user scheme, so we have to adapt the paths # before comparing (issue #9100) @@ -259,8 +265,9 @@ class TestSysConfig(unittest.TestCase): # before comparing global_path = global_path.replace(sys.base_prefix, sys.prefix) base = base.replace(sys.base_prefix, sys.prefix) - user_path = get_path(name, 'posix_user') - self.assertEqual(user_path, global_path.replace(base, user, 1)) + if HAS_USER_BASE: + user_path = get_path(name, 'posix_user') + self.assertEqual(user_path, global_path.replace(base, user, 1)) def test_main(self): # just making sure _main() runs and returns things in the stdout diff --git a/Misc/NEWS.d/next/Library/2020-08-11-17-44-07.bpo-31904.cb13ea.rst b/Misc/NEWS.d/next/Library/2020-08-11-17-44-07.bpo-31904.cb13ea.rst new file mode 100644 index 0000000..a7164b7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-11-17-44-07.bpo-31904.cb13ea.rst @@ -0,0 +1 @@ +Fix site and sysconfig modules for VxWorks RTOS which has no home directories. -- cgit v0.12