1import sys
2import subprocess
3
4import pytest
5
6from . import namespaces
7from setuptools.command import test
8
9
10class TestNamespaces:
11
12    @pytest.mark.skipif(
13        sys.version_info < (3, 5),
14        reason="Requires importlib.util.module_from_spec",
15    )
16    def test_mixed_site_and_non_site(self, tmpdir):
17        """
18        Installing two packages sharing the same namespace, one installed
19        to a site dir and the other installed just to a path on PYTHONPATH
20        should leave the namespace in tact and both packages reachable by
21        import.
22        """
23        pkg_A = namespaces.build_namespace_package(tmpdir, 'myns.pkgA')
24        pkg_B = namespaces.build_namespace_package(tmpdir, 'myns.pkgB')
25        site_packages = tmpdir / 'site-packages'
26        path_packages = tmpdir / 'path-packages'
27        targets = site_packages, path_packages
28        # use pip to install to the target directory
29        install_cmd = [
30            sys.executable,
31            '-m',
32            'pip.__main__',
33            'install',
34            str(pkg_A),
35            '-t', str(site_packages),
36        ]
37        subprocess.check_call(install_cmd)
38        namespaces.make_site_dir(site_packages)
39        install_cmd = [
40            sys.executable,
41            '-m',
42            'pip.__main__',
43            'install',
44            str(pkg_B),
45            '-t', str(path_packages),
46        ]
47        subprocess.check_call(install_cmd)
48        try_import = [
49            sys.executable,
50            '-c', 'import myns.pkgA; import myns.pkgB',
51        ]
52        with test.test.paths_on_pythonpath(map(str, targets)):
53            subprocess.check_call(try_import)
54
55    def test_pkg_resources_import(self, tmpdir):
56        """
57        Ensure that a namespace package doesn't break on import
58        of pkg_resources.
59        """
60        pkg = namespaces.build_namespace_package(tmpdir, 'myns.pkgA')
61        target = tmpdir / 'packages'
62        target.mkdir()
63        install_cmd = [
64            sys.executable,
65            '-m', 'pip',
66            'install',
67            '-t', str(target),
68            str(pkg),
69        ]
70        with test.test.paths_on_pythonpath([str(target)]):
71            subprocess.check_call(install_cmd)
72        namespaces.make_site_dir(target)
73        try_import = [
74            sys.executable,
75            '-c', 'import pkg_resources',
76        ]
77        with test.test.paths_on_pythonpath([str(target)]):
78            subprocess.check_call(try_import)
79
80    def test_namespace_package_installed_and_cwd(self, tmpdir):
81        """
82        Installing a namespace packages but also having it in the current
83        working directory, only one version should take precedence.
84        """
85        pkg_A = namespaces.build_namespace_package(tmpdir, 'myns.pkgA')
86        target = tmpdir / 'packages'
87        # use pip to install to the target directory
88        install_cmd = [
89            sys.executable,
90            '-m',
91            'pip.__main__',
92            'install',
93            str(pkg_A),
94            '-t', str(target),
95        ]
96        subprocess.check_call(install_cmd)
97        namespaces.make_site_dir(target)
98
99        # ensure that package imports and pkg_resources imports
100        pkg_resources_imp = [
101            sys.executable,
102            '-c', 'import pkg_resources; import myns.pkgA',
103        ]
104        with test.test.paths_on_pythonpath([str(target)]):
105            subprocess.check_call(pkg_resources_imp, cwd=str(pkg_A))
106
107    def test_packages_in_the_same_namespace_installed_and_cwd(self, tmpdir):
108        """
109        Installing one namespace package and also have another in the same
110        namespace in the current working directory, both of them must be
111        importable.
112        """
113        pkg_A = namespaces.build_namespace_package(tmpdir, 'myns.pkgA')
114        pkg_B = namespaces.build_namespace_package(tmpdir, 'myns.pkgB')
115        target = tmpdir / 'packages'
116        # use pip to install to the target directory
117        install_cmd = [
118            sys.executable,
119            '-m',
120            'pip.__main__',
121            'install',
122            str(pkg_A),
123            '-t', str(target),
124        ]
125        subprocess.check_call(install_cmd)
126        namespaces.make_site_dir(target)
127
128        # ensure that all packages import and pkg_resources imports
129        pkg_resources_imp = [
130            sys.executable,
131            '-c', 'import pkg_resources; import myns.pkgA; import myns.pkgB',
132        ]
133        with test.test.paths_on_pythonpath([str(target)]):
134            subprocess.check_call(pkg_resources_imp, cwd=str(pkg_B))
135