mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Merge pull request #1095 from techalchemy/bugfix/1083-install-local-path
Properly split and parse requirements lines
This commit is contained in:
+32
-8
@@ -277,15 +277,33 @@ def get_requirement(dep):
|
||||
remote URIs, and package names, and that we pass only valid requirement strings
|
||||
to the requirements parser. Performs necessary modifications to requirements
|
||||
object if the user input was a local relative path.
|
||||
|
||||
:param str dep: A requirement line
|
||||
:returns: :class:`requirements.Requirement` object
|
||||
"""
|
||||
path = None
|
||||
# Split out markers if they are present - similar to how pip does it
|
||||
# See pip.req.req_install.InstallRequirement.from_line
|
||||
if not any(dep.startswith(uri_prefix) for uri_prefix in SCHEME_LIST):
|
||||
marker_sep = ';'
|
||||
else:
|
||||
marker_sep = '; '
|
||||
if marker_sep in dep:
|
||||
dep, markers = dep.split(marker_sep, 1)
|
||||
markers = markers.strip()
|
||||
if not markers:
|
||||
markers = None
|
||||
else:
|
||||
markers = None
|
||||
# Strip extras from the requirement so we can make a properly parseable req
|
||||
dep, extras = pip.req.req_install._strip_extras(dep)
|
||||
# Only operate on local, existing, non-URI formatted paths
|
||||
if (is_file(dep) and isinstance(dep, six.string_types) and
|
||||
not any(dep.startswith(uri_prefix) for uri_prefix in SCHEME_LIST)):
|
||||
dep_path = Path(dep)
|
||||
# Only parse if it is a file or an installable dir
|
||||
if dep_path.is_file() or (dep_path.is_dir() and pip.utils.is_installable_dir(dep)):
|
||||
if dep_path.is_absolute():
|
||||
if dep_path.is_absolute() or dep_path.as_posix() == '.':
|
||||
path = dep
|
||||
else:
|
||||
path = get_converted_relative_path(dep)
|
||||
@@ -296,6 +314,11 @@ def get_requirement(dep):
|
||||
if req.local_file and req.uri and not req.path and path:
|
||||
req.path = path
|
||||
req.uri = None
|
||||
if markers:
|
||||
req.markers = markers
|
||||
if extras:
|
||||
# Bizarrely this is also what pip does...
|
||||
req.extras = [r for r in requirements.parse('fakepkg{0}'.format(extras))][0].extras
|
||||
return req
|
||||
|
||||
|
||||
@@ -611,28 +634,26 @@ def convert_deps_from_pip(dep):
|
||||
hashable_path = req.uri if req.uri else req.path
|
||||
req.name = hashlib.sha256(hashable_path.encode('utf-8')).hexdigest()
|
||||
req.name = req.name[len(req.name) - 7:]
|
||||
|
||||
# {path: uri} TOML (spec 4 I guess...)
|
||||
if req.uri:
|
||||
dependency[req.name] = {'file': hashable_path}
|
||||
else:
|
||||
dependency[req.name] = {'path': hashable_path}
|
||||
|
||||
if req.extras:
|
||||
dependency[req.name].update(extras)
|
||||
|
||||
# Add --editable if applicable
|
||||
if req.editable:
|
||||
dependency[req.name].update({'editable': True})
|
||||
|
||||
# VCS Installs. Extra check for unparsed git over SSH
|
||||
if req.vcs or is_vcs(req.path):
|
||||
elif req.vcs or is_vcs(req.path):
|
||||
if req.name is None:
|
||||
raise ValueError('pipenv requires an #egg fragment for version controlled '
|
||||
'dependencies. Please install remote dependency '
|
||||
'in the form {0}#egg=<package-name>.'.format(req.uri))
|
||||
|
||||
# Extras: e.g. #egg=requests[security]
|
||||
if req.extras:
|
||||
dependency[req.name] = extras
|
||||
|
||||
# Set up this requirement as a proper VCS requirement if it was not
|
||||
if not req.vcs and req.path.startswith(VCS_LIST):
|
||||
req.vcs = [vcs for vcs in VCS_LIST if req.path.startswith(vcs)][0]
|
||||
@@ -654,6 +675,10 @@ def convert_deps_from_pip(dep):
|
||||
if req.revision:
|
||||
dependency[req.name].update({'ref': req.revision})
|
||||
|
||||
# Extras: e.g. #egg=requests[security]
|
||||
if req.extras:
|
||||
dependency[req.name].update({'extras': req.extras})
|
||||
|
||||
elif req.extras or req.specs:
|
||||
|
||||
specs = None
|
||||
@@ -679,7 +704,6 @@ def convert_deps_from_pip(dep):
|
||||
for key in dependency.copy():
|
||||
if not hasattr(dependency[key], 'keys'):
|
||||
del dependency[key]
|
||||
|
||||
return dependency
|
||||
|
||||
|
||||
|
||||
@@ -334,6 +334,39 @@ class TestPipenv:
|
||||
assert 'urllib3' in p.lockfile['default']
|
||||
assert 'pysocks' in p.lockfile['default']
|
||||
|
||||
@pytest.mark.extras
|
||||
@pytest.mark.install
|
||||
@pytest.mark.local
|
||||
def test_local_extras_install(self):
|
||||
with PipenvInstance() as p:
|
||||
setup_py = os.path.join(p.path, 'setup.py')
|
||||
with open(setup_py, 'w') as fh:
|
||||
contents = """
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='test_pipenv',
|
||||
version='0.1',
|
||||
description='Pipenv Test Package',
|
||||
author='Pipenv Test',
|
||||
author_email='test@pipenv.package',
|
||||
license='PIPENV',
|
||||
packages=find_packages(),
|
||||
install_requires=['tablib'],
|
||||
extras_require={'dev': ['flake8', 'pylint']},
|
||||
zip_safe=False
|
||||
)
|
||||
""".strip()
|
||||
fh.write(contents)
|
||||
c = p.pipenv('install .[dev]')
|
||||
assert c.return_code == 0
|
||||
key = [k for k in p.pipfile['packages'].keys()][0]
|
||||
dep = p.pipfile['packages'][key]
|
||||
assert dep['path'] == '.'
|
||||
assert dep['extras'] == ['dev']
|
||||
assert key in p.lockfile['default']
|
||||
assert 'dev' in p.lockfile['default'][key]['extras']
|
||||
|
||||
@pytest.mark.vcs
|
||||
@pytest.mark.install
|
||||
def test_basic_vcs_install(self):
|
||||
|
||||
Reference in New Issue
Block a user