mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Allow requirements.txt URLs to have egg= definitions.
This commit is contained in:
parent
98947e0016
commit
f73385adc5
4 changed files with 56 additions and 22 deletions
|
@ -24,6 +24,15 @@ The ``#egg=MyProject`` part is important, because while you can
|
|||
install simply given the svn location, the project name is useful in
|
||||
other places.
|
||||
|
||||
You can also specify the egg name for a non-editable url. This is useful to
|
||||
point to HEAD locations on the local filesystem:
|
||||
|
||||
file:///path/to/your/lib/project#egg=MyProject
|
||||
|
||||
or relative paths:
|
||||
|
||||
file:../../lib/project#egg=MyProject
|
||||
|
||||
If you need to give pip (and by association easy_install) hints
|
||||
about where to find a package, you can use the ``-f``
|
||||
(``--find-links``) option, like::
|
||||
|
|
16
pip/index.py
16
pip/index.py
|
@ -578,13 +578,9 @@ class Link(object):
|
|||
|
||||
@property
|
||||
def filename(self):
|
||||
url = self.url
|
||||
url = url.split('#', 1)[0]
|
||||
url = url.split('?', 1)[0]
|
||||
url = url.rstrip('/')
|
||||
url = self.url_fragment
|
||||
name = posixpath.basename(url)
|
||||
assert name, (
|
||||
'URL %r produced no filename' % url)
|
||||
assert name, ('URL %r produced no filename' % url)
|
||||
return name
|
||||
|
||||
@property
|
||||
|
@ -598,6 +594,14 @@ class Link(object):
|
|||
def splitext(self):
|
||||
return splitext(posixpath.basename(self.path.rstrip('/')))
|
||||
|
||||
@property
|
||||
def url_fragment(self):
|
||||
url = self.url
|
||||
url = url.split('#', 1)[0]
|
||||
url = url.split('?', 1)[0]
|
||||
url = url.rstrip('/')
|
||||
return url
|
||||
|
||||
_egg_fragment_re = re.compile(r'#egg=([^&]*)')
|
||||
|
||||
@property
|
||||
|
|
36
pip/req.py
36
pip/req.py
|
@ -73,28 +73,34 @@ class InstallRequirement(object):
|
|||
"""
|
||||
url = None
|
||||
name = name.strip()
|
||||
req = name
|
||||
req = None
|
||||
path = os.path.normpath(os.path.abspath(name))
|
||||
link = None
|
||||
|
||||
if is_url(name):
|
||||
url = name
|
||||
## FIXME: I think getting the requirement here is a bad idea:
|
||||
#req = get_requirement_from_url(url)
|
||||
req = None
|
||||
link = Link(name)
|
||||
elif os.path.isdir(path) and (os.path.sep in name or name.startswith('.')):
|
||||
if not is_installable_dir(path):
|
||||
raise InstallationError("Directory %r is not installable. File 'setup.py' not found."
|
||||
% name)
|
||||
url = path_to_url(name)
|
||||
#req = get_requirement_from_url(url)
|
||||
req = None
|
||||
raise InstallationError("Directory %r is not installable. File 'setup.py' not found.", name)
|
||||
link = Link(path_to_url(name))
|
||||
elif is_archive_file(path):
|
||||
if not os.path.isfile(path):
|
||||
logger.warn('Requirement %r looks like a filename, but the file does not exist'
|
||||
% name)
|
||||
url = path_to_url(name)
|
||||
#req = get_requirement_from_url(url)
|
||||
req = None
|
||||
logger.warn('Requirement %r looks like a filename, but the file does not exist', name)
|
||||
link = Link(path_to_url(name))
|
||||
|
||||
# If the line has an egg= definition, but isn't editable, pull the requirement out.
|
||||
# Otherwise, assume the name is the req for the non URL/path/archive case.
|
||||
if link and req is None:
|
||||
url = link.url_fragment
|
||||
req = link.egg_fragment
|
||||
|
||||
# Handle relative file URLs
|
||||
if link.scheme == 'file' and re.search(r'\.\./', url):
|
||||
url = path_to_url(os.path.normpath(os.path.abspath(link.path)))
|
||||
|
||||
else:
|
||||
req = name
|
||||
|
||||
return cls(req, comes_from, url=url)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import textwrap
|
||||
from pip.backwardcompat import urllib
|
||||
from pip.req import Requirements
|
||||
from tests.test_pip import reset_env, run_pip, write_file, pyversion
|
||||
from tests.test_pip import reset_env, run_pip, write_file, pyversion, here
|
||||
from tests.local_repos import local_checkout
|
||||
from tests.path import Path
|
||||
|
||||
def test_requirements_file():
|
||||
"""
|
||||
|
@ -22,6 +24,19 @@ def test_requirements_file():
|
|||
fn = '%s-%s-py%s.egg-info' % (other_lib_name, other_lib_version, pyversion)
|
||||
assert result.files_created[env.site_packages/fn].dir
|
||||
|
||||
def test_relative_requirements_file():
|
||||
"""
|
||||
Test installing from a requirements file with a relative path with an egg= definition..
|
||||
|
||||
"""
|
||||
url = 'file://' + str(urllib.quote(Path(here).abspath + '/packages/../packages/FSPkg') + '#egg=FSPkg').replace('\\', '/')
|
||||
env = reset_env()
|
||||
write_file('file-egg-req.txt', textwrap.dedent("""\
|
||||
%s
|
||||
""" % url))
|
||||
result = run_pip('install', '-vvv', '-r', env.scratch_path / 'file-egg-req.txt')
|
||||
assert (env.site_packages/'FSPkg-0.1dev-py%s.egg-info' % pyversion) in result.files_created, str(result)
|
||||
assert (env.site_packages/'fspkg') in result.files_created, str(result.stdout)
|
||||
|
||||
def test_multiple_requirements_files():
|
||||
"""
|
||||
|
|
Loading…
Reference in a new issue