mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Allow installing modules from a vcs subdirectory in non-editable mode
This commit is contained in:
parent
61f75c40ad
commit
1d759b3afa
4 changed files with 38 additions and 23 deletions
|
@ -8,6 +8,9 @@
|
|||
* Exclude the wheel package from the `pip freeze` output (like pip and setuptools).
|
||||
:issue:`2989`.
|
||||
|
||||
* Allow installing modules from a subdirectory of a vcs repository
|
||||
in non-editable mode (:issue:`3217`).
|
||||
|
||||
|
||||
**8.0.2 (2016-01-21)**
|
||||
|
||||
|
|
11
pip/index.py
11
pip/index.py
|
@ -919,7 +919,7 @@ class Link(object):
|
|||
scheme, netloc, path, query, fragment = urllib_parse.urlsplit(self.url)
|
||||
return urllib_parse.urlunsplit((scheme, netloc, path, query, None))
|
||||
|
||||
_egg_fragment_re = re.compile(r'#egg=([^&]*)')
|
||||
_egg_fragment_re = re.compile(r'[#&]egg=([^&]*)')
|
||||
|
||||
@property
|
||||
def egg_fragment(self):
|
||||
|
@ -928,6 +928,15 @@ class Link(object):
|
|||
return None
|
||||
return match.group(1)
|
||||
|
||||
_subdirectory_fragment_re = re.compile(r'[#&]subdirectory=([^&]*)')
|
||||
|
||||
@property
|
||||
def subdirectory_fragment(self):
|
||||
match = self._subdirectory_fragment_re.search(self.url)
|
||||
if not match:
|
||||
return None
|
||||
return match.group(1)
|
||||
|
||||
_hash_re = re.compile(
|
||||
r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)'
|
||||
)
|
||||
|
|
|
@ -368,6 +368,12 @@ class InstallRequirement(object):
|
|||
return None
|
||||
return native_str(self.req.project_name)
|
||||
|
||||
@property
|
||||
def setup_py_dir(self):
|
||||
return os.path.join(
|
||||
self.source_dir,
|
||||
self.link and self.link.subdirectory_fragment or '')
|
||||
|
||||
@property
|
||||
def setup_py(self):
|
||||
assert self.source_dir, "No source dir for %s" % self
|
||||
|
@ -384,15 +390,7 @@ class InstallRequirement(object):
|
|||
"install from a source distribution.\n%s" % add_msg
|
||||
)
|
||||
|
||||
setup_file = 'setup.py'
|
||||
|
||||
if self.editable_options and 'subdirectory' in self.editable_options:
|
||||
setup_py = os.path.join(self.source_dir,
|
||||
self.editable_options['subdirectory'],
|
||||
setup_file)
|
||||
|
||||
else:
|
||||
setup_py = os.path.join(self.source_dir, setup_file)
|
||||
setup_py = os.path.join(self.setup_py_dir, 'setup.py')
|
||||
|
||||
# Python2 __file__ should not be unicode
|
||||
if six.PY2 and isinstance(setup_py, six.text_type):
|
||||
|
@ -425,16 +423,12 @@ class InstallRequirement(object):
|
|||
if self.editable:
|
||||
egg_base_option = []
|
||||
else:
|
||||
egg_info_dir = os.path.join(self.source_dir, 'pip-egg-info')
|
||||
egg_info_dir = os.path.join(self.setup_py_dir, 'pip-egg-info')
|
||||
ensure_dir(egg_info_dir)
|
||||
egg_base_option = ['--egg-base', 'pip-egg-info']
|
||||
cwd = self.source_dir
|
||||
if self.editable_options and \
|
||||
'subdirectory' in self.editable_options:
|
||||
cwd = os.path.join(cwd, self.editable_options['subdirectory'])
|
||||
call_subprocess(
|
||||
egg_info_cmd + egg_base_option,
|
||||
cwd=cwd,
|
||||
cwd=self.setup_py_dir,
|
||||
show_stdout=False,
|
||||
command_level=logging.DEBUG,
|
||||
command_desc='python setup.py egg_info')
|
||||
|
@ -481,7 +475,7 @@ class InstallRequirement(object):
|
|||
if self.editable:
|
||||
base = self.source_dir
|
||||
else:
|
||||
base = os.path.join(self.source_dir, 'pip-egg-info')
|
||||
base = os.path.join(self.setup_py_dir, 'pip-egg-info')
|
||||
filenames = os.listdir(base)
|
||||
if self.editable:
|
||||
filenames = []
|
||||
|
@ -889,7 +883,7 @@ class InstallRequirement(object):
|
|||
with indent_log():
|
||||
call_subprocess(
|
||||
install_args + install_options,
|
||||
cwd=self.source_dir,
|
||||
cwd=self.setup_py_dir,
|
||||
show_stdout=False,
|
||||
spinner=spinner,
|
||||
)
|
||||
|
@ -981,10 +975,6 @@ class InstallRequirement(object):
|
|||
|
||||
with indent_log():
|
||||
# FIXME: should we do --install-headers here too?
|
||||
cwd = self.source_dir
|
||||
if self.editable_options and \
|
||||
'subdirectory' in self.editable_options:
|
||||
cwd = os.path.join(cwd, self.editable_options['subdirectory'])
|
||||
call_subprocess(
|
||||
[
|
||||
sys.executable,
|
||||
|
@ -995,7 +985,7 @@ class InstallRequirement(object):
|
|||
['develop', '--no-deps'] +
|
||||
list(install_options),
|
||||
|
||||
cwd=cwd,
|
||||
cwd=self.setup_py_dir,
|
||||
show_stdout=False)
|
||||
|
||||
self.install_succeeded = True
|
||||
|
|
|
@ -191,6 +191,19 @@ def test_install_local_editable_with_subdirectory(script):
|
|||
result.assert_installed('version-subpkg', sub_dir='version_subdir')
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_install_local_with_subdirectory(script):
|
||||
version_pkg_path = _create_test_package_with_subdirectory(script,
|
||||
'version_subdir')
|
||||
result = script.pip(
|
||||
'install',
|
||||
'%s#egg=version_subpkg&subdirectory=version_subdir' %
|
||||
('git+file://%s' % version_pkg_path,)
|
||||
)
|
||||
|
||||
result.assert_installed('version_subpkg.py', editable=False)
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_wheel_user_with_prefix_in_pydistutils_cfg(script, data, virtualenv):
|
||||
# Make sure wheel is available in the virtualenv
|
||||
|
|
Loading…
Reference in a new issue