mirror of https://github.com/pypa/pip
Move InstallRequirement.from_line to constructors module
This commit is contained in:
parent
69b494aa29
commit
a5a07fe61c
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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/']
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue