aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsetuptools/command/develop.py6
-rwxr-xr-xsetuptools/namespaces.py11
-rw-r--r--setuptools/tests/test_develop.py49
3 files changed, 63 insertions, 3 deletions
diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py
index 3eb86120..aa82f959 100755
--- a/setuptools/command/develop.py
+++ b/setuptools/command/develop.py
@@ -9,10 +9,11 @@ from setuptools.extern import six
from pkg_resources import Distribution, PathMetadata, normalize_path
from setuptools.command.easy_install import easy_install
+from setuptools import namespaces
import setuptools
-class develop(easy_install):
+class develop(namespaces.DevelopInstaller, easy_install):
"""Set up package for development"""
description = "install package in 'development mode'"
@@ -30,6 +31,7 @@ class develop(easy_install):
if self.uninstall:
self.multi_version = True
self.uninstall_link()
+ self.uninstall_namespaces()
else:
self.install_for_development()
self.warn_deprecated_options()
@@ -123,6 +125,8 @@ class develop(easy_install):
self.easy_install(setuptools.bootstrap_install_from)
setuptools.bootstrap_install_from = None
+ self.install_namespaces()
+
# create an .egg-link in the installation dir, pointing to our egg
log.info("Creating %s (link to %s)", self.egg_link, self.egg_base)
if not self.dry_run:
diff --git a/setuptools/namespaces.py b/setuptools/namespaces.py
index cc934b7e..9c1f0243 100755
--- a/setuptools/namespaces.py
+++ b/setuptools/namespaces.py
@@ -30,6 +30,14 @@ class Installer:
with open(filename, 'wt') as f:
f.writelines(lines)
+ def uninstall_namespaces(self):
+ filename, ext = os.path.splitext(self._get_target())
+ filename += self.nspkg_ext
+ if not os.path.exists(filename):
+ return
+ log.info("Removing %s", filename)
+ os.remove(filename)
+
def _get_target(self):
return self.target
@@ -37,8 +45,7 @@ class Installer:
"import sys, types, os",
"pep420 = sys.version_info > (3, 3)",
"p = os.path.join(%(root)s, *%(pth)r)",
- "ie = os.path.exists(os.path.join(p,'__init__.py'))",
- "m = not ie and not pep420 and "
+ "m = "
"sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))",
"mp = (m or []) and m.__dict__.setdefault('__path__',[])",
"(p not in mp) and mp.append(p)",
diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py
index 4cf483f2..e0227453 100644
--- a/setuptools/tests/test_develop.py
+++ b/setuptools/tests/test_develop.py
@@ -1,9 +1,13 @@
"""develop tests
"""
+
+from __future__ import absolute_import, unicode_literals
+
import os
import site
import sys
import io
+import subprocess
from setuptools.extern import six
@@ -12,6 +16,7 @@ import pytest
from setuptools.command.develop import develop
from setuptools.dist import Distribution
from . import contexts
+from . import namespaces
SETUP_PY = """\
from setuptools import setup
@@ -114,3 +119,47 @@ class TestDevelop:
cmd.install_dir = tmpdir
cmd.run()
# assert '0.0' not in foocmd_text
+
+
+class TestNamespaces:
+
+ @staticmethod
+ def install_develop(src_dir, target):
+
+ develop_cmd = [
+ sys.executable,
+ 'setup.py',
+ 'develop',
+ '--install-dir', str(target),
+ ]
+ env = dict(PYTHONPATH=str(target))
+ with src_dir.as_cwd():
+ subprocess.check_call(develop_cmd, env=env)
+
+ def test_namespace_package_importable(self, tmpdir):
+ """
+ Installing two packages sharing the same namespace, one installed
+ naturally using pip or `--single-version-externally-managed`
+ and the other installed using `develop` should leave the namespace
+ in tact and both packages reachable by import.
+ """
+ pkg_A = namespaces.build_namespace_package(tmpdir, 'myns.pkgA')
+ pkg_B = namespaces.build_namespace_package(tmpdir, 'myns.pkgB')
+ target = tmpdir / 'packages'
+ # use pip to install to the target directory
+ install_cmd = [
+ 'pip',
+ 'install',
+ str(pkg_A),
+ '-t', str(target),
+ ]
+ subprocess.check_call(install_cmd)
+ self.install_develop(pkg_B, target)
+ namespaces.make_site_dir(target)
+ try_import = [
+ sys.executable,
+ '-c', 'import myns.pkgA; import myns.pkgB',
+ ]
+ env = dict(PYTHONPATH=str(target))
+ subprocess.check_call(try_import, env=env)
+