Move InstallRequirement.from_line to constructors module

This commit is contained in:
Pradyun Gedam 2018-08-21 20:37:40 +05:30
parent 69b494aa29
commit a5a07fe61c
No known key found for this signature in database
GPG Key ID: DA17C4B29CB32E4B
11 changed files with 240 additions and 221 deletions

View File

@ -22,9 +22,10 @@ from pip._internal.exceptions import (
)
from pip._internal.index import PackageFinder
from pip._internal.locations import running_under_virtualenv
from pip._internal.req.constructors import install_req_from_editable
from pip._internal.req.constructors import (
install_req_from_editable, install_req_from_line,
)
from pip._internal.req.req_file import parse_requirements
from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.logging import setup_logging
from pip._internal.utils.misc import get_prog, normalize_path
from pip._internal.utils.outdated import pip_version_check
@ -209,7 +210,7 @@ class RequirementCommand(Command):
requirement_set.add_requirement(req_to_add)
for req in args:
req_to_add = InstallRequirement.from_line(
req_to_add = install_req_from_line(
req, None, isolated=options.isolated_mode,
wheel_cache=wheel_cache
)

View File

@ -4,7 +4,8 @@ from pip._vendor.packaging.utils import canonicalize_name
from pip._internal.cli.base_command import Command
from pip._internal.exceptions import InstallationError
from pip._internal.req import InstallRequirement, parse_requirements
from pip._internal.req import parse_requirements
from pip._internal.req.constructors import install_req_from_line
from pip._internal.utils.misc import protect_pip_from_modification_on_windows
@ -47,7 +48,7 @@ class UninstallCommand(Command):
with self._build_session(options) as session:
reqs_to_uninstall = {}
for name in args:
req = InstallRequirement.from_line(
req = install_req_from_line(
name, isolated=options.isolated_mode,
)
if req.name:

View File

@ -10,8 +10,9 @@ from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.pkg_resources import RequirementParseError
from pip._internal.exceptions import InstallationError
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_editable
from pip._internal.req.constructors import (
install_req_from_editable, install_req_from_line,
)
from pip._internal.req.req_file import COMMENT_RE
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.misc import (
@ -106,7 +107,7 @@ def freeze(
wheel_cache=wheel_cache,
)
else:
line_req = InstallRequirement.from_line(
line_req = install_req_from_line(
COMMENT_RE.sub('', line).strip(),
isolated=isolated,
wheel_cache=wheel_cache,

View File

@ -8,18 +8,45 @@ These are meant to be used elsewhere within pip to create instances of
InstallRequirement.
"""
import logging
import os
import re
import traceback
from pip._vendor.packaging.markers import Marker
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
from pip._vendor.packaging.specifiers import Specifier
from pip._vendor.pkg_resources import RequirementParseError, parse_requirements
# XXX: Temporarily importing _strip_extras
from pip._internal.download import path_to_url, url_to_path
from pip._internal.download import (
is_archive_file, is_url, path_to_url, url_to_path,
)
from pip._internal.exceptions import InstallationError
from pip._internal.models.link import Link
from pip._internal.req.req_install import InstallRequirement, _strip_extras
from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.misc import is_installable_dir
from pip._internal.vcs import vcs
from pip._internal.wheel import Wheel
__all__ = ["install_req_from_editable", "parse_editable"]
__all__ = [
"install_req_from_editable", "install_req_from_line",
"parse_editable"
]
logger = logging.getLogger(__name__)
operators = Specifier._operators.keys()
def _strip_extras(path):
m = re.match(r'^(.+)(\[[^\]]+\])$', path)
extras = None
if m:
path_no_extras = m.group(1)
extras = m.group(2)
else:
path_no_extras = path
return path_no_extras, extras
def parse_editable(editable_req):
@ -87,6 +114,36 @@ def parse_editable(editable_req):
return package_name, url, None
def deduce_helpful_msg(req):
"""Returns helpful msg in case requirements file does not exist,
or cannot be parsed.
:params req: Requirements file path
"""
msg = ""
if os.path.exists(req):
msg = " It does exist."
# Try to parse and check if it is a requirements file.
try:
with open(req, 'r') as fp:
# parse first line only
next(parse_requirements(fp.read()))
msg += " The argument you provided " + \
"(%s) appears to be a" % (req) + \
" requirements file. If that is the" + \
" case, use the '-r' flag to install" + \
" the packages specified within it."
except RequirementParseError:
logger.debug("Cannot parse '%s' as requirements \
file" % (req), exc_info=1)
else:
msg += " File '%s' does not exist." % (req)
return msg
# ---- The actual constructors follow ----
def install_req_from_editable(
editable_req, comes_from=None, isolated=False, options=None,
wheel_cache=None, constraint=False
@ -114,3 +171,102 @@ def install_req_from_editable(
wheel_cache=wheel_cache,
extras=extras_override or (),
)
def install_req_from_line(
name, comes_from=None, isolated=False, options=None, wheel_cache=None,
constraint=False
):
"""Creates an InstallRequirement from a name, which might be a
requirement, directory containing 'setup.py', filename, or URL.
"""
if is_url(name):
marker_sep = '; '
else:
marker_sep = ';'
if marker_sep in name:
name, markers = name.split(marker_sep, 1)
markers = markers.strip()
if not markers:
markers = None
else:
markers = Marker(markers)
else:
markers = None
name = name.strip()
req = None
path = os.path.normpath(os.path.abspath(name))
link = None
extras = None
if is_url(name):
link = Link(name)
else:
p, extras = _strip_extras(path)
looks_like_dir = os.path.isdir(p) and (
os.path.sep in name or
(os.path.altsep is not None and os.path.altsep in name) or
name.startswith('.')
)
if looks_like_dir:
if not is_installable_dir(p):
raise InstallationError(
"Directory %r is not installable. Neither 'setup.py' "
"nor 'pyproject.toml' found." % name
)
link = Link(path_to_url(p))
elif is_archive_file(p):
if not os.path.isfile(p):
logger.warning(
'Requirement %r looks like a filename, but the '
'file does not exist',
name
)
link = Link(path_to_url(p))
# it's a local file, dir, or url
if link:
# Handle relative file URLs
if link.scheme == 'file' and re.search(r'\.\./', link.url):
link = Link(
path_to_url(os.path.normpath(os.path.abspath(link.path))))
# wheel file
if link.is_wheel:
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
req = "%s==%s" % (wheel.name, wheel.version)
else:
# set the req to the egg fragment. when it's not there, this
# will become an 'unnamed' requirement
req = link.egg_fragment
# a requirement specifier
else:
req = name
if extras:
extras = Requirement("placeholder" + extras.lower()).extras
else:
extras = ()
if req is not None:
try:
req = Requirement(req)
except InvalidRequirement:
if os.path.sep in req:
add_msg = "It looks like a path."
add_msg += deduce_helpful_msg(req)
elif '=' in req and not any(op in req for op in operators):
add_msg = "= is not a valid operator. Did you mean == ?"
else:
add_msg = traceback.format_exc()
raise InstallationError(
"Invalid requirement: '%s'\n%s" % (req, add_msg)
)
return InstallRequirement(
req, comes_from, link=link, markers=markers,
isolated=isolated,
options=options if options else {},
wheel_cache=wheel_cache,
constraint=constraint,
extras=extras,
)

View File

@ -16,8 +16,9 @@ from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.cli import cmdoptions
from pip._internal.download import get_file_content
from pip._internal.exceptions import RequirementsFileParseError
from pip._internal.req.constructors import install_req_from_editable
from pip._internal.req.req_install import InstallRequirement
from pip._internal.req.constructors import (
install_req_from_editable, install_req_from_line,
)
__all__ = ['parse_requirements']
@ -152,7 +153,7 @@ def process_line(line, filename, line_number, finder=None, comes_from=None,
for dest in SUPPORTED_OPTIONS_REQ_DEST:
if dest in opts.__dict__ and opts.__dict__[dest]:
req_options[dest] = opts.__dict__[dest]
yield InstallRequirement.from_line(
yield install_req_from_line(
args_str, line_comes_from, constraint=constraint,
isolated=isolated, options=req_options, wheel_cache=wheel_cache
)

View File

@ -2,27 +2,21 @@ from __future__ import absolute_import
import logging
import os
import re
import shutil
import sys
import sysconfig
import traceback
import zipfile
from distutils.util import change_root
from pip._vendor import pkg_resources, six
from pip._vendor.packaging import specifiers
from pip._vendor.packaging.markers import Marker
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.packaging.version import Version
from pip._vendor.packaging.version import parse as parse_version
from pip._vendor.pep517.wrappers import Pep517HookCaller
from pip._vendor.pkg_resources import RequirementParseError, parse_requirements
from pip._internal import wheel
from pip._internal.build_env import NoOpBuildEnvironment
from pip._internal.download import is_archive_file, is_url, path_to_url
from pip._internal.exceptions import InstallationError
from pip._internal.locations import (
PIP_DELETE_MARKER_FILENAME, running_under_virtualenv,
@ -37,31 +31,17 @@ from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import (
_make_build_dir, ask_path_exists, backup_dir, call_subprocess,
display_path, dist_in_site_packages, dist_in_usersite, ensure_dir,
get_installed_version, is_installable_dir, rmtree,
get_installed_version, rmtree,
)
from pip._internal.utils.packaging import get_metadata
from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.utils.ui import open_spinner
from pip._internal.vcs import vcs
from pip._internal.wheel import Wheel, move_wheel_files
from pip._internal.wheel import move_wheel_files
logger = logging.getLogger(__name__)
operators = specifiers.Specifier._operators.keys()
def _strip_extras(path):
m = re.match(r'^(.+)(\[[^\]]+\])$', path)
extras = None
if m:
path_no_extras = m.group(1)
extras = m.group(2)
else:
path_no_extras = path
return path_no_extras, extras
class InstallRequirement(object):
"""
@ -168,102 +148,6 @@ class InstallRequirement(object):
return cls(req, comes_from, isolated=isolated, wheel_cache=wheel_cache)
@classmethod
def from_line(
cls, name, comes_from=None, isolated=False, options=None,
wheel_cache=None, constraint=False):
"""Creates an InstallRequirement from a name, which might be a
requirement, directory containing 'setup.py', filename, or URL.
"""
if is_url(name):
marker_sep = '; '
else:
marker_sep = ';'
if marker_sep in name:
name, markers = name.split(marker_sep, 1)
markers = markers.strip()
if not markers:
markers = None
else:
markers = Marker(markers)
else:
markers = None
name = name.strip()
req = None
path = os.path.normpath(os.path.abspath(name))
link = None
extras = None
if is_url(name):
link = Link(name)
else:
p, extras = _strip_extras(path)
looks_like_dir = os.path.isdir(p) and (
os.path.sep in name or
(os.path.altsep is not None and os.path.altsep in name) or
name.startswith('.')
)
if looks_like_dir:
if not is_installable_dir(p):
raise InstallationError(
"Directory %r is not installable. Neither 'setup.py' "
"nor 'pyproject.toml' found." % name
)
link = Link(path_to_url(p))
elif is_archive_file(p):
if not os.path.isfile(p):
logger.warning(
'Requirement %r looks like a filename, but the '
'file does not exist',
name
)
link = Link(path_to_url(p))
# it's a local file, dir, or url
if link:
# Handle relative file URLs
if link.scheme == 'file' and re.search(r'\.\./', link.url):
link = Link(
path_to_url(os.path.normpath(os.path.abspath(link.path))))
# wheel file
if link.is_wheel:
wheel = Wheel(link.filename) # can raise InvalidWheelFilename
req = "%s==%s" % (wheel.name, wheel.version)
else:
# set the req to the egg fragment. when it's not there, this
# will become an 'unnamed' requirement
req = link.egg_fragment
# a requirement specifier
else:
req = name
if extras:
extras = Requirement("placeholder" + extras.lower()).extras
else:
extras = ()
if req is not None:
try:
req = Requirement(req)
except InvalidRequirement:
if os.path.sep in req:
add_msg = "It looks like a path."
add_msg += deduce_helpful_msg(req)
elif '=' in req and not any(op in req for op in operators):
add_msg = "= is not a valid operator. Did you mean == ?"
else:
add_msg = traceback.format_exc()
raise InstallationError(
"Invalid requirement: '%s'\n%s" % (req, add_msg))
return cls(
req, comes_from, link=link, markers=markers,
isolated=isolated,
options=options if options else {},
wheel_cache=wheel_cache,
constraint=constraint,
extras=extras,
)
def __str__(self):
if self.req:
s = str(self.req)
@ -998,30 +882,3 @@ class InstallRequirement(object):
py_ver_str, self.name)]
return install_args
def deduce_helpful_msg(req):
"""Returns helpful msg in case requirements file does not exist,
or cannot be parsed.
:params req: Requirements file path
"""
msg = ""
if os.path.exists(req):
msg = " It does exist."
# Try to parse and check if it is a requirements file.
try:
with open(req, 'r') as fp:
# parse first line only
next(parse_requirements(fp.read()))
msg += " The argument you provided " + \
"(%s) appears to be a" % (req) + \
" requirements file. If that is the" + \
" case, use the '-r' flag to install" + \
" the packages specified within it."
except RequirementParseError:
logger.debug("Cannot parse '%s' as requirements \
file" % (req), exc_info=1)
else:
msg += " File '%s' does not exist." % (req)
return msg

View File

@ -11,7 +11,7 @@ from tempfile import mkdtemp
import pretend
import pytest
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_line
from pip._internal.utils.misc import rmtree
from tests.lib import assert_all_changes, create_test_package_with_setup
from tests.lib.local_repos import local_checkout, local_repo
@ -439,7 +439,7 @@ def test_uninstall_non_local_distutils(caplog, monkeypatch, tmpdir):
get_dist = pretend.call_recorder(lambda x: dist)
monkeypatch.setattr("pip._vendor.pkg_resources.get_distribution", get_dist)
req = InstallRequirement.from_line("thing")
req = install_req_from_line("thing")
req.uninstall()
assert os.path.exists(einfo)

View File

@ -14,13 +14,13 @@ from pip._internal.exceptions import (
from pip._internal.index import (
FormatControl, InstallationCandidate, Link, PackageFinder, fmt_ctl_formats,
)
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_line
def test_no_mpkg(data):
"""Finder skips zipfiles with "macosx10" in the name."""
finder = PackageFinder([data.find_links], [], session=PipSession())
req = InstallRequirement.from_line("pkgwithmpkg")
req = install_req_from_line("pkgwithmpkg")
found = finder.find_requirement(req, False)
assert found.url.endswith("pkgwithmpkg-1.0.tar.gz"), found
@ -29,7 +29,7 @@ def test_no_mpkg(data):
def test_no_partial_name_match(data):
"""Finder requires the full project name to match, not just beginning."""
finder = PackageFinder([data.find_links], [], session=PipSession())
req = InstallRequirement.from_line("gmpy")
req = install_req_from_line("gmpy")
found = finder.find_requirement(req, False)
assert found.url.endswith("gmpy-1.15.tar.gz"), found
@ -40,7 +40,7 @@ def test_tilde():
session = PipSession()
with patch('pip._internal.index.os.path.exists', return_value=True):
finder = PackageFinder(['~/python-pkgs'], [], session=session)
req = InstallRequirement.from_line("gmpy")
req = install_req_from_line("gmpy")
with pytest.raises(DistributionNotFound):
finder.find_requirement(req, False)
@ -53,7 +53,7 @@ def test_duplicates_sort_ok(data):
[],
session=PipSession(),
)
req = InstallRequirement.from_line("duplicate")
req = install_req_from_line("duplicate")
found = finder.find_requirement(req, False)
assert found.url.endswith("duplicate-1.0.tar.gz"), found
@ -61,7 +61,7 @@ def test_duplicates_sort_ok(data):
def test_finder_detects_latest_find_links(data):
"""Test PackageFinder detects latest using find-links"""
req = InstallRequirement.from_line('simple', None)
req = install_req_from_line('simple', None)
finder = PackageFinder([data.find_links], [], session=PipSession())
link = finder.find_requirement(req, False)
assert link.url.endswith("simple-3.0.tar.gz")
@ -69,7 +69,7 @@ def test_finder_detects_latest_find_links(data):
def test_incorrect_case_file_index(data):
"""Test PackageFinder detects latest using wrong case"""
req = InstallRequirement.from_line('dinner', None)
req = install_req_from_line('dinner', None)
finder = PackageFinder([], [data.find_links3], session=PipSession())
link = finder.find_requirement(req, False)
assert link.url.endswith("Dinner-2.0.tar.gz")
@ -78,7 +78,7 @@ def test_incorrect_case_file_index(data):
@pytest.mark.network
def test_finder_detects_latest_already_satisfied_find_links(data):
"""Test PackageFinder detects latest already satisfied using find-links"""
req = InstallRequirement.from_line('simple', None)
req = install_req_from_line('simple', None)
# the latest simple in local pkgs is 3.0
latest_version = "3.0"
satisfied_by = Mock(
@ -96,7 +96,7 @@ def test_finder_detects_latest_already_satisfied_find_links(data):
@pytest.mark.network
def test_finder_detects_latest_already_satisfied_pypi_links():
"""Test PackageFinder detects latest already satisfied using pypi links"""
req = InstallRequirement.from_line('initools', None)
req = install_req_from_line('initools', None)
# the latest initools on pypi is 0.3.1
latest_version = "0.3.1"
satisfied_by = Mock(
@ -123,7 +123,7 @@ class TestWheel:
"""
caplog.set_level(logging.DEBUG)
req = InstallRequirement.from_line("invalid")
req = install_req_from_line("invalid")
# data.find_links contains "invalid.whl", which is an invalid wheel
finder = PackageFinder(
[data.find_links],
@ -148,7 +148,7 @@ class TestWheel:
lambda **kw: [("py1", "none", "any")],
)
req = InstallRequirement.from_line("simple.dist")
req = install_req_from_line("simple.dist")
finder = PackageFinder(
[data.find_links],
[],
@ -169,7 +169,7 @@ class TestWheel:
lambda **kw: [('py2', 'none', 'any')],
)
req = InstallRequirement.from_line("simple.dist")
req = install_req_from_line("simple.dist")
finder = PackageFinder(
[data.find_links],
[],
@ -185,7 +185,7 @@ class TestWheel:
Test wheels have priority over sdists.
`test_link_sorting` also covers this at lower level
"""
req = InstallRequirement.from_line("priority")
req = install_req_from_line("priority")
finder = PackageFinder(
[data.find_links],
[],
@ -199,7 +199,7 @@ class TestWheel:
Test existing install has priority over wheels.
`test_link_sorting` also covers this at a lower level
"""
req = InstallRequirement.from_line('priority', None)
req = install_req_from_line('priority', None)
latest_version = "1.0"
satisfied_by = Mock(
location="/path",
@ -284,7 +284,7 @@ class TestWheel:
def test_finder_priority_file_over_page(data):
"""Test PackageFinder prefers file links over equivalent page links"""
req = InstallRequirement.from_line('gmpy==1.15', None)
req = install_req_from_line('gmpy==1.15', None)
finder = PackageFinder(
[data.find_links],
["http://pypi.org/simple/"],
@ -304,7 +304,7 @@ def test_finder_deplink():
"""
Test PackageFinder with dependency links only
"""
req = InstallRequirement.from_line('gmpy==1.15', None)
req = install_req_from_line('gmpy==1.15', None)
finder = PackageFinder(
[],
[],
@ -323,7 +323,7 @@ def test_finder_priority_page_over_deplink():
"""
Test PackageFinder prefers page links over equivalent dependency links
"""
req = InstallRequirement.from_line('pip==1.5.6', None)
req = install_req_from_line('pip==1.5.6', None)
finder = PackageFinder(
[],
["https://pypi.org/simple/"],
@ -346,7 +346,7 @@ def test_finder_priority_page_over_deplink():
def test_finder_priority_nonegg_over_eggfragments():
"""Test PackageFinder prefers non-egg links over "#egg=" links"""
req = InstallRequirement.from_line('bar==1.0', None)
req = install_req_from_line('bar==1.0', None)
links = ['http://foo/bar.py#egg=bar-1.0', 'http://foo/bar-1.0.tar.gz']
finder = PackageFinder(links, [], session=PipSession())
@ -377,7 +377,7 @@ def test_finder_only_installs_stable_releases(data):
Test PackageFinder only accepts stable versioned releases by default.
"""
req = InstallRequirement.from_line("bar", None)
req = install_req_from_line("bar", None)
# using a local index (that has pre & dev releases)
finder = PackageFinder([], [data.index_url("pre")], session=PipSession())
@ -431,7 +431,7 @@ def test_finder_installs_pre_releases(data):
Test PackageFinder finds pre-releases if asked to.
"""
req = InstallRequirement.from_line("bar", None)
req = install_req_from_line("bar", None)
# using a local index (that has pre & dev releases)
finder = PackageFinder(
@ -471,7 +471,7 @@ def test_finder_installs_dev_releases(data):
Test PackageFinder finds dev releases if asked to.
"""
req = InstallRequirement.from_line("bar", None)
req = install_req_from_line("bar", None)
# using a local index (that has dev releases)
finder = PackageFinder(
@ -487,7 +487,7 @@ def test_finder_installs_pre_releases_with_version_spec():
"""
Test PackageFinder only accepts stable versioned releases by default.
"""
req = InstallRequirement.from_line("bar>=0.0.dev0", None)
req = install_req_from_line("bar>=0.0.dev0", None)
links = ["https://foo/bar-1.0.tar.gz", "https://foo/bar-2.0b1.tar.gz"]
finder = PackageFinder(links, [], session=PipSession())
@ -555,7 +555,7 @@ def test_get_index_urls_locations():
finder = PackageFinder(
[], ['file://index1/', 'file://index2'], session=PipSession())
locations = finder._get_index_urls_locations(
InstallRequirement.from_line('Complex_Name').name)
install_req_from_line('Complex_Name').name)
assert locations == ['file://index1/complex-name/',
'file://index2/complex-name/']

View File

@ -18,7 +18,7 @@ from pip._internal.index import PackageFinder
from pip._internal.operations.prepare import RequirementPreparer
from pip._internal.req import InstallRequirement, RequirementSet
from pip._internal.req.constructors import (
install_req_from_editable, parse_editable,
install_req_from_editable, install_req_from_line, parse_editable,
)
from pip._internal.req.req_file import process_line
from pip._internal.req.req_tracker import RequirementTracker
@ -68,7 +68,7 @@ class TestRequirementSet(object):
os.makedirs(build_dir)
open(os.path.join(build_dir, "setup.py"), 'w')
reqset = RequirementSet()
req = InstallRequirement.from_line('simple')
req = install_req_from_line('simple')
req.is_direct = True
reqset.add_requirement(req)
finder = PackageFinder([data.find_links], [], session=PipSession())
@ -341,12 +341,12 @@ class TestInstallRequirement(object):
"""InstallRequirement should strip the fragment, but not the query."""
url = 'http://foo.com/?p=bar.git;a=snapshot;h=v0.1;sf=tgz'
fragment = '#egg=bar'
req = InstallRequirement.from_line(url + fragment)
req = install_req_from_line(url + fragment)
assert req.link.url == url + fragment, req.link
def test_unsupported_wheel_link_requirement_raises(self):
reqset = RequirementSet()
req = InstallRequirement.from_line(
req = install_req_from_line(
'https://whatever.com/peppercorn-0.4-py2.py3-bogus-any.whl',
)
assert req.link is not None
@ -358,7 +358,7 @@ class TestInstallRequirement(object):
def test_unsupported_wheel_local_file_requirement_raises(self, data):
reqset = RequirementSet()
req = InstallRequirement.from_line(
req = install_req_from_line(
data.packages.join('simple.dist-0.1-py1-none-invalid.whl'),
)
assert req.link is not None
@ -369,32 +369,32 @@ class TestInstallRequirement(object):
reqset.add_requirement(req)
def test_installed_version_not_installed(self):
req = InstallRequirement.from_line('simple-0.1-py2.py3-none-any.whl')
req = install_req_from_line('simple-0.1-py2.py3-none-any.whl')
assert req.installed_version is None
def test_str(self):
req = InstallRequirement.from_line('simple==0.1')
req = install_req_from_line('simple==0.1')
assert str(req) == 'simple==0.1'
def test_repr(self):
req = InstallRequirement.from_line('simple==0.1')
req = install_req_from_line('simple==0.1')
assert repr(req) == (
'<InstallRequirement object: simple==0.1 editable=False>'
)
def test_invalid_wheel_requirement_raises(self):
with pytest.raises(InvalidWheelFilename):
InstallRequirement.from_line('invalid.whl')
install_req_from_line('invalid.whl')
def test_wheel_requirement_sets_req_attribute(self):
req = InstallRequirement.from_line('simple-0.1-py2.py3-none-any.whl')
req = install_req_from_line('simple-0.1-py2.py3-none-any.whl')
assert isinstance(req.req, Requirement)
assert str(req.req) == 'simple==0.1'
def test_url_preserved_line_req(self):
"""Confirm the url is preserved in a non-editable requirement"""
url = 'git+http://foo.com@ref#egg=foo'
req = InstallRequirement.from_line(url)
req = install_req_from_line(url)
assert req.link.url == url
def test_url_preserved_editable_req(self):
@ -409,7 +409,7 @@ class TestInstallRequirement(object):
'/path/to/foo.egg-info/'.replace('/', os.path.sep),
))
def test_get_dist(self, path):
req = InstallRequirement.from_line('foo')
req = install_req_from_line('foo')
req._egg_info_path = path
dist = req.get_dist()
assert isinstance(dist, pkg_resources.Distribution)
@ -425,14 +425,14 @@ class TestInstallRequirement(object):
# without spaces
'mock3;python_version >= "3"',
):
req = InstallRequirement.from_line(line)
req = install_req_from_line(line)
assert req.req.name == 'mock3'
assert str(req.req.specifier) == ''
assert str(req.markers) == 'python_version >= "3"'
def test_markers_semicolon(self):
# check that the markers can contain a semicolon
req = InstallRequirement.from_line('semicolon; os_name == "a; b"')
req = install_req_from_line('semicolon; os_name == "a; b"')
assert req.req.name == 'semicolon'
assert str(req.req.specifier) == ''
assert str(req.markers) == 'os_name == "a; b"'
@ -441,14 +441,14 @@ class TestInstallRequirement(object):
# test "URL; markers" syntax
url = 'http://foo.com/?p=bar.git;a=snapshot;h=v0.1;sf=tgz'
line = '%s; python_version >= "3"' % url
req = InstallRequirement.from_line(line)
req = install_req_from_line(line)
assert req.link.url == url, req.url
assert str(req.markers) == 'python_version >= "3"'
# without space, markers are part of the URL
url = 'http://foo.com/?p=bar.git;a=snapshot;h=v0.1;sf=tgz'
line = '%s;python_version >= "3"' % url
req = InstallRequirement.from_line(line)
req = install_req_from_line(line)
assert req.link.url == line, req.url
assert req.markers is None
@ -459,7 +459,7 @@ class TestInstallRequirement(object):
'sys_platform == %r' % sys.platform,
):
line = 'name; ' + markers
req = InstallRequirement.from_line(line)
req = install_req_from_line(line)
assert str(req.markers) == str(Marker(markers))
assert req.match_markers()
@ -469,7 +469,7 @@ class TestInstallRequirement(object):
'sys_platform != %r' % sys.platform,
):
line = 'name; ' + markers
req = InstallRequirement.from_line(line)
req = install_req_from_line(line)
assert str(req.markers) == str(Marker(markers))
assert not req.match_markers()
@ -480,7 +480,7 @@ class TestInstallRequirement(object):
'sys_platform == %r' % sys.platform,
):
line = 'name; ' + markers
req = InstallRequirement.from_line(line, comes_from='')
req = install_req_from_line(line, comes_from='')
assert str(req.markers) == str(Marker(markers))
assert req.match_markers()
@ -490,7 +490,7 @@ class TestInstallRequirement(object):
'sys_platform != %r' % sys.platform,
):
line = 'name; ' + markers
req = InstallRequirement.from_line(line, comes_from='')
req = install_req_from_line(line, comes_from='')
assert str(req.markers) == str(Marker(markers))
assert not req.match_markers()
@ -498,7 +498,7 @@ class TestInstallRequirement(object):
line = 'SomeProject[ex1,ex2]'
filename = 'filename'
comes_from = '-r %s (line %s)' % (filename, 1)
req = InstallRequirement.from_line(line, comes_from=comes_from)
req = install_req_from_line(line, comes_from=comes_from)
assert len(req.extras) == 2
assert req.extras == {'ex1', 'ex2'}
@ -506,7 +506,7 @@ class TestInstallRequirement(object):
line = 'git+https://url#egg=SomeProject[ex1,ex2]'
filename = 'filename'
comes_from = '-r %s (line %s)' % (filename, 1)
req = InstallRequirement.from_line(line, comes_from=comes_from)
req = install_req_from_line(line, comes_from=comes_from)
assert len(req.extras) == 2
assert req.extras == {'ex1', 'ex2'}
@ -528,7 +528,7 @@ class TestInstallRequirement(object):
def test_unexisting_path(self):
with pytest.raises(InstallationError) as e:
InstallRequirement.from_line(
install_req_from_line(
os.path.join('this', 'path', 'does', 'not', 'exist'))
err_msg = e.value.args[0]
assert "Invalid requirement" in err_msg
@ -536,14 +536,14 @@ class TestInstallRequirement(object):
def test_single_equal_sign(self):
with pytest.raises(InstallationError) as e:
InstallRequirement.from_line('toto=42')
install_req_from_line('toto=42')
err_msg = e.value.args[0]
assert "Invalid requirement" in err_msg
assert "= is not a valid operator. Did you mean == ?" in err_msg
def test_traceback(self):
with pytest.raises(InstallationError) as e:
InstallRequirement.from_line('toto 42')
install_req_from_line('toto 42')
err_msg = e.value.args[0]
assert "Invalid requirement" in err_msg
assert "\nTraceback " in err_msg
@ -553,7 +553,7 @@ class TestInstallRequirement(object):
with open(req_file_path, 'w') as req_file:
req_file.write('pip\nsetuptools')
with pytest.raises(InstallationError) as e:
InstallRequirement.from_line(req_file_path)
install_req_from_line(req_file_path)
err_msg = e.value.args[0]
assert "Invalid requirement" in err_msg
assert "It looks like a path. It does exist." in err_msg
@ -610,10 +610,10 @@ def test_parse_editable_local_extras(
def test_exclusive_environment_markers():
"""Make sure RequirementSet accepts several excluding env markers"""
eq26 = InstallRequirement.from_line(
eq26 = install_req_from_line(
"Django>=1.6.10,<1.7 ; python_version == '2.6'")
eq26.is_direct = True
ne26 = InstallRequirement.from_line(
ne26 = install_req_from_line(
"Django>=1.6.10,<1.8 ; python_version != '2.6'")
ne26.is_direct = True

View File

@ -12,12 +12,13 @@ from pip._internal.exceptions import (
InstallationError, RequirementsFileParseError,
)
from pip._internal.index import PackageFinder
from pip._internal.req.constructors import install_req_from_editable
from pip._internal.req.constructors import (
install_req_from_editable, install_req_from_line,
)
from pip._internal.req.req_file import (
break_args_options, ignore_comments, join_lines, parse_requirements,
preprocess, process_line, skip_regex,
)
from pip._internal.req.req_install import InstallRequirement
from tests.lib import requirements_file
@ -193,14 +194,14 @@ class TestProcessLine(object):
line = 'SomeProject'
filename = 'filename'
comes_from = '-r %s (line %s)' % (filename, 1)
req = InstallRequirement.from_line(line, comes_from=comes_from)
req = install_req_from_line(line, comes_from=comes_from)
assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
def test_yield_line_constraint(self):
line = 'SomeProject'
filename = 'filename'
comes_from = '-c %s (line %s)' % (filename, 1)
req = InstallRequirement.from_line(
req = install_req_from_line(
line, comes_from=comes_from, constraint=True)
found_req = list(process_line(line, filename, 1, constraint=True))[0]
assert repr(found_req) == repr(req)
@ -210,7 +211,7 @@ class TestProcessLine(object):
line = 'SomeProject >= 2'
filename = 'filename'
comes_from = '-r %s (line %s)' % (filename, 1)
req = InstallRequirement.from_line(line, comes_from=comes_from)
req = install_req_from_line(line, comes_from=comes_from)
assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
assert str(req.req.specifier) == '>=2'
@ -235,7 +236,7 @@ class TestProcessLine(object):
def test_nested_requirements_file(self, monkeypatch):
line = '-r another_file'
req = InstallRequirement.from_line('SomeProject')
req = install_req_from_line('SomeProject')
import pip._internal.req.req_file
def stub_parse_requirements(req_url, finder, comes_from, options,
@ -248,7 +249,7 @@ class TestProcessLine(object):
def test_nested_constraints_file(self, monkeypatch):
line = '-c another_file'
req = InstallRequirement.from_line('SomeProject')
req = install_req_from_line('SomeProject')
import pip._internal.req.req_file
def stub_parse_requirements(req_url, finder, comes_from, options,

View File

@ -3,6 +3,7 @@ import tempfile
import pytest
from pip._internal.req.constructors import install_req_from_line
from pip._internal.req.req_install import InstallRequirement
@ -36,7 +37,7 @@ class TestInstallRequirementBuildDirectory(object):
with open(setup_py_path, 'w') as f:
f.write('')
requirement = InstallRequirement.from_line(
requirement = install_req_from_line(
str(install_dir).replace(os.sep, os.altsep or os.sep)
)