Repository: pypa/pip

Issue:
Namespace packages in pkg_resources style are not supported in build environment
**Environment**

* pip version: 18.0
* Python version: 2.7.15
* OS: Gentoo Linux

**Description**
When ``setup.py`` depends on ``pkg_resources`` namespace package, ``ImportError`` happens during ``pip wheel`` build process. This happens only with Python2 because Python3 supports native namespace packages and ``.pth`` files machinery is not required.

**Expected behavior**
Expected for package to be built successfully and expected ability to use namespace packages in ``setup.py``.

**How to Reproduce**
Consider package depending on package using ``pkg_resources`` namespace packages, for example let it be ``google.protobuf``.

``setup.py``:
```
from setuptools import find_packages, setup

# this is for example only, actually some setup helper is imported
import google.protobuf


setup(
    name='p',
    version='1.0',
    description='namespace packages not supported',
    packages=find_packages(),
)
```

``pyproject.toml``:
```
[build-system]
requires = [
    "setuptools",
    "wheel",
    "protobuf",
]
```

``p/__init__.py`` is empty.

**Output**

```
~/env/bin/pip wheel .
Processing /home/daa/tmp/2
  Installing build dependencies ... done
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-req-build-jy9sib/setup.py", line 4, in <module>
        import google.protobuf
    ImportError: No module named google.protobuf
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-req-build-jy9sib/
```

**My reasoning**
This happens because ``pkg_resources``-style namespace packages rely on ``*.pth`` files being executed on Python startup, but those files are looked for only in site directory. ``pip`` sets up build environment by installing packages to some prefix and setting ``PYTHONPATH``. So that directory is not considered as sitedir and thus pth-files from that location are not executed and namespace packages are not set up properly which leads to inability to import them.


Discussion:

Resolving patch:
diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py
--- a/src/pip/_internal/build_env.py
+++ b/src/pip/_internal/build_env.py
@@ -4,6 +4,7 @@
 import logging
 import os
 import sys
+import textwrap
 from distutils.sysconfig import get_python_lib
 from sysconfig import get_paths
 
@@ -61,6 +62,15 @@ def __enter__(self):
 
         os.environ['PYTHONNOUSERSITE'] = '1'
 
+        # Ensure .pth files are honored.
+        with open(os.path.join(purelib, 'sitecustomize.py'), 'w') as fp:
+            fp.write(textwrap.dedent(
+                '''
+                import site
+                site.addsitedir({!r})
+                '''
+            ).format(purelib))
+
         return self.path
 
     def __exit__(self, exc_type, exc_val, exc_tb):


Test patch:
diff --git a/tests/data/packages/simple_namespace-1.0-py2.py3-none-any.whl b/tests/data/packages/simple_namespace-1.0-py2.py3-none-any.whl
new file mode 100644
Binary files /dev/null and b/tests/data/packages/simple_namespace-1.0-py2.py3-none-any.whl differ
diff --git a/tests/data/src/pep518_with_namespace_package-1.0/pep518_with_namespace_package.py b/tests/data/src/pep518_with_namespace_package-1.0/pep518_with_namespace_package.py
new file mode 100644
diff --git a/tests/data/src/pep518_with_namespace_package-1.0/pyproject.toml b/tests/data/src/pep518_with_namespace_package-1.0/pyproject.toml
new file mode 100644
--- /dev/null
+++ b/tests/data/src/pep518_with_namespace_package-1.0/pyproject.toml
@@ -0,0 +1,6 @@
+[build-system]
+requires = [
+    "setuptools",
+    "wheel",
+    "simple_namespace",
+]
diff --git a/tests/data/src/pep518_with_namespace_package-1.0/setup.cfg b/tests/data/src/pep518_with_namespace_package-1.0/setup.cfg
new file mode 100644
--- /dev/null
+++ b/tests/data/src/pep518_with_namespace_package-1.0/setup.cfg
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal=1
diff --git a/tests/data/src/pep518_with_namespace_package-1.0/setup.py b/tests/data/src/pep518_with_namespace_package-1.0/setup.py
new file mode 100644
--- /dev/null
+++ b/tests/data/src/pep518_with_namespace_package-1.0/setup.py
@@ -0,0 +1,10 @@
+from setuptools import setup
+
+import simple_namespace.module
+
+
+setup(
+    name='pep518_with_namespace_package',
+    version='1.0',
+    py_modules=['pep518_with_namespace_package'],
+)
diff --git a/tests/data/src/simple_namespace/setup.cfg b/tests/data/src/simple_namespace/setup.cfg
new file mode 100644
--- /dev/null
+++ b/tests/data/src/simple_namespace/setup.cfg
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal=1
diff --git a/tests/data/src/simple_namespace/setup.py b/tests/data/src/simple_namespace/setup.py
new file mode 100644
--- /dev/null
+++ b/tests/data/src/simple_namespace/setup.py
@@ -0,0 +1,9 @@
+from setuptools import setup
+
+
+setup(
+    name='simple_namespace',
+    version='1.0',
+    namespace_packages=['simple_namespace'],
+    packages=['simple_namespace.module'],
+)
diff --git a/tests/data/src/simple_namespace/simple_namespace/__init__.py b/tests/data/src/simple_namespace/simple_namespace/__init__.py
new file mode 100644
diff --git a/tests/data/src/simple_namespace/simple_namespace/module/__init__.py b/tests/data/src/simple_namespace/simple_namespace/module/__init__.py
new file mode 100644
diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py
--- a/tests/functional/test_install.py
+++ b/tests/functional/test_install.py
@@ -100,6 +100,16 @@ def test_pep518_with_extra_and_markers(script, data, common_wheels):
     )
 
 
+def test_pep518_with_namespace_package(script, data, common_wheels):
+    script.pip(
+        'wheel', '--no-index',
+        '-f', common_wheels,
+        '-f', data.find_links,
+        data.src.join("pep518_with_namespace_package-1.0"),
+        use_module=True,
+    )
+
+
 @pytest.mark.timeout(60)
 @pytest.mark.parametrize('command', ('install', 'wheel'))
 @pytest.mark.parametrize('package', ('pep518_forkbomb',