mirror of https://github.com/pypa/pip
Support markers in requirements
It's now possible to specify requirements markers in requirements. Examples:: futures; python_version < '2.7' mock; python_version < '3.3' nose ordereddict; python_version < '2.7' unittest2; python_version < '2.7' The separator is "; ". For convinience, ";" alone is also supported, but no in URLs. The ";" character is a legit and common character in an URL. Example of valid URL without markers:: http://foo.com/?p=bar.git;a=snapshot;h=v0.1;sf=tgz Example of URL with markers:: http://foo.com/?p=bar.git;a=snapshot;h=v0.1;sf=tgz; python_version < '3.3'
This commit is contained in:
parent
e236842944
commit
e498d83db1
|
@ -29,6 +29,12 @@ and like arguments to :ref:`pip install`, the following forms are supported::
|
|||
[-e] <local project path>
|
||||
[-e] <vcs project url>
|
||||
|
||||
Since version 6.0, pip also supports markers using the "; " separator.
|
||||
Examples::
|
||||
|
||||
futures; python_version < '2.7'
|
||||
http://my.package.repo/SomePackage-1.0.4.zip; python_version >= '3.4'
|
||||
|
||||
See the :ref:`pip install Examples<pip install Examples>` for examples of all these forms.
|
||||
|
||||
A line that begins with ``#`` is treated as a comment and ignored. Whitespace
|
||||
|
|
|
@ -13,6 +13,7 @@ from distutils import sysconfig
|
|||
from email.parser import FeedParser
|
||||
|
||||
from pip._vendor import pkg_resources, six
|
||||
from pip._vendor.distlib.markers import interpret as markers_interpret
|
||||
from pip._vendor.six.moves import configparser
|
||||
from pip._vendor.six.moves.urllib import parse as urllib_parse
|
||||
|
||||
|
@ -116,8 +117,12 @@ class InstallRequirement(object):
|
|||
requirement, directory containing 'setup.py', filename, or URL.
|
||||
"""
|
||||
url = None
|
||||
if ';' in name:
|
||||
name, markers = name.split(';', 1)
|
||||
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
|
||||
|
@ -737,7 +742,7 @@ exec(compile(
|
|||
|
||||
def match_markers(self):
|
||||
if self.markers is not None:
|
||||
return markers.interpret(self.markers)
|
||||
return markers_interpret(self.markers)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
@ -104,6 +105,63 @@ class TestInstallRequirement(object):
|
|||
req = InstallRequirement.from_editable(url)
|
||||
assert req.url == url
|
||||
|
||||
def test_markers(self):
|
||||
for line in (
|
||||
# recommanded syntax
|
||||
'mock3; python_version >= "3"',
|
||||
# with more spaces
|
||||
'mock3 ; python_version >= "3" ',
|
||||
# without spaces
|
||||
'mock3;python_version >= "3"',
|
||||
):
|
||||
req = InstallRequirement.from_line(line)
|
||||
assert req.req.project_name == 'mock3'
|
||||
assert req.req.specs == []
|
||||
assert 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"')
|
||||
assert req.req.project_name == 'semicolon'
|
||||
assert req.req.specs == []
|
||||
assert req.markers == 'os_name == "a; b"'
|
||||
|
||||
def test_markers_url(self):
|
||||
# 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)
|
||||
assert req.url == url, req.url
|
||||
assert 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)
|
||||
assert req.url == line, req.url
|
||||
assert req.markers is None
|
||||
|
||||
def test_markers_match(self):
|
||||
# match
|
||||
for markers in (
|
||||
'python_version >= "1.0"',
|
||||
'sys_platform == %r' % sys.platform,
|
||||
):
|
||||
line = 'name; ' + markers
|
||||
req = InstallRequirement.from_line(line)
|
||||
assert req.markers == markers
|
||||
assert req.match_markers()
|
||||
|
||||
# don't match
|
||||
for markers in (
|
||||
'python_version >= "5.0"',
|
||||
'sys_platform != %r' % sys.platform,
|
||||
):
|
||||
line = 'name; ' + markers
|
||||
req = InstallRequirement.from_line(line)
|
||||
assert req.markers == markers
|
||||
assert not req.match_markers()
|
||||
|
||||
|
||||
def test_requirements_data_structure_keeps_order():
|
||||
requirements = Requirements()
|
||||
|
|
Loading…
Reference in New Issue