We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
allow users to pick if package should be installed with pip
## Details

There is a system-wide config for whether "install this package" should mean `pip install .` or `setup.py install`. It would be useful for packages to be able to specify, at least in the `setup.py install` case that's on the official deployment, that `pip install .` should be used for their package.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `readthedocs/doc_builder/config.py`
Content:
```
1 from readthedocs_build.config import (ConfigError, BuildConfig, InvalidConfig,
2                                       load as load_config)
3 
4 
5 from readthedocs.projects.exceptions import ProjectImportError
6 
7 
8 class ConfigWrapper(object):
9 
10     """
11     A config object that wraps the Project & YAML based configs.
12 
13     Gives precidence to YAML, falling back to project if it isn't defined.
14 
15     We only currently implement a subset of the existing YAML config.
16     This should be the canonical source for our usage of the YAML files,
17     never accessing the config object directly.
18 
19     """
20 
21     def __init__(self, version, yaml_config):
22         self._version = version
23         self._project = version.project
24         self._yaml_config = yaml_config
25 
26     @property
27     def install_project(self):
28         if 'setup_py_install' in self._yaml_config.get('python', {}):
29             return self._yaml_config['python']['setup_py_install']
30         else:
31             return self._project.install_project
32 
33     @property
34     def python_interpreter(self):
35         if 'version' in self._yaml_config.get('python', {}):
36             ver = self._yaml_config['python']['version']
37             if str(ver).startswith('2'):
38                 return 'python'
39             else:
40                 return 'python3'
41         else:
42             return self._project.python_interpreter
43 
44     @property
45     def python_version(self):
46         if 'version' in self._yaml_config.get('python', {}):
47             ver = self._yaml_config['python']['version']
48             return ver
49         else:
50             if self._project.python_interpreter == 'python':
51                 return 2
52             else:
53                 return 3
54 
55     @property
56     def use_system_site_packages(self):
57         if 'use_system_site_packages' in self._yaml_config.get('python', {}):
58             return self._yaml_config['python']['use_system_site_packages']
59         else:
60             return self._project.use_system_packages
61 
62     @property
63     def use_conda(self):
64         if 'conda' in self._yaml_config:
65             return True
66         else:
67             return False
68 
69     @property
70     def conda_file(self):
71         if 'file' in self._yaml_config.get('conda', {}):
72             return self._yaml_config['conda']['file']
73         else:
74             return None
75 
76     @property
77     def requirements_file(self):
78         if 'requirements_file' in self._yaml_config:
79             return self._yaml_config['requirements_file']
80         else:
81             return self._project.requirements_file
82 
83     @property
84     def formats(self):
85         if 'formats' in self._yaml_config:
86             return self._yaml_config['formats']
87         else:
88             formats = ['htmlzip']
89             if self._project.enable_epub_build:
90                 formats += ['epub']
91             if self._project.enable_pdf_build:
92                 formats += ['pdf']
93             return formats
94 
95     # Not implemented until we figure out how to keep in sync with the webs.
96     # Probably needs to be version-specific as well, not project.
97     # @property
98     # def documentation_type(self):
99     #     if 'type' in self._yaml_config:
100     #         return self._yaml_config['type']
101     #     else:
102     #         return self._project.documentation_type
103 
104 
105 def load_yaml_config(version):
106     """
107     Load a configuration from `readthedocs.yml` file.
108 
109     This uses the configuration logic from `readthedocs-build`,
110     which will keep parsing consistent between projects.
111     """
112 
113     checkout_path = version.project.checkout_path(version.slug)
114     try:
115         config = load_config(
116             path=checkout_path,
117             env_config={
118                 'output_base': '',
119                 'type': 'sphinx',
120                 'name': version.slug,
121             },
122         )[0]
123     except InvalidConfig:  # This is a subclass of ConfigError, so has to come first
124         raise
125     except ConfigError:
126         config = BuildConfig(
127             env_config={},
128             raw_config={},
129             source_file='empty',
130             source_position=0,
131         )
132     return ConfigWrapper(version=version, yaml_config=config)
133
```

Path: `readthedocs/doc_builder/python_environments.py`
Content:
```
1 import logging
2 import os
3 import shutil
4 
5 from django.conf import settings
6 
7 from readthedocs.doc_builder.config import ConfigWrapper
8 from readthedocs.doc_builder.loader import get_builder_class
9 from readthedocs.projects.constants import LOG_TEMPLATE
10 
11 log = logging.getLogger(__name__)
12 
13 
14 class PythonEnvironment(object):
15 
16     def __init__(self, version, build_env, config=None):
17         self.version = version
18         self.project = version.project
19         self.build_env = build_env
20         if config:
21             self.config = config
22         else:
23             self.config = ConfigWrapper(version=version, yaml_config={})
24         # Compute here, since it's used a lot
25         self.checkout_path = self.project.checkout_path(self.version.slug)
26 
27     def _log(self, msg):
28         log.info(LOG_TEMPLATE
29                  .format(project=self.project.slug,
30                          version=self.version.slug,
31                          msg=msg))
32 
33     def delete_existing_build_dir(self):
34 
35         # Handle deleting old build dir
36         build_dir = os.path.join(
37             self.venv_path(),
38             'build')
39         if os.path.exists(build_dir):
40             self._log('Removing existing build directory')
41             shutil.rmtree(build_dir)
42 
43     def install_package(self):
44         setup_path = os.path.join(self.checkout_path, 'setup.py')
45         if os.path.isfile(setup_path) and self.config.install_project:
46             if getattr(settings, 'USE_PIP_INSTALL', False):
47                 self.build_env.run(
48                     'python',
49                     self.venv_bin(filename='pip'),
50                     'install',
51                     '--ignore-installed',
52                     '--cache-dir',
53                     self.project.pip_cache_path,
54                     '.',
55                     cwd=self.checkout_path,
56                     bin_path=self.venv_bin()
57                 )
58             else:
59                 self.build_env.run(
60                     'python',
61                     'setup.py',
62                     'install',
63                     '--force',
64                     cwd=self.checkout_path,
65                     bin_path=self.venv_bin()
66                 )
67 
68     def venv_bin(self, filename=None):
69         """Return path to the virtualenv bin path, or a specific binary
70 
71         :param filename: If specified, add this filename to the path return
72         :returns: Path to virtualenv bin or filename in virtualenv bin
73         """
74         parts = [self.venv_path(), 'bin']
75         if filename is not None:
76             parts.append(filename)
77         return os.path.join(*parts)
78 
79 
80 class Virtualenv(PythonEnvironment):
81 
82     def venv_path(self):
83         return os.path.join(self.project.doc_path, 'envs', self.version.slug)
84 
85     def setup_base(self):
86         site_packages = '--no-site-packages'
87         if self.config.use_system_site_packages:
88             site_packages = '--system-site-packages'
89         env_path = self.venv_path()
90         self.build_env.run(
91             self.config.python_interpreter,
92             '-mvirtualenv',
93             site_packages,
94             env_path,
95             bin_path=None,  # Don't use virtualenv bin that doesn't exist yet
96         )
97 
98     def install_core_requirements(self):
99         requirements = [
100             'sphinx==1.3.5',
101             'Pygments==2.0.2',
102             'setuptools==20.1.1',
103             'docutils==0.12',
104             'mkdocs==0.15.0',
105             'mock==1.0.1',
106             'pillow==2.6.1',
107             ('git+https://github.com/rtfd/readthedocs-sphinx-ext.git'
108              '@0.6-alpha#egg=readthedocs-sphinx-ext'),
109             'sphinx-rtd-theme==0.1.9',
110             'alabaster>=0.7,<0.8,!=0.7.5',
111             'commonmark==0.5.4',
112             'recommonmark==0.1.1',
113         ]
114 
115         cmd = [
116             'python',
117             self.venv_bin(filename='pip'),
118             'install',
119             '--use-wheel',
120             '-U',
121             '--cache-dir',
122             self.project.pip_cache_path,
123         ]
124         if self.config.use_system_site_packages:
125             # Other code expects sphinx-build to be installed inside the
126             # virtualenv.  Using the -I option makes sure it gets installed
127             # even if it is already installed system-wide (and
128             # --system-site-packages is used)
129             cmd.append('-I')
130         cmd.extend(requirements)
131         self.build_env.run(
132             *cmd,
133             bin_path=self.venv_bin()
134         )
135 
136     def install_user_requirements(self):
137         requirements_file_path = self.config.requirements_file
138         if not requirements_file_path:
139             builder_class = get_builder_class(self.project.documentation_type)
140             docs_dir = (builder_class(build_env=self.build_env, python_env=self)
141                         .docs_dir())
142             for path in [docs_dir, '']:
143                 for req_file in ['pip_requirements.txt', 'requirements.txt']:
144                     test_path = os.path.join(self.checkout_path, path, req_file)
145                     if os.path.exists(test_path):
146                         requirements_file_path = test_path
147                         break
148 
149         if requirements_file_path:
150             self.build_env.run(
151                 'python',
152                 self.venv_bin(filename='pip'),
153                 'install',
154                 '--exists-action=w',
155                 '--cache-dir',
156                 self.project.pip_cache_path,
157                 '-r{0}'.format(requirements_file_path),
158                 cwd=self.checkout_path,
159                 bin_path=self.venv_bin()
160             )
161 
162 
163 class Conda(PythonEnvironment):
164 
165     def venv_path(self):
166         return os.path.join(self.project.doc_path, 'conda', self.version.slug)
167 
168     def setup_base(self):
169         conda_env_path = os.path.join(self.project.doc_path, 'conda')
170         version_path = os.path.join(conda_env_path, self.version.slug)
171 
172         if os.path.exists(version_path):
173             # Re-create conda directory each time to keep fresh state
174             self._log('Removing existing conda directory')
175             shutil.rmtree(version_path)
176         self.build_env.run(
177             'conda',
178             'env',
179             'create',
180             '--name',
181             self.version.slug,
182             '--file',
183             self.config.conda_file,
184             bin_path=None,  # Don't use conda bin that doesn't exist yet
185         )
186 
187     def install_core_requirements(self):
188 
189         # Use conda for requirements it packages
190         requirements = [
191             'sphinx==1.3.5',
192             'Pygments==2.0.2',
193             'docutils==0.12',
194             'mock',
195             'pillow==3.0.0',
196             'sphinx_rtd_theme==0.1.7',
197             'alabaster>=0.7,<0.8,!=0.7.5',
198         ]
199 
200         cmd = [
201             'conda',
202             'install',
203             '--yes',
204             '--name',
205             self.version.slug,
206         ]
207         cmd.extend(requirements)
208         self.build_env.run(
209             *cmd
210         )
211 
212         # Install pip-only things.
213         pip_requirements = [
214             'mkdocs==0.15.0',
215             ('git+https://github.com/rtfd/readthedocs-sphinx-ext.git'
216              '@0.6-alpha#egg=readthedocs-sphinx-ext'),
217             'commonmark==0.5.4',
218             'recommonmark==0.1.1',
219         ]
220 
221         pip_cmd = [
222             'python',
223             self.venv_bin(filename='pip'),
224             'install',
225             '-U',
226             '--cache-dir',
227             self.project.pip_cache_path,
228         ]
229         pip_cmd.extend(pip_requirements)
230         self.build_env.run(
231             *pip_cmd,
232             bin_path=self.venv_bin()
233         )
234 
235     def install_user_requirements(self):
236         self.build_env.run(
237             'conda',
238             'env',
239             'update',
240             '--name',
241             self.version.slug,
242             '--file',
243             self.config.conda_file,
244         )
245
```
--- 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/readthedocs/doc_builder/config.py b/readthedocs/doc_builder/config.py
--- a/readthedocs/doc_builder/config.py
+++ b/readthedocs/doc_builder/config.py
@@ -23,8 +23,17 @@
         self._project = version.project
         self._yaml_config = yaml_config
 
+    @property
+    def pip_install(self):
+        if 'pip_install' in self._yaml_config.get('python', {}):
+            return self._yaml_config['python']['pip_install']
+        else:
+            return False
+
     @property
     def install_project(self):
+        if self.pip_install:
+            return True
         if 'setup_py_install' in self._yaml_config.get('python', {}):
             return self._yaml_config['python']['setup_py_install']
         else:
diff --git a/readthedocs/doc_builder/python_environments.py b/readthedocs/doc_builder/python_environments.py
--- a/readthedocs/doc_builder/python_environments.py
+++ b/readthedocs/doc_builder/python_environments.py
@@ -43,7 +43,7 @@
     def install_package(self):
         setup_path = os.path.join(self.checkout_path, 'setup.py')
         if os.path.isfile(setup_path) and self.config.install_project:
-            if getattr(settings, 'USE_PIP_INSTALL', False):
+            if self.config.pip_install or getattr(settings, 'USE_PIP_INSTALL', False):
                 self.build_env.run(
                     'python',
                     self.venv_bin(filename='pip'),

{"golden_diff": "diff --git a/readthedocs/doc_builder/config.py b/readthedocs/doc_builder/config.py\n--- a/readthedocs/doc_builder/config.py\n+++ b/readthedocs/doc_builder/config.py\n@@ -23,8 +23,17 @@\n         self._project = version.project\n         self._yaml_config = yaml_config\n \n+    @property\n+    def pip_install(self):\n+        if 'pip_install' in self._yaml_config.get('python', {}):\n+            return self._yaml_config['python']['pip_install']\n+        else:\n+            return False\n+\n     @property\n     def install_project(self):\n+        if self.pip_install:\n+            return True\n         if 'setup_py_install' in self._yaml_config.get('python', {}):\n             return self._yaml_config['python']['setup_py_install']\n         else:\ndiff --git a/readthedocs/doc_builder/python_environments.py b/readthedocs/doc_builder/python_environments.py\n--- a/readthedocs/doc_builder/python_environments.py\n+++ b/readthedocs/doc_builder/python_environments.py\n@@ -43,7 +43,7 @@\n     def install_package(self):\n         setup_path = os.path.join(self.checkout_path, 'setup.py')\n         if os.path.isfile(setup_path) and self.config.install_project:\n-            if getattr(settings, 'USE_PIP_INSTALL', False):\n+            if self.config.pip_install or getattr(settings, 'USE_PIP_INSTALL', False):\n                 self.build_env.run(\n                     'python',\n                     self.venv_bin(filename='pip'),\n", "issue": "allow users to pick if package should be installed with pip\n## Details\n\nThere is a system-wide config for whether \"install this package\" should mean `pip install .` or `setup.py install`. It would be useful for packages to be able to specify, at least in the `setup.py install` case that's on the official deployment, that `pip install .` should be used for their package.\n\n", "before_files": [{"content": "from readthedocs_build.config import (ConfigError, BuildConfig, InvalidConfig,\n                                      load as load_config)\n\n\nfrom readthedocs.projects.exceptions import ProjectImportError\n\n\nclass ConfigWrapper(object):\n\n    \"\"\"\n    A config object that wraps the Project & YAML based configs.\n\n    Gives precidence to YAML, falling back to project if it isn't defined.\n\n    We only currently implement a subset of the existing YAML config.\n    This should be the canonical source for our usage of the YAML files,\n    never accessing the config object directly.\n\n    \"\"\"\n\n    def __init__(self, version, yaml_config):\n        self._version = version\n        self._project = version.project\n        self._yaml_config = yaml_config\n\n    @property\n    def install_project(self):\n        if 'setup_py_install' in self._yaml_config.get('python', {}):\n            return self._yaml_config['python']['setup_py_install']\n        else:\n            return self._project.install_project\n\n    @property\n    def python_interpreter(self):\n        if 'version' in self._yaml_config.get('python', {}):\n            ver = self._yaml_config['python']['version']\n            if str(ver).startswith('2'):\n                return 'python'\n            else:\n                return 'python3'\n        else:\n            return self._project.python_interpreter\n\n    @property\n    def python_version(self):\n        if 'version' in self._yaml_config.get('python', {}):\n            ver = self._yaml_config['python']['version']\n            return ver\n        else:\n            if self._project.python_interpreter == 'python':\n                return 2\n            else:\n                return 3\n\n    @property\n    def use_system_site_packages(self):\n        if 'use_system_site_packages' in self._yaml_config.get('python', {}):\n            return self._yaml_config['python']['use_system_site_packages']\n        else:\n            return self._project.use_system_packages\n\n    @property\n    def use_conda(self):\n        if 'conda' in self._yaml_config:\n            return True\n        else:\n            return False\n\n    @property\n    def conda_file(self):\n        if 'file' in self._yaml_config.get('conda', {}):\n            return self._yaml_config['conda']['file']\n        else:\n            return None\n\n    @property\n    def requirements_file(self):\n        if 'requirements_file' in self._yaml_config:\n            return self._yaml_config['requirements_file']\n        else:\n            return self._project.requirements_file\n\n    @property\n    def formats(self):\n        if 'formats' in self._yaml_config:\n            return self._yaml_config['formats']\n        else:\n            formats = ['htmlzip']\n            if self._project.enable_epub_build:\n                formats += ['epub']\n            if self._project.enable_pdf_build:\n                formats += ['pdf']\n            return formats\n\n    # Not implemented until we figure out how to keep in sync with the webs.\n    # Probably needs to be version-specific as well, not project.\n    # @property\n    # def documentation_type(self):\n    #     if 'type' in self._yaml_config:\n    #         return self._yaml_config['type']\n    #     else:\n    #         return self._project.documentation_type\n\n\ndef load_yaml_config(version):\n    \"\"\"\n    Load a configuration from `readthedocs.yml` file.\n\n    This uses the configuration logic from `readthedocs-build`,\n    which will keep parsing consistent between projects.\n    \"\"\"\n\n    checkout_path = version.project.checkout_path(version.slug)\n    try:\n        config = load_config(\n            path=checkout_path,\n            env_config={\n                'output_base': '',\n                'type': 'sphinx',\n                'name': version.slug,\n            },\n        )[0]\n    except InvalidConfig:  # This is a subclass of ConfigError, so has to come first\n        raise\n    except ConfigError:\n        config = BuildConfig(\n            env_config={},\n            raw_config={},\n            source_file='empty',\n            source_position=0,\n        )\n    return ConfigWrapper(version=version, yaml_config=config)\n", "path": "readthedocs/doc_builder/config.py"}, {"content": "import logging\nimport os\nimport shutil\n\nfrom django.conf import settings\n\nfrom readthedocs.doc_builder.config import ConfigWrapper\nfrom readthedocs.doc_builder.loader import get_builder_class\nfrom readthedocs.projects.constants import LOG_TEMPLATE\n\nlog = logging.getLogger(__name__)\n\n\nclass PythonEnvironment(object):\n\n    def __init__(self, version, build_env, config=None):\n        self.version = version\n        self.project = version.project\n        self.build_env = build_env\n        if config:\n            self.config = config\n        else:\n            self.config = ConfigWrapper(version=version, yaml_config={})\n        # Compute here, since it's used a lot\n        self.checkout_path = self.project.checkout_path(self.version.slug)\n\n    def _log(self, msg):\n        log.info(LOG_TEMPLATE\n                 .format(project=self.project.slug,\n                         version=self.version.slug,\n                         msg=msg))\n\n    def delete_existing_build_dir(self):\n\n        # Handle deleting old build dir\n        build_dir = os.path.join(\n            self.venv_path(),\n            'build')\n        if os.path.exists(build_dir):\n            self._log('Removing existing build directory')\n            shutil.rmtree(build_dir)\n\n    def install_package(self):\n        setup_path = os.path.join(self.checkout_path, 'setup.py')\n        if os.path.isfile(setup_path) and self.config.install_project:\n            if getattr(settings, 'USE_PIP_INSTALL', False):\n                self.build_env.run(\n                    'python',\n                    self.venv_bin(filename='pip'),\n                    'install',\n                    '--ignore-installed',\n                    '--cache-dir',\n                    self.project.pip_cache_path,\n                    '.',\n                    cwd=self.checkout_path,\n                    bin_path=self.venv_bin()\n                )\n            else:\n                self.build_env.run(\n                    'python',\n                    'setup.py',\n                    'install',\n                    '--force',\n                    cwd=self.checkout_path,\n                    bin_path=self.venv_bin()\n                )\n\n    def venv_bin(self, filename=None):\n        \"\"\"Return path to the virtualenv bin path, or a specific binary\n\n        :param filename: If specified, add this filename to the path return\n        :returns: Path to virtualenv bin or filename in virtualenv bin\n        \"\"\"\n        parts = [self.venv_path(), 'bin']\n        if filename is not None:\n            parts.append(filename)\n        return os.path.join(*parts)\n\n\nclass Virtualenv(PythonEnvironment):\n\n    def venv_path(self):\n        return os.path.join(self.project.doc_path, 'envs', self.version.slug)\n\n    def setup_base(self):\n        site_packages = '--no-site-packages'\n        if self.config.use_system_site_packages:\n            site_packages = '--system-site-packages'\n        env_path = self.venv_path()\n        self.build_env.run(\n            self.config.python_interpreter,\n            '-mvirtualenv',\n            site_packages,\n            env_path,\n            bin_path=None,  # Don't use virtualenv bin that doesn't exist yet\n        )\n\n    def install_core_requirements(self):\n        requirements = [\n            'sphinx==1.3.5',\n            'Pygments==2.0.2',\n            'setuptools==20.1.1',\n            'docutils==0.12',\n            'mkdocs==0.15.0',\n            'mock==1.0.1',\n            'pillow==2.6.1',\n            ('git+https://github.com/rtfd/readthedocs-sphinx-ext.git'\n             '@0.6-alpha#egg=readthedocs-sphinx-ext'),\n            'sphinx-rtd-theme==0.1.9',\n            'alabaster>=0.7,<0.8,!=0.7.5',\n            'commonmark==0.5.4',\n            'recommonmark==0.1.1',\n        ]\n\n        cmd = [\n            'python',\n            self.venv_bin(filename='pip'),\n            'install',\n            '--use-wheel',\n            '-U',\n            '--cache-dir',\n            self.project.pip_cache_path,\n        ]\n        if self.config.use_system_site_packages:\n            # Other code expects sphinx-build to be installed inside the\n            # virtualenv.  Using the -I option makes sure it gets installed\n            # even if it is already installed system-wide (and\n            # --system-site-packages is used)\n            cmd.append('-I')\n        cmd.extend(requirements)\n        self.build_env.run(\n            *cmd,\n            bin_path=self.venv_bin()\n        )\n\n    def install_user_requirements(self):\n        requirements_file_path = self.config.requirements_file\n        if not requirements_file_path:\n            builder_class = get_builder_class(self.project.documentation_type)\n            docs_dir = (builder_class(build_env=self.build_env, python_env=self)\n                        .docs_dir())\n            for path in [docs_dir, '']:\n                for req_file in ['pip_requirements.txt', 'requirements.txt']:\n                    test_path = os.path.join(self.checkout_path, path, req_file)\n                    if os.path.exists(test_path):\n                        requirements_file_path = test_path\n                        break\n\n        if requirements_file_path:\n            self.build_env.run(\n                'python',\n                self.venv_bin(filename='pip'),\n                'install',\n                '--exists-action=w',\n                '--cache-dir',\n                self.project.pip_cache_path,\n                '-r{0}'.format(requirements_file_path),\n                cwd=self.checkout_path,\n                bin_path=self.venv_bin()\n            )\n\n\nclass Conda(PythonEnvironment):\n\n    def venv_path(self):\n        return os.path.join(self.project.doc_path, 'conda', self.version.slug)\n\n    def setup_base(self):\n        conda_env_path = os.path.join(self.project.doc_path, 'conda')\n        version_path = os.path.join(conda_env_path, self.version.slug)\n\n        if os.path.exists(version_path):\n            # Re-create conda directory each time to keep fresh state\n            self._log('Removing existing conda directory')\n            shutil.rmtree(version_path)\n        self.build_env.run(\n            'conda',\n            'env',\n            'create',\n            '--name',\n            self.version.slug,\n            '--file',\n            self.config.conda_file,\n            bin_path=None,  # Don't use conda bin that doesn't exist yet\n        )\n\n    def install_core_requirements(self):\n\n        # Use conda for requirements it packages\n        requirements = [\n            'sphinx==1.3.5',\n            'Pygments==2.0.2',\n            'docutils==0.12',\n            'mock',\n            'pillow==3.0.0',\n            'sphinx_rtd_theme==0.1.7',\n            'alabaster>=0.7,<0.8,!=0.7.5',\n        ]\n\n        cmd = [\n            'conda',\n            'install',\n            '--yes',\n            '--name',\n            self.version.slug,\n        ]\n        cmd.extend(requirements)\n        self.build_env.run(\n            *cmd\n        )\n\n        # Install pip-only things.\n        pip_requirements = [\n            'mkdocs==0.15.0',\n            ('git+https://github.com/rtfd/readthedocs-sphinx-ext.git'\n             '@0.6-alpha#egg=readthedocs-sphinx-ext'),\n            'commonmark==0.5.4',\n            'recommonmark==0.1.1',\n        ]\n\n        pip_cmd = [\n            'python',\n            self.venv_bin(filename='pip'),\n            'install',\n            '-U',\n            '--cache-dir',\n            self.project.pip_cache_path,\n        ]\n        pip_cmd.extend(pip_requirements)\n        self.build_env.run(\n            *pip_cmd,\n            bin_path=self.venv_bin()\n        )\n\n    def install_user_requirements(self):\n        self.build_env.run(\n            'conda',\n            'env',\n            'update',\n            '--name',\n            self.version.slug,\n            '--file',\n            self.config.conda_file,\n        )\n", "path": "readthedocs/doc_builder/python_environments.py"}], "after_files": [{"content": "from readthedocs_build.config import (ConfigError, BuildConfig, InvalidConfig,\n                                      load as load_config)\n\n\nfrom readthedocs.projects.exceptions import ProjectImportError\n\n\nclass ConfigWrapper(object):\n\n    \"\"\"\n    A config object that wraps the Project & YAML based configs.\n\n    Gives precidence to YAML, falling back to project if it isn't defined.\n\n    We only currently implement a subset of the existing YAML config.\n    This should be the canonical source for our usage of the YAML files,\n    never accessing the config object directly.\n\n    \"\"\"\n\n    def __init__(self, version, yaml_config):\n        self._version = version\n        self._project = version.project\n        self._yaml_config = yaml_config\n\n    @property\n    def pip_install(self):\n        if 'pip_install' in self._yaml_config.get('python', {}):\n            return self._yaml_config['python']['pip_install']\n        else:\n            return False\n\n    @property\n    def install_project(self):\n        if self.pip_install:\n            return True\n        if 'setup_py_install' in self._yaml_config.get('python', {}):\n            return self._yaml_config['python']['setup_py_install']\n        else:\n            return self._project.install_project\n\n    @property\n    def python_interpreter(self):\n        if 'version' in self._yaml_config.get('python', {}):\n            ver = self._yaml_config['python']['version']\n            if str(ver).startswith('2'):\n                return 'python'\n            else:\n                return 'python3'\n        else:\n            return self._project.python_interpreter\n\n    @property\n    def python_version(self):\n        if 'version' in self._yaml_config.get('python', {}):\n            ver = self._yaml_config['python']['version']\n            return ver\n        else:\n            if self._project.python_interpreter == 'python':\n                return 2\n            else:\n                return 3\n\n    @property\n    def use_system_site_packages(self):\n        if 'use_system_site_packages' in self._yaml_config.get('python', {}):\n            return self._yaml_config['python']['use_system_site_packages']\n        else:\n            return self._project.use_system_packages\n\n    @property\n    def use_conda(self):\n        if 'conda' in self._yaml_config:\n            return True\n        else:\n            return False\n\n    @property\n    def conda_file(self):\n        if 'file' in self._yaml_config.get('conda', {}):\n            return self._yaml_config['conda']['file']\n        else:\n            return None\n\n    @property\n    def requirements_file(self):\n        if 'requirements_file' in self._yaml_config:\n            return self._yaml_config['requirements_file']\n        else:\n            return self._project.requirements_file\n\n    @property\n    def formats(self):\n        if 'formats' in self._yaml_config:\n            return self._yaml_config['formats']\n        else:\n            formats = ['htmlzip']\n            if self._project.enable_epub_build:\n                formats += ['epub']\n            if self._project.enable_pdf_build:\n                formats += ['pdf']\n            return formats\n\n    # Not implemented until we figure out how to keep in sync with the webs.\n    # Probably needs to be version-specific as well, not project.\n    # @property\n    # def documentation_type(self):\n    #     if 'type' in self._yaml_config:\n    #         return self._yaml_config['type']\n    #     else:\n    #         return self._project.documentation_type\n\n\ndef load_yaml_config(version):\n    \"\"\"\n    Load a configuration from `readthedocs.yml` file.\n\n    This uses the configuration logic from `readthedocs-build`,\n    which will keep parsing consistent between projects.\n    \"\"\"\n\n    checkout_path = version.project.checkout_path(version.slug)\n    try:\n        config = load_config(\n            path=checkout_path,\n            env_config={\n                'output_base': '',\n                'type': 'sphinx',\n                'name': version.slug,\n            },\n        )[0]\n    except InvalidConfig:  # This is a subclass of ConfigError, so has to come first\n        raise\n    except ConfigError:\n        config = BuildConfig(\n            env_config={},\n            raw_config={},\n            source_file='empty',\n            source_position=0,\n        )\n    return ConfigWrapper(version=version, yaml_config=config)\n", "path": "readthedocs/doc_builder/config.py"}, {"content": "import logging\nimport os\nimport shutil\n\nfrom django.conf import settings\n\nfrom readthedocs.doc_builder.config import ConfigWrapper\nfrom readthedocs.doc_builder.loader import get_builder_class\nfrom readthedocs.projects.constants import LOG_TEMPLATE\n\nlog = logging.getLogger(__name__)\n\n\nclass PythonEnvironment(object):\n\n    def __init__(self, version, build_env, config=None):\n        self.version = version\n        self.project = version.project\n        self.build_env = build_env\n        if config:\n            self.config = config\n        else:\n            self.config = ConfigWrapper(version=version, yaml_config={})\n        # Compute here, since it's used a lot\n        self.checkout_path = self.project.checkout_path(self.version.slug)\n\n    def _log(self, msg):\n        log.info(LOG_TEMPLATE\n                 .format(project=self.project.slug,\n                         version=self.version.slug,\n                         msg=msg))\n\n    def delete_existing_build_dir(self):\n\n        # Handle deleting old build dir\n        build_dir = os.path.join(\n            self.venv_path(),\n            'build')\n        if os.path.exists(build_dir):\n            self._log('Removing existing build directory')\n            shutil.rmtree(build_dir)\n\n    def install_package(self):\n        setup_path = os.path.join(self.checkout_path, 'setup.py')\n        if os.path.isfile(setup_path) and self.config.install_project:\n            if self.config.pip_install or getattr(settings, 'USE_PIP_INSTALL', False):\n                self.build_env.run(\n                    'python',\n                    self.venv_bin(filename='pip'),\n                    'install',\n                    '--ignore-installed',\n                    '--cache-dir',\n                    self.project.pip_cache_path,\n                    '.',\n                    cwd=self.checkout_path,\n                    bin_path=self.venv_bin()\n                )\n            else:\n                self.build_env.run(\n                    'python',\n                    'setup.py',\n                    'install',\n                    '--force',\n                    cwd=self.checkout_path,\n                    bin_path=self.venv_bin()\n                )\n\n    def venv_bin(self, filename=None):\n        \"\"\"Return path to the virtualenv bin path, or a specific binary\n\n        :param filename: If specified, add this filename to the path return\n        :returns: Path to virtualenv bin or filename in virtualenv bin\n        \"\"\"\n        parts = [self.venv_path(), 'bin']\n        if filename is not None:\n            parts.append(filename)\n        return os.path.join(*parts)\n\n\nclass Virtualenv(PythonEnvironment):\n\n    def venv_path(self):\n        return os.path.join(self.project.doc_path, 'envs', self.version.slug)\n\n    def setup_base(self):\n        site_packages = '--no-site-packages'\n        if self.config.use_system_site_packages:\n            site_packages = '--system-site-packages'\n        env_path = self.venv_path()\n        self.build_env.run(\n            self.config.python_interpreter,\n            '-mvirtualenv',\n            site_packages,\n            env_path,\n            bin_path=None,  # Don't use virtualenv bin that doesn't exist yet\n        )\n\n    def install_core_requirements(self):\n        requirements = [\n            'sphinx==1.3.4',\n            'Pygments==2.0.2',\n            'setuptools==18.6.1',\n            'docutils==0.12',\n            'mkdocs==0.15.0',\n            'mock==1.0.1',\n            'pillow==2.6.1',\n            'readthedocs-sphinx-ext==0.5.4',\n            'sphinx-rtd-theme==0.1.9',\n            'alabaster>=0.7,<0.8,!=0.7.5',\n            'commonmark==0.5.4',\n            'recommonmark==0.1.1',\n        ]\n\n        cmd = [\n            'python',\n            self.venv_bin(filename='pip'),\n            'install',\n            '--use-wheel',\n            '-U',\n            '--cache-dir',\n            self.project.pip_cache_path,\n        ]\n        if self.config.use_system_site_packages:\n            # Other code expects sphinx-build to be installed inside the\n            # virtualenv.  Using the -I option makes sure it gets installed\n            # even if it is already installed system-wide (and\n            # --system-site-packages is used)\n            cmd.append('-I')\n        cmd.extend(requirements)\n        self.build_env.run(\n            *cmd,\n            bin_path=self.venv_bin()\n        )\n\n    def install_user_requirements(self):\n        requirements_file_path = self.config.requirements_file\n        if not requirements_file_path:\n            builder_class = get_builder_class(self.project.documentation_type)\n            docs_dir = (builder_class(build_env=self.build_env, python_env=self)\n                        .docs_dir())\n            for path in [docs_dir, '']:\n                for req_file in ['pip_requirements.txt', 'requirements.txt']:\n                    test_path = os.path.join(self.checkout_path, path, req_file)\n                    if os.path.exists(test_path):\n                        requirements_file_path = test_path\n                        break\n\n        if requirements_file_path:\n            self.build_env.run(\n                'python',\n                self.venv_bin(filename='pip'),\n                'install',\n                '--exists-action=w',\n                '--cache-dir',\n                self.project.pip_cache_path,\n                '-r{0}'.format(requirements_file_path),\n                cwd=self.checkout_path,\n                bin_path=self.venv_bin()\n            )\n\n\nclass Conda(PythonEnvironment):\n\n    def venv_path(self):\n        return os.path.join(self.project.doc_path, 'conda', self.version.slug)\n\n    def setup_base(self):\n        conda_env_path = os.path.join(self.project.doc_path, 'conda')\n        version_path = os.path.join(conda_env_path, self.version.slug)\n\n        if os.path.exists(version_path):\n            # Re-create conda directory each time to keep fresh state\n            self._log('Removing existing conda directory')\n            shutil.rmtree(version_path)\n        self.build_env.run(\n            'conda',\n            'env',\n            'create',\n            '--name',\n            self.version.slug,\n            '--file',\n            self.config.conda_file,\n            bin_path=None,  # Don't use conda bin that doesn't exist yet\n        )\n\n    def install_core_requirements(self):\n\n        # Use conda for requirements it packages\n        requirements = [\n            'sphinx==1.3.1',\n            'Pygments==2.0.2',\n            'docutils==0.12',\n            'mock',\n            'pillow==3.0.0',\n            'sphinx_rtd_theme==0.1.7',\n            'alabaster>=0.7,<0.8,!=0.7.5',\n        ]\n\n        cmd = [\n            'conda',\n            'install',\n            '--yes',\n            '--name',\n            self.version.slug,\n        ]\n        cmd.extend(requirements)\n        self.build_env.run(\n            *cmd\n        )\n\n        # Install pip-only things.\n        pip_requirements = [\n            'mkdocs==0.15.0',\n            'readthedocs-sphinx-ext==0.5.4',\n            'commonmark==0.5.4',\n            'recommonmark==0.1.1',\n        ]\n\n        pip_cmd = [\n            'python',\n            self.venv_bin(filename='pip'),\n            'install',\n            '-U',\n            '--cache-dir',\n            self.project.pip_cache_path,\n        ]\n        pip_cmd.extend(pip_requirements)\n        self.build_env.run(\n            *pip_cmd,\n            bin_path=self.venv_bin()\n        )\n\n    def install_user_requirements(self):\n        self.build_env.run(\n            'conda',\n            'env',\n            'update',\n            '--name',\n            self.version.slug,\n            '--file',\n            self.config.conda_file,\n        )\n", "path": "readthedocs/doc_builder/python_environments.py"}]}