We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
pip 19.0 fails to install packages that import to-be-installed package from CWD
**Environment**

* pip version: 19.0
* Python version: 3.6
* OS: MacOS

<!-- Feel free to add more information about your environment here -->

**Description**
When running pip install pyinstaller==3.4 with pip 19.0 we are getting an install error. ModuleNotFoundError: No module named 'PyInstaller'


**Expected behavior**
Expect pyinstall to be installed, as it is with pip 18.1

**How to Reproduce**
Using python3:
pip install pyinstaller=3.4

**Output**

```
pip install pyinstaller==3.4
Collecting pip
  Using cached https://files.pythonhosted.org/packages/60/64/73b729587b6b0d13e690a7c3acd2231ee561e8dd28a58ae1b0409a5a2b20/pip-19.0-py2.py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 9.0.3
    Uninstalling pip-9.0.3:
      Successfully uninstalled pip-9.0.3
Successfully installed pip-19.0
(BuildVEnv) jlaroche-mbp:TrackSense$ pip install pyinstaller
Collecting pyinstaller
  Using cached https://files.pythonhosted.org/packages/03/32/0e0de593f129bf1d1e77eed562496d154ef4460fd5cecfd78612ef39a0cc/PyInstaller-3.4.tar.gz
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  Complete output from command /Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/bin/python3 /Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/tmps3z6flnv:
  Traceback (most recent call last):
    File "/Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 207, in <module>
      main()
    File "/Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 197, in main
      json_out['return_val'] = hook(**hook_input['kwargs'])
    File "/Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 54, in get_requires_for_build_wheel
      return hook(config_settings)
    File "/private/var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/pip-build-env-lo_ir5_f/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 115, in get_requires_for_build_wheel
      return _get_build_requires(config_settings, requirements=['wheel'])
    File "/private/var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/pip-build-env-lo_ir5_f/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 101, in _get_build_requires
      _run_setup()
    File "/private/var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/pip-build-env-lo_ir5_f/overlay/lib/python3.6/site-packages/setuptools/build_meta.py", line 85, in _run_setup
      exec(compile(code, __file__, 'exec'), locals())
    File "setup.py", line 20, in <module>
      from PyInstaller import __version__ as version, HOMEPATH, PLATFORM
  ModuleNotFoundError: No module named 'PyInstaller'
```

----

Maintainer note on timeline: See https://github.com/pypa/pip/issues/6163#issuecomment-460563963

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/pip/_internal/pyproject.py`
Content:
```
1 from __future__ import absolute_import
2 
3 import io
4 import os
5 import sys
6 
7 from pip._vendor import pytoml, six
8 
9 from pip._internal.exceptions import InstallationError
10 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
11 
12 if MYPY_CHECK_RUNNING:
13     from typing import Any, Tuple, Optional, List  # noqa: F401
14 
15 
16 def _is_list_of_str(obj):
17     # type: (Any) -> bool
18     return (
19         isinstance(obj, list) and
20         all(isinstance(item, six.string_types) for item in obj)
21     )
22 
23 
24 def make_pyproject_path(setup_py_dir):
25     # type: (str) -> str
26     path = os.path.join(setup_py_dir, 'pyproject.toml')
27 
28     # Python2 __file__ should not be unicode
29     if six.PY2 and isinstance(path, six.text_type):
30         path = path.encode(sys.getfilesystemencoding())
31 
32     return path
33 
34 
35 def load_pyproject_toml(
36     use_pep517,  # type: Optional[bool]
37     pyproject_toml,  # type: str
38     setup_py,  # type: str
39     req_name  # type: str
40 ):
41     # type: (...) -> Optional[Tuple[List[str], str, List[str]]]
42     """Load the pyproject.toml file.
43 
44     Parameters:
45         use_pep517 - Has the user requested PEP 517 processing? None
46                      means the user hasn't explicitly specified.
47         pyproject_toml - Location of the project's pyproject.toml file
48         setup_py - Location of the project's setup.py file
49         req_name - The name of the requirement we're processing (for
50                    error reporting)
51 
52     Returns:
53         None if we should use the legacy code path, otherwise a tuple
54         (
55             requirements from pyproject.toml,
56             name of PEP 517 backend,
57             requirements we should check are installed after setting
58                 up the build environment
59         )
60     """
61     has_pyproject = os.path.isfile(pyproject_toml)
62     has_setup = os.path.isfile(setup_py)
63 
64     if has_pyproject:
65         with io.open(pyproject_toml, encoding="utf-8") as f:
66             pp_toml = pytoml.load(f)
67         build_system = pp_toml.get("build-system")
68     else:
69         build_system = None
70 
71     # The following cases must use PEP 517
72     # We check for use_pep517 being non-None and falsey because that means
73     # the user explicitly requested --no-use-pep517.  The value 0 as
74     # opposed to False can occur when the value is provided via an
75     # environment variable or config file option (due to the quirk of
76     # strtobool() returning an integer in pip's configuration code).
77     if has_pyproject and not has_setup:
78         if use_pep517 is not None and not use_pep517:
79             raise InstallationError(
80                 "Disabling PEP 517 processing is invalid: "
81                 "project does not have a setup.py"
82             )
83         use_pep517 = True
84     elif build_system and "build-backend" in build_system:
85         if use_pep517 is not None and not use_pep517:
86             raise InstallationError(
87                 "Disabling PEP 517 processing is invalid: "
88                 "project specifies a build backend of {} "
89                 "in pyproject.toml".format(
90                     build_system["build-backend"]
91                 )
92             )
93         use_pep517 = True
94 
95     # If we haven't worked out whether to use PEP 517 yet,
96     # and the user hasn't explicitly stated a preference,
97     # we do so if the project has a pyproject.toml file.
98     elif use_pep517 is None:
99         use_pep517 = has_pyproject
100 
101     # At this point, we know whether we're going to use PEP 517.
102     assert use_pep517 is not None
103 
104     # If we're using the legacy code path, there is nothing further
105     # for us to do here.
106     if not use_pep517:
107         return None
108 
109     if build_system is None:
110         # Either the user has a pyproject.toml with no build-system
111         # section, or the user has no pyproject.toml, but has opted in
112         # explicitly via --use-pep517.
113         # In the absence of any explicit backend specification, we
114         # assume the setuptools backend, and require wheel and a version
115         # of setuptools that supports that backend.
116         build_system = {
117             "requires": ["setuptools>=40.2.0", "wheel"],
118             "build-backend": "setuptools.build_meta",
119         }
120 
121     # If we're using PEP 517, we have build system information (either
122     # from pyproject.toml, or defaulted by the code above).
123     # Note that at this point, we do not know if the user has actually
124     # specified a backend, though.
125     assert build_system is not None
126 
127     # Ensure that the build-system section in pyproject.toml conforms
128     # to PEP 518.
129     error_template = (
130         "{package} has a pyproject.toml file that does not comply "
131         "with PEP 518: {reason}"
132     )
133 
134     # Specifying the build-system table but not the requires key is invalid
135     if "requires" not in build_system:
136         raise InstallationError(
137             error_template.format(package=req_name, reason=(
138                 "it has a 'build-system' table but not "
139                 "'build-system.requires' which is mandatory in the table"
140             ))
141         )
142 
143     # Error out if requires is not a list of strings
144     requires = build_system["requires"]
145     if not _is_list_of_str(requires):
146         raise InstallationError(error_template.format(
147             package=req_name,
148             reason="'build-system.requires' is not a list of strings.",
149         ))
150 
151     backend = build_system.get("build-backend")
152     check = []  # type: List[str]
153     if backend is None:
154         # If the user didn't specify a backend, we assume they want to use
155         # the setuptools backend. But we can't be sure they have included
156         # a version of setuptools which supplies the backend, or wheel
157         # (which is neede by the backend) in their requirements. So we
158         # make a note to check that those requirements are present once
159         # we have set up the environment.
160         # This is quite a lot of work to check for a very specific case. But
161         # the problem is, that case is potentially quite common - projects that
162         # adopted PEP 518 early for the ability to specify requirements to
163         # execute setup.py, but never considered needing to mention the build
164         # tools themselves. The original PEP 518 code had a similar check (but
165         # implemented in a different way).
166         backend = "setuptools.build_meta"
167         check = ["setuptools>=40.2.0", "wheel"]
168 
169     return (requires, backend, check)
170
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/pip/_internal/pyproject.py b/src/pip/_internal/pyproject.py
--- a/src/pip/_internal/pyproject.py
+++ b/src/pip/_internal/pyproject.py
@@ -111,11 +111,13 @@
         # section, or the user has no pyproject.toml, but has opted in
         # explicitly via --use-pep517.
         # In the absence of any explicit backend specification, we
-        # assume the setuptools backend, and require wheel and a version
-        # of setuptools that supports that backend.
+        # assume the setuptools backend that most closely emulates the
+        # traditional direct setup.py execution, and require wheel and
+        # a version of setuptools that supports that backend.
+
         build_system = {
-            "requires": ["setuptools>=40.2.0", "wheel"],
-            "build-backend": "setuptools.build_meta",
+            "requires": ["setuptools>=40.8.0", "wheel"],
+            "build-backend": "setuptools.build_meta:__legacy__",
         }
 
     # If we're using PEP 517, we have build system information (either
@@ -154,7 +156,7 @@
         # If the user didn't specify a backend, we assume they want to use
         # the setuptools backend. But we can't be sure they have included
         # a version of setuptools which supplies the backend, or wheel
-        # (which is neede by the backend) in their requirements. So we
+        # (which is needed by the backend) in their requirements. So we
         # make a note to check that those requirements are present once
         # we have set up the environment.
         # This is quite a lot of work to check for a very specific case. But
@@ -163,7 +165,7 @@
         # execute setup.py, but never considered needing to mention the build
         # tools themselves. The original PEP 518 code had a similar check (but
         # implemented in a different way).
-        backend = "setuptools.build_meta"
-        check = ["setuptools>=40.2.0", "wheel"]
+        backend = "setuptools.build_meta:__legacy__"
+        check = ["setuptools>=40.8.0", "wheel"]
 
     return (requires, backend, check)

{"golden_diff": "diff --git a/src/pip/_internal/pyproject.py b/src/pip/_internal/pyproject.py\n--- a/src/pip/_internal/pyproject.py\n+++ b/src/pip/_internal/pyproject.py\n@@ -111,11 +111,13 @@\n         # section, or the user has no pyproject.toml, but has opted in\n         # explicitly via --use-pep517.\n         # In the absence of any explicit backend specification, we\n-        # assume the setuptools backend, and require wheel and a version\n-        # of setuptools that supports that backend.\n+        # assume the setuptools backend that most closely emulates the\n+        # traditional direct setup.py execution, and require wheel and\n+        # a version of setuptools that supports that backend.\n+\n         build_system = {\n-            \"requires\": [\"setuptools>=40.2.0\", \"wheel\"],\n-            \"build-backend\": \"setuptools.build_meta\",\n+            \"requires\": [\"setuptools>=40.8.0\", \"wheel\"],\n+            \"build-backend\": \"setuptools.build_meta:__legacy__\",\n         }\n \n     # If we're using PEP 517, we have build system information (either\n@@ -154,7 +156,7 @@\n         # If the user didn't specify a backend, we assume they want to use\n         # the setuptools backend. But we can't be sure they have included\n         # a version of setuptools which supplies the backend, or wheel\n-        # (which is neede by the backend) in their requirements. So we\n+        # (which is needed by the backend) in their requirements. So we\n         # make a note to check that those requirements are present once\n         # we have set up the environment.\n         # This is quite a lot of work to check for a very specific case. But\n@@ -163,7 +165,7 @@\n         # execute setup.py, but never considered needing to mention the build\n         # tools themselves. The original PEP 518 code had a similar check (but\n         # implemented in a different way).\n-        backend = \"setuptools.build_meta\"\n-        check = [\"setuptools>=40.2.0\", \"wheel\"]\n+        backend = \"setuptools.build_meta:__legacy__\"\n+        check = [\"setuptools>=40.8.0\", \"wheel\"]\n \n     return (requires, backend, check)\n", "issue": "pip 19.0 fails to install packages that import to-be-installed package from CWD\n**Environment**\r\n\r\n* pip version: 19.0\r\n* Python version: 3.6\r\n* OS: MacOS\r\n\r\n<!-- Feel free to add more information about your environment here -->\r\n\r\n**Description**\r\nWhen running pip install pyinstaller==3.4 with pip 19.0 we are getting an install error. ModuleNotFoundError: No module named 'PyInstaller'\r\n\r\n\r\n**Expected behavior**\r\nExpect pyinstall to be installed, as it is with pip 18.1\r\n\r\n**How to Reproduce**\r\nUsing python3:\r\npip install pyinstaller=3.4\r\n\r\n**Output**\r\n\r\n```\r\npip install pyinstaller==3.4\r\nCollecting pip\r\n  Using cached https://files.pythonhosted.org/packages/60/64/73b729587b6b0d13e690a7c3acd2231ee561e8dd28a58ae1b0409a5a2b20/pip-19.0-py2.py3-none-any.whl\r\nInstalling collected packages: pip\r\n  Found existing installation: pip 9.0.3\r\n    Uninstalling pip-9.0.3:\r\n      Successfully uninstalled pip-9.0.3\r\nSuccessfully installed pip-19.0\r\n(BuildVEnv) jlaroche-mbp:TrackSense$ pip install pyinstaller\r\nCollecting pyinstaller\r\n  Using cached https://files.pythonhosted.org/packages/03/32/0e0de593f129bf1d1e77eed562496d154ef4460fd5cecfd78612ef39a0cc/PyInstaller-3.4.tar.gz\r\n  Installing build dependencies ... done\r\n  Getting requirements to build wheel ... error\r\n  Complete output from command /Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/bin/python3 /Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/tmps3z6flnv:\r\n  Traceback (most recent call last):\r\n    File \"/Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py\", line 207, in <module>\r\n      main()\r\n    File \"/Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py\", line 197, in main\r\n      json_out['return_val'] = hook(**hook_input['kwargs'])\r\n    File \"/Users/jlaroche/Dev/uapkg/packages/system/algo/BuildVEnv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py\", line 54, in get_requires_for_build_wheel\r\n      return hook(config_settings)\r\n    File \"/private/var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/pip-build-env-lo_ir5_f/overlay/lib/python3.6/site-packages/setuptools/build_meta.py\", line 115, in get_requires_for_build_wheel\r\n      return _get_build_requires(config_settings, requirements=['wheel'])\r\n    File \"/private/var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/pip-build-env-lo_ir5_f/overlay/lib/python3.6/site-packages/setuptools/build_meta.py\", line 101, in _get_build_requires\r\n      _run_setup()\r\n    File \"/private/var/folders/j6/7t8sg1vj4q97zhh9z5cdmxbm4rz935/T/pip-build-env-lo_ir5_f/overlay/lib/python3.6/site-packages/setuptools/build_meta.py\", line 85, in _run_setup\r\n      exec(compile(code, __file__, 'exec'), locals())\r\n    File \"setup.py\", line 20, in <module>\r\n      from PyInstaller import __version__ as version, HOMEPATH, PLATFORM\r\n  ModuleNotFoundError: No module named 'PyInstaller'\r\n```\r\n\r\n----\r\n\r\nMaintainer note on timeline: See https://github.com/pypa/pip/issues/6163#issuecomment-460563963\n", "before_files": [{"content": "from __future__ import absolute_import\n\nimport io\nimport os\nimport sys\n\nfrom pip._vendor import pytoml, six\n\nfrom pip._internal.exceptions import InstallationError\nfrom pip._internal.utils.typing import MYPY_CHECK_RUNNING\n\nif MYPY_CHECK_RUNNING:\n    from typing import Any, Tuple, Optional, List  # noqa: F401\n\n\ndef _is_list_of_str(obj):\n    # type: (Any) -> bool\n    return (\n        isinstance(obj, list) and\n        all(isinstance(item, six.string_types) for item in obj)\n    )\n\n\ndef make_pyproject_path(setup_py_dir):\n    # type: (str) -> str\n    path = os.path.join(setup_py_dir, 'pyproject.toml')\n\n    # Python2 __file__ should not be unicode\n    if six.PY2 and isinstance(path, six.text_type):\n        path = path.encode(sys.getfilesystemencoding())\n\n    return path\n\n\ndef load_pyproject_toml(\n    use_pep517,  # type: Optional[bool]\n    pyproject_toml,  # type: str\n    setup_py,  # type: str\n    req_name  # type: str\n):\n    # type: (...) -> Optional[Tuple[List[str], str, List[str]]]\n    \"\"\"Load the pyproject.toml file.\n\n    Parameters:\n        use_pep517 - Has the user requested PEP 517 processing? None\n                     means the user hasn't explicitly specified.\n        pyproject_toml - Location of the project's pyproject.toml file\n        setup_py - Location of the project's setup.py file\n        req_name - The name of the requirement we're processing (for\n                   error reporting)\n\n    Returns:\n        None if we should use the legacy code path, otherwise a tuple\n        (\n            requirements from pyproject.toml,\n            name of PEP 517 backend,\n            requirements we should check are installed after setting\n                up the build environment\n        )\n    \"\"\"\n    has_pyproject = os.path.isfile(pyproject_toml)\n    has_setup = os.path.isfile(setup_py)\n\n    if has_pyproject:\n        with io.open(pyproject_toml, encoding=\"utf-8\") as f:\n            pp_toml = pytoml.load(f)\n        build_system = pp_toml.get(\"build-system\")\n    else:\n        build_system = None\n\n    # The following cases must use PEP 517\n    # We check for use_pep517 being non-None and falsey because that means\n    # the user explicitly requested --no-use-pep517.  The value 0 as\n    # opposed to False can occur when the value is provided via an\n    # environment variable or config file option (due to the quirk of\n    # strtobool() returning an integer in pip's configuration code).\n    if has_pyproject and not has_setup:\n        if use_pep517 is not None and not use_pep517:\n            raise InstallationError(\n                \"Disabling PEP 517 processing is invalid: \"\n                \"project does not have a setup.py\"\n            )\n        use_pep517 = True\n    elif build_system and \"build-backend\" in build_system:\n        if use_pep517 is not None and not use_pep517:\n            raise InstallationError(\n                \"Disabling PEP 517 processing is invalid: \"\n                \"project specifies a build backend of {} \"\n                \"in pyproject.toml\".format(\n                    build_system[\"build-backend\"]\n                )\n            )\n        use_pep517 = True\n\n    # If we haven't worked out whether to use PEP 517 yet,\n    # and the user hasn't explicitly stated a preference,\n    # we do so if the project has a pyproject.toml file.\n    elif use_pep517 is None:\n        use_pep517 = has_pyproject\n\n    # At this point, we know whether we're going to use PEP 517.\n    assert use_pep517 is not None\n\n    # If we're using the legacy code path, there is nothing further\n    # for us to do here.\n    if not use_pep517:\n        return None\n\n    if build_system is None:\n        # Either the user has a pyproject.toml with no build-system\n        # section, or the user has no pyproject.toml, but has opted in\n        # explicitly via --use-pep517.\n        # In the absence of any explicit backend specification, we\n        # assume the setuptools backend, and require wheel and a version\n        # of setuptools that supports that backend.\n        build_system = {\n            \"requires\": [\"setuptools>=40.2.0\", \"wheel\"],\n            \"build-backend\": \"setuptools.build_meta\",\n        }\n\n    # If we're using PEP 517, we have build system information (either\n    # from pyproject.toml, or defaulted by the code above).\n    # Note that at this point, we do not know if the user has actually\n    # specified a backend, though.\n    assert build_system is not None\n\n    # Ensure that the build-system section in pyproject.toml conforms\n    # to PEP 518.\n    error_template = (\n        \"{package} has a pyproject.toml file that does not comply \"\n        \"with PEP 518: {reason}\"\n    )\n\n    # Specifying the build-system table but not the requires key is invalid\n    if \"requires\" not in build_system:\n        raise InstallationError(\n            error_template.format(package=req_name, reason=(\n                \"it has a 'build-system' table but not \"\n                \"'build-system.requires' which is mandatory in the table\"\n            ))\n        )\n\n    # Error out if requires is not a list of strings\n    requires = build_system[\"requires\"]\n    if not _is_list_of_str(requires):\n        raise InstallationError(error_template.format(\n            package=req_name,\n            reason=\"'build-system.requires' is not a list of strings.\",\n        ))\n\n    backend = build_system.get(\"build-backend\")\n    check = []  # type: List[str]\n    if backend is None:\n        # If the user didn't specify a backend, we assume they want to use\n        # the setuptools backend. But we can't be sure they have included\n        # a version of setuptools which supplies the backend, or wheel\n        # (which is neede by the backend) in their requirements. So we\n        # make a note to check that those requirements are present once\n        # we have set up the environment.\n        # This is quite a lot of work to check for a very specific case. But\n        # the problem is, that case is potentially quite common - projects that\n        # adopted PEP 518 early for the ability to specify requirements to\n        # execute setup.py, but never considered needing to mention the build\n        # tools themselves. The original PEP 518 code had a similar check (but\n        # implemented in a different way).\n        backend = \"setuptools.build_meta\"\n        check = [\"setuptools>=40.2.0\", \"wheel\"]\n\n    return (requires, backend, check)\n", "path": "src/pip/_internal/pyproject.py"}], "after_files": [{"content": "from __future__ import absolute_import\n\nimport io\nimport os\nimport sys\n\nfrom pip._vendor import pytoml, six\n\nfrom pip._internal.exceptions import InstallationError\nfrom pip._internal.utils.typing import MYPY_CHECK_RUNNING\n\nif MYPY_CHECK_RUNNING:\n    from typing import Any, Tuple, Optional, List  # noqa: F401\n\n\ndef _is_list_of_str(obj):\n    # type: (Any) -> bool\n    return (\n        isinstance(obj, list) and\n        all(isinstance(item, six.string_types) for item in obj)\n    )\n\n\ndef make_pyproject_path(setup_py_dir):\n    # type: (str) -> str\n    path = os.path.join(setup_py_dir, 'pyproject.toml')\n\n    # Python2 __file__ should not be unicode\n    if six.PY2 and isinstance(path, six.text_type):\n        path = path.encode(sys.getfilesystemencoding())\n\n    return path\n\n\ndef load_pyproject_toml(\n    use_pep517,  # type: Optional[bool]\n    pyproject_toml,  # type: str\n    setup_py,  # type: str\n    req_name  # type: str\n):\n    # type: (...) -> Optional[Tuple[List[str], str, List[str]]]\n    \"\"\"Load the pyproject.toml file.\n\n    Parameters:\n        use_pep517 - Has the user requested PEP 517 processing? None\n                     means the user hasn't explicitly specified.\n        pyproject_toml - Location of the project's pyproject.toml file\n        setup_py - Location of the project's setup.py file\n        req_name - The name of the requirement we're processing (for\n                   error reporting)\n\n    Returns:\n        None if we should use the legacy code path, otherwise a tuple\n        (\n            requirements from pyproject.toml,\n            name of PEP 517 backend,\n            requirements we should check are installed after setting\n                up the build environment\n        )\n    \"\"\"\n    has_pyproject = os.path.isfile(pyproject_toml)\n    has_setup = os.path.isfile(setup_py)\n\n    if has_pyproject:\n        with io.open(pyproject_toml, encoding=\"utf-8\") as f:\n            pp_toml = pytoml.load(f)\n        build_system = pp_toml.get(\"build-system\")\n    else:\n        build_system = None\n\n    # The following cases must use PEP 517\n    # We check for use_pep517 being non-None and falsey because that means\n    # the user explicitly requested --no-use-pep517.  The value 0 as\n    # opposed to False can occur when the value is provided via an\n    # environment variable or config file option (due to the quirk of\n    # strtobool() returning an integer in pip's configuration code).\n    if has_pyproject and not has_setup:\n        if use_pep517 is not None and not use_pep517:\n            raise InstallationError(\n                \"Disabling PEP 517 processing is invalid: \"\n                \"project does not have a setup.py\"\n            )\n        use_pep517 = True\n    elif build_system and \"build-backend\" in build_system:\n        if use_pep517 is not None and not use_pep517:\n            raise InstallationError(\n                \"Disabling PEP 517 processing is invalid: \"\n                \"project specifies a build backend of {} \"\n                \"in pyproject.toml\".format(\n                    build_system[\"build-backend\"]\n                )\n            )\n        use_pep517 = True\n\n    # If we haven't worked out whether to use PEP 517 yet,\n    # and the user hasn't explicitly stated a preference,\n    # we do so if the project has a pyproject.toml file.\n    elif use_pep517 is None:\n        use_pep517 = has_pyproject\n\n    # At this point, we know whether we're going to use PEP 517.\n    assert use_pep517 is not None\n\n    # If we're using the legacy code path, there is nothing further\n    # for us to do here.\n    if not use_pep517:\n        return None\n\n    if build_system is None:\n        # Either the user has a pyproject.toml with no build-system\n        # section, or the user has no pyproject.toml, but has opted in\n        # explicitly via --use-pep517.\n        # In the absence of any explicit backend specification, we\n        # assume the setuptools backend that most closely emulates the\n        # traditional direct setup.py execution, and require wheel and\n        # a version of setuptools that supports that backend.\n\n        build_system = {\n            \"requires\": [\"setuptools>=40.8.0\", \"wheel\"],\n            \"build-backend\": \"setuptools.build_meta:__legacy__\",\n        }\n\n    # If we're using PEP 517, we have build system information (either\n    # from pyproject.toml, or defaulted by the code above).\n    # Note that at this point, we do not know if the user has actually\n    # specified a backend, though.\n    assert build_system is not None\n\n    # Ensure that the build-system section in pyproject.toml conforms\n    # to PEP 518.\n    error_template = (\n        \"{package} has a pyproject.toml file that does not comply \"\n        \"with PEP 518: {reason}\"\n    )\n\n    # Specifying the build-system table but not the requires key is invalid\n    if \"requires\" not in build_system:\n        raise InstallationError(\n            error_template.format(package=req_name, reason=(\n                \"it has a 'build-system' table but not \"\n                \"'build-system.requires' which is mandatory in the table\"\n            ))\n        )\n\n    # Error out if requires is not a list of strings\n    requires = build_system[\"requires\"]\n    if not _is_list_of_str(requires):\n        raise InstallationError(error_template.format(\n            package=req_name,\n            reason=\"'build-system.requires' is not a list of strings.\",\n        ))\n\n    backend = build_system.get(\"build-backend\")\n    check = []  # type: List[str]\n    if backend is None:\n        # If the user didn't specify a backend, we assume they want to use\n        # the setuptools backend. But we can't be sure they have included\n        # a version of setuptools which supplies the backend, or wheel\n        # (which is needed by the backend) in their requirements. So we\n        # make a note to check that those requirements are present once\n        # we have set up the environment.\n        # This is quite a lot of work to check for a very specific case. But\n        # the problem is, that case is potentially quite common - projects that\n        # adopted PEP 518 early for the ability to specify requirements to\n        # execute setup.py, but never considered needing to mention the build\n        # tools themselves. The original PEP 518 code had a similar check (but\n        # implemented in a different way).\n        backend = \"setuptools.build_meta:__legacy__\"\n        check = [\"setuptools>=40.8.0\", \"wheel\"]\n\n    return (requires, backend, check)\n", "path": "src/pip/_internal/pyproject.py"}]}