From: Stefano Rivera Date: Sat, 7 Oct 2017 09:38:58 +0200 Subject: distutils: Add an option --install-layout=deb This option: - installs into $prefix/dist-packages instead of $prefix/site-packages. - doesn't encode the python version into the egg name. Based on cpython Debian packaging Author: Matthias Klose Author: Stefano Rivera Last-Update: 2013-02-23 --- lib-python/2.7/distutils/command/install.py | 44 +++++++++++++++++++++- .../2.7/distutils/command/install_egg_info.py | 30 ++++++++++++--- lib-python/2.7/distutils/sysconfig_pypy.py | 6 ++- lib-python/2.7/pydoc.py | 1 + lib-python/2.7/site.py | 18 ++++++++- lib-python/2.7/sysconfig.py | 29 +++++++++++++- lib-python/2.7/test/test_site.py | 2 +- lib-python/2.7/test/test_sysconfig.py | 3 +- 8 files changed, 119 insertions(+), 14 deletions(-) diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py index fc43951..76fdd75 100644 --- a/lib-python/2.7/distutils/command/install.py +++ b/lib-python/2.7/distutils/command/install.py @@ -90,6 +90,20 @@ INSTALL_SCHEMES = { 'scripts': '$base/bin', 'data' : '$base', }, + 'pypy-deb': { + 'purelib': '$base/dist-packages', + 'platlib': '$base/dist-packages', + 'headers': '$base/include', + 'scripts': '$base/bin', + 'data' : '$base', + }, + 'pypy-local': { + 'purelib': '$base/../../local/lib/pypy$py_version_short/dist-packages', + 'platlib': '$base/../../local/lib/pypy$py_version_short/dist-packages', + 'headers': '$base/../../local/include', + 'scripts': '$base/../../local/bin', + 'data' : '$base/../../local', + }, } # The keys to an installation scheme; if any new types of files are to be @@ -161,6 +175,9 @@ class install (Command): ('record=', None, "filename in which to record list of installed files"), + + ('install-layout=', None, + "installation layout to choose (known values: deb, unix)"), ] boolean_options = ['compile', 'force', 'skip-build', 'user'] @@ -175,6 +192,7 @@ class install (Command): self.exec_prefix = None self.home = None self.user = 0 + self.prefix_option = None # These select only the installation base; it's up to the user to # specify the installation scheme (currently, that means supplying @@ -196,6 +214,9 @@ class install (Command): self.install_userbase = USER_BASE self.install_usersite = USER_SITE + # enable custom installation, known values: deb + self.install_layout = None + self.compile = None self.optimize = None @@ -428,6 +449,7 @@ class install (Command): self.install_base = self.install_platbase = self.home self.select_scheme("unix_home") else: + self.prefix_option = self.prefix if self.prefix is None: if self.exec_prefix is not None: raise DistutilsOptionError, \ @@ -442,7 +464,25 @@ class install (Command): self.install_base = self.prefix self.install_platbase = self.exec_prefix - self.select_scheme("unix_prefix") + if self.install_layout: + if self.install_layout.lower() in ['deb']: + self.select_scheme("pypy-deb") + elif self.install_layout.lower() in ['posix', 'unix']: + self.select_scheme("unix_prefix") + else: + raise DistutilsOptionError( + "unknown value for --install-layout") + elif ((self.prefix_option + and not os.path.normpath(self.prefix).startswith( + '/usr/local/')) + or 'PYTHONUSERBASE' in os.environ + or 'real_prefix' in sys.__dict__): + self.select_scheme("unix_prefix") + else: + if os.path.normpath(self.prefix).startswith('/usr/local/'): + self.select_scheme("pypy-deb") + else: + self.select_scheme("pypy-local") # finalize_unix () @@ -475,7 +515,7 @@ class install (Command): def select_scheme (self, name): # it's the caller's problem if they supply a bad name! if (hasattr(sys, 'pypy_version_info') and - not name.endswith(('_user', '_home'))): + not (name.endswith(('_user', '_home')) or name.startswith('pypy'))): name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: diff --git a/lib-python/2.7/distutils/command/install_egg_info.py b/lib-python/2.7/distutils/command/install_egg_info.py index c888031..88b5d94 100644 --- a/lib-python/2.7/distutils/command/install_egg_info.py +++ b/lib-python/2.7/distutils/command/install_egg_info.py @@ -14,18 +14,38 @@ class install_egg_info(Command): description = "Install package's PKG-INFO metadata as an .egg-info file" user_options = [ ('install-dir=', 'd', "directory to install to"), + ('install-layout', None, "custom installation layout"), ] def initialize_options(self): self.install_dir = None + self.install_layout = None + self.prefix_option = None def finalize_options(self): self.set_undefined_options('install_lib',('install_dir','install_dir')) - basename = "%s-%s-py%s.egg-info" % ( - to_filename(safe_name(self.distribution.get_name())), - to_filename(safe_version(self.distribution.get_version())), - sys.version[:3] - ) + self.set_undefined_options('install',('install_layout','install_layout')) + self.set_undefined_options('install',('prefix_option','prefix_option')) + if self.install_layout: + if not self.install_layout.lower() in ['deb', 'unix']: + raise DistutilsOptionError( + "unknown value for --install-layout") + no_pyver = (self.install_layout.lower() == 'deb') + elif self.prefix_option: + no_pyver = False + else: + no_pyver = True + if no_pyver: + basename = "%s-%s.egg-info" % ( + to_filename(safe_name(self.distribution.get_name())), + to_filename(safe_version(self.distribution.get_version())) + ) + else: + basename = "%s-%s-py%s.egg-info" % ( + to_filename(safe_name(self.distribution.get_name())), + to_filename(safe_version(self.distribution.get_version())), + sys.version[:3] + ) self.target = os.path.join(self.install_dir, basename) self.outputs = [self.target] diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py index 9b0d941..d6f4bdb 100644 --- a/lib-python/2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -49,11 +49,15 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): If 'prefix' is supplied, use it instead of sys.prefix or sys.exec_prefix -- i.e., ignore 'plat_specific'. """ + is_default_prefix = not prefix or os.path.normpath(prefix).startswith(('/usr/lib/pypy')) if prefix is None: prefix = PREFIX if standard_lib: return os.path.join(prefix, "lib-python", get_python_version()) - return os.path.join(prefix, 'site-packages') + if is_default_prefix and 'PYTHONUSERBASE' not in os.environ and 'real_prefix' not in sys.__dict__: + return os.path.join(prefix, 'dist-packages') + else: + return os.path.join(prefix, 'site-packages') _config_vars = None diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py index 14ff9bb..985f285 100755 --- a/lib-python/2.7/pydoc.py +++ b/lib-python/2.7/pydoc.py @@ -393,6 +393,7 @@ class Doc: 'marshal', 'posix', 'signal', 'sys', 'thread', 'zipimport') or (file.startswith(basedir) and + not file.startswith(os.path.join(basedir, 'dist-packages')) and not file.startswith(os.path.join(basedir, 'site-packages')))) and object.__name__ not in ('xml.etree', 'test.pydoc_mod')): if docloc.startswith(("http://", "https://")): diff --git a/lib-python/2.7/site.py b/lib-python/2.7/site.py index 37de98e..7cfa6be 100644 --- a/lib-python/2.7/site.py +++ b/lib-python/2.7/site.py @@ -12,13 +12,18 @@ works). This will append site-specific paths to the module search path. On Unix (including Mac OSX), it starts with sys.prefix and -sys.exec_prefix (if different) and appends -lib/python/site-packages as well as lib/site-python. +sys.exec_prefix (if different) and appends dist-packages. On other platforms (such as Windows), it tries each of the prefixes directly, as well as with lib/site-packages appended. The resulting directories, if they exist, are appended to sys.path, and also inspected for path configuration files. +For Debian and derivatives, this sys.path is augmented with directories +for packages distributed within the distribution. Local addons go +into /usr/local/lib/pypy/dist-packages, Debian addons +install into /usr/{lib,share}/pypy/dist-packages. +/usr/lib/pypy/site-packages is not used. + A path configuration file is a file whose name has the form .pth; its contents are additional directories (one per line) to be added to sys.path. Non-existing directories (or @@ -277,6 +282,13 @@ def addusersitepackages(known_paths): if ENABLE_USER_SITE and os.path.isdir(user_site): addsitedir(user_site, known_paths) + if ENABLE_USER_SITE: + for dist_libdir in ("local/lib", "lib"): + user_site = os.path.join(USER_BASE, dist_libdir, + "pypy" + sys.version[:3], + "dist-packages") + if os.path.isdir(user_site): + addsitedir(user_site, known_paths) return known_paths def getsitepackages(): @@ -301,6 +313,8 @@ def getsitepackages(): elif is_pypy: from distutils.sysconfig import get_python_lib sitedir = get_python_lib(standard_lib=False, prefix=prefix) + sitepackages.append(sitedir.replace('lib/pypy', 'local/lib/' + 'pypy' + sys.version[:3])) sitepackages.append(sitedir) elif os.sep == '/': sitepackages.append(os.path.join(prefix, "lib", diff --git a/lib-python/2.7/sysconfig.py b/lib-python/2.7/sysconfig.py index 22af6e8..9be6a5b 100644 --- a/lib-python/2.7/sysconfig.py +++ b/lib-python/2.7/sysconfig.py @@ -36,6 +36,26 @@ _INSTALL_SCHEMES = { 'scripts': '{base}/bin', 'data' : '{base}', }, + 'pypy-deb': { + 'stdlib': '{base}/lib-python', + 'platstdlib': '{base}/lib-python', + 'purelib': '{base}/lib-python', + 'platlib': '{base}/lib-python', + 'include': '{base}/include', + 'platinclude': '{base}/include', + 'scripts': '{base}/bin', + 'data' : '{base}', + }, + 'pypy-local': { + 'stdlib': '{base}/../../local/lib/pypy{py_version_short}/lib-python', + 'platstdlib': '{base}/../../local/lib/pypy{py_version_short}/lib-python', + 'purelib': '{base}/../../local/lib/pypy{py_version_short}/lib-python', + 'platlib': '{base}/../../local/lib/pypy{py_version_short}/lib-python', + 'include': '{base}/../../local/include', + 'platinclude': '{base}/../../local/include', + 'scripts': '{base}/../../local/bin', + 'data' : '{base}/../../local', + }, 'nt': { 'stdlib': '{base}/Lib', 'platstdlib': '{base}/Lib', @@ -178,7 +198,11 @@ def _expand_vars(scheme, vars): def _get_default_scheme(): if '__pypy__' in sys.builtin_module_names: - return 'pypy' + # the default scheme for posix on Debian/Ubuntu is pypy-local + # FIXME: return dist-packages/posix_prefix only for + # is_default_prefix and 'PYTHONUSERBASE' not in os.environ and 'real_prefix' not in sys.__dict__ + # is_default_prefix = not prefix or os.path.normpath(prefix) in ('/usr', '/usr/local') + return 'pypy-local' elif os.name == 'posix': # the default scheme for posix is posix_prefix return 'posix_prefix' @@ -425,7 +449,8 @@ def get_config_h_filename(): else: inc_dir = _PROJECT_BASE else: - inc_dir = get_path('platinclude') + inc_dir = get_path('platinclude', 'pypy-deb').replace("/../../local/", + "/", 1) return os.path.join(inc_dir, 'pyconfig.h') def get_scheme_names(): diff --git a/lib-python/2.7/test/test_site.py b/lib-python/2.7/test/test_site.py index 02331be..8a34204 100644 --- a/lib-python/2.7/test/test_site.py +++ b/lib-python/2.7/test/test_site.py @@ -234,7 +234,7 @@ class HelperFunctionsTests(unittest.TestCase): wanted = os.path.join('xoxo', 'Lib', 'site-packages') self.assertEqual(dirs[0], wanted) elif '__pypy__' in sys.builtin_module_names: - self.assertEquals(len(dirs), 1) + self.assertEquals(len(dirs), 2) wanted = os.path.join('xoxo', 'site-packages') self.assertEquals(dirs[0], wanted) elif os.sep == '/': diff --git a/lib-python/2.7/test/test_sysconfig.py b/lib-python/2.7/test/test_sysconfig.py index 95d3a3c..a874d8d 100644 --- a/lib-python/2.7/test/test_sysconfig.py +++ b/lib-python/2.7/test/test_sysconfig.py @@ -253,7 +253,8 @@ class TestSysConfig(unittest.TestCase): def test_get_scheme_names(self): wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user', - 'posix_home', 'posix_prefix', 'posix_user', 'pypy') + 'posix_home', 'posix_prefix', 'posix_user', 'pypy', + 'pypy-deb', 'pypy-local') self.assertEqual(get_scheme_names(), wanted) @unittest.skipIf(check_impl_detail(pypy=True),