# DP: distutils: Add an option --install-layout=deb, which
# DP: - installs into $prefix/dist-packages instead of $prefix/site-packages.
# DP: - doesn't encode the python version into the egg name.

Index: b/Doc/install/index.rst
===================================================================
--- a/Doc/install/index.rst
+++ b/Doc/install/index.rst
@@ -240,6 +240,8 @@
 +-----------------+-----------------------------------------------------+--------------------------------------------------+-------+
 | Platform        | Standard installation location                      | Default value                                    | Notes |
 +=================+=====================================================+==================================================+=======+
+| Debian/Ubuntu   | :file:`{prefix}/lib/python3/dist-packages`          | :file:`/usr/local/lib/python{X.Y}/dist-packages` | \(0)  |
++-----------------+-----------------------------------------------------+--------------------------------------------------+-------+
 | Unix (pure)     | :file:`{prefix}/lib/python{X.Y}/site-packages`      | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1)  |
 +-----------------+-----------------------------------------------------+--------------------------------------------------+-------+
 | Unix (non-pure) | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1)  |
@@ -249,6 +251,17 @@
 
 Notes:
 
+(0)
+   Starting with Python-2.6 Debian/Ubuntu uses for the Python which comes within
+   the Linux distribution a non-default name for the installation directory. This
+   is to avoid overwriting of the python modules which come with the distribution,
+   which unfortunately is the upstream behaviour of the installation tools. The
+   non-default name in :file:`/usr/local` is used not to overwrite a local python
+   installation (defaulting to :file:`/usr/local`).
+
+   Starting with Python3, Debian/Ubuntu use a common installation directory for
+   all Python3 versions.
+
 (1)
    Most Linux distributions include Python as a standard part of the system, so
    :file:`{prefix}` and :file:`{exec-prefix}` are usually both :file:`/usr` on
@@ -432,6 +445,15 @@
 
    /usr/bin/python setup.py install --prefix=/usr/local
 
+Starting with Python3 Debian/Ubuntu does use
+:file:`/usr/lib/python3/dist-packages` and
+:file:`/usr/local/lib/python{X.Y}/dist-packages` for the installation
+of python modules included in the Linux distribution.  To overwrite
+the name of the site directory, explicitely use the :option:`--prefix`
+option, however make sure that the installation path is included in
+``sys.path``.  For packaging of python modules for Debian/Ubuntu, use
+the new ``setup.py install`` option :option:`--install-layout=deb`.
+
 Another possibility is a network filesystem where the name used to write to a
 remote directory is different from the name used to read it: for example, the
 Python interpreter accessed as :file:`/usr/local/bin/python` might search for
@@ -683,6 +705,17 @@
 import them, this directory must be added to ``sys.path``.  There are several
 different ways to add the directory.
 
+On Debian/Ubuntu, starting with Python3 the convention for system
+installed packages is to put then in the
+:file:`/usr/lib/python3/dist-packages/` directory, and for locally
+installed packages is to put them in the
+:file:`/usr/local/lib/python{X.Y}/dist-packages/` directory.  To share the
+locally installed packages for the system provided Python with the
+locally installed packages of a local python installation, make
+:file:`/usr/local/lib/python{X.Y}/dist-packages/` a symbolic link to the
+:file:`{...}/site-packages/` directory of your local python
+installation.
+
 The most convenient way is to add a path configuration file to a directory
 that's already on Python's path, usually to the :file:`.../site-packages/`
 directory.  Path configuration files have an extension of :file:`.pth`, and each
Index: b/Lib/distutils/command/install_egg_info.py
===================================================================
--- a/Lib/distutils/command/install_egg_info.py
+++ b/Lib/distutils/command/install_egg_info.py
@@ -14,18 +14,38 @@
     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]
 
Index: b/Lib/distutils/command/install.py
===================================================================
--- a/Lib/distutils/command/install.py
+++ b/Lib/distutils/command/install.py
@@ -50,6 +50,20 @@
         'scripts': '$base/bin',
         'data'   : '$base',
         },
+    'unix_local': {
+        'purelib': '$base/local/lib/python$py_version_short/dist-packages',
+        'platlib': '$platbase/local/lib/python$py_version_short/dist-packages',
+        'headers': '$base/local/include/python$py_version_short$abiflags/$dist_name',
+        'scripts': '$base/local/bin',
+        'data'   : '$base/local',
+        },
+    'deb_system': {
+        'purelib': '$base/lib/python3/dist-packages',
+        'platlib': '$platbase/lib/python3/dist-packages',
+        'headers': '$base/include/python$py_version_short$abiflags/$dist_name',
+        'scripts': '$base/bin',
+        'data'   : '$base',
+        },
     'unix_home': {
         'purelib': '$base/lib/python',
         'platlib': '$base/lib/python',
@@ -161,6 +175,9 @@
 
         ('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']
@@ -181,6 +198,7 @@
         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
@@ -202,6 +220,9 @@
         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
 
@@ -441,6 +462,7 @@
             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(
@@ -455,7 +477,23 @@
 
             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("deb_system")
+                elif self.install_layout.lower() in ['unix']:
+                    self.select_scheme("unix_prefix")
+                else:
+                    raise DistutilsOptionError(
+                        "unknown value for --install-layout")
+            elif (self.prefix_option and os.path.normpath(self.prefix) != '/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) == '/usr/local':
+                    self.prefix = self.exec_prefix = '/usr'
+                    self.install_base = self.install_platbase = '/usr'
+                self.select_scheme("unix_local")
 
     def finalize_other(self):
         """Finalizes options for non-posix platforms"""
Index: b/Lib/distutils/sysconfig.py
===================================================================
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -118,6 +118,7 @@
     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) in ('/usr', '/usr/local')
     if prefix is None:
         prefix = plat_specific and EXEC_PREFIX or PREFIX
 
@@ -126,6 +127,8 @@
                                  "lib", "python" + get_python_version())
         if standard_lib:
             return libpython
+        elif is_default_prefix and 'PYTHONUSERBASE' not in os.environ and 'real_prefix' not in sys.__dict__:
+            return os.path.join(prefix, "lib", "python3", "dist-packages")
         else:
             return os.path.join(libpython, "site-packages")
     elif os.name == "nt":
Index: b/Lib/site.py
===================================================================
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -270,6 +270,13 @@
 
     if ENABLE_USER_SITE and os.path.isdir(user_site):
         addsitedir(user_site, known_paths)
+    if ENABLE_USER_SITE:
+        for dist_libdir in ("lib", "local/lib"):
+            user_site = os.path.join(USER_BASE, dist_libdir,
+                                     "python" + sys.version[:3],
+                                     "dist-packages")
+            if os.path.isdir(user_site):
+                addsitedir(user_site, known_paths)
     return known_paths
 
 def getsitepackages():
Index: b/Lib/sysconfig.py
===================================================================
--- a/Lib/sysconfig.py
+++ b/Lib/sysconfig.py
@@ -32,6 +32,26 @@
         'scripts': '{base}/bin',
         'data': '{base}',
         },
+    'posix_local': {
+        'stdlib': '{base}/local/lib/python{py_version_short}',
+        'platstdlib': '{platbase}/local/lib/python{py_version_short}',
+        'purelib': '{base}/local/lib/python{py_version_short}/dist-packages',
+        'platlib': '{platbase}/local/lib/python{py_version_short}/dist-packages',
+        'include': '{base}/local/include/python{py_version_short}',
+        'platinclude': '{platbase}/local/include/python{py_version_short}',
+        'scripts': '{base}/local/bin',
+        'data': '{base}/local',
+        },
+    'deb_system': {
+        'stdlib': '{base}/lib/python{py_version_short}',
+        'platstdlib': '{platbase}/lib/python{py_version_short}',
+        'purelib': '{base}/lib/python3/dist-packages',
+        'platlib': '{platbase}/lib/python3/dist-packages',
+        'include': '{base}/include/python{py_version_short}',
+        'platinclude': '{platbase}/include/python{py_version_short}',
+        'scripts': '{base}/bin',
+        'data': '{base}',
+        },
     'posix_home': {
         'stdlib': '{base}/lib/python',
         'platstdlib': '{base}/lib/python',
Index: b/Lib/test/test_site.py
===================================================================
--- a/Lib/test/test_site.py
+++ b/Lib/test/test_site.py
@@ -236,12 +236,20 @@
             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(len(dirs), 4)
+            wanted = os.path.join('xoxo', 'local', 'lib',
+                                  'python' + sys.version[:3],
+                                  'dist-packages')
             self.assertEqual(dirs[0], wanted)
-            wanted = os.path.join('xoxo', 'lib', 'site-python')
+            wanted = os.path.join('xoxo', 'lib',
+                                  'python3', 'dist-packages')
             self.assertEqual(dirs[1], wanted)
+            wanted = os.path.join('xoxo', 'lib',
+                                  'python' + sys.version[:3],
+                                  'dist-packages')
+            self.assertEqual(dirs[2], wanted)
+            wanted = os.path.join('xoxo', 'lib', 'dist-python')
+            self.assertEqual(dirs[3], wanted)
         else:
             # other platforms
             self.assertEqual(len(dirs), 2)
Index: b/Lib/distutils/tests/test_bdist_dumb.py
===================================================================
--- a/Lib/distutils/tests/test_bdist_dumb.py
+++ b/Lib/distutils/tests/test_bdist_dumb.py
@@ -88,7 +88,7 @@
             fp.close()
 
         contents = sorted(os.path.basename(fn) for fn in contents)
-        wanted = ['foo-0.1-py%s.%s.egg-info' % sys.version_info[:2],
+        wanted = ['foo-0.1.egg-info',
                   'foo.%s.pyc' % imp.get_tag(),
                   'foo.py']
         self.assertEqual(contents, sorted(wanted))
Index: b/Lib/distutils/tests/test_install.py
===================================================================
--- a/Lib/distutils/tests/test_install.py
+++ b/Lib/distutils/tests/test_install.py
@@ -194,7 +194,7 @@
 
         found = [os.path.basename(line) for line in content.splitlines()]
         expected = ['hello.py', 'hello.%s.pyc' % imp.get_tag(), 'sayhi',
-                    'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
+                    'UNKNOWN-0.0.0.egg-info']
         self.assertEqual(found, expected)
 
     def test_record_extensions(self):
@@ -224,7 +224,7 @@
 
         found = [os.path.basename(line) for line in content.splitlines()]
         expected = [_make_ext_name('xx'),
-                    'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
+                    'UNKNOWN-0.0.0.egg-info']
         self.assertEqual(found, expected)
 
     def test_debug_mode(self):
Index: b/Lib/pydoc.py
===================================================================
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -372,6 +372,7 @@
                                  '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://"):
