ยปCore Development>Code coverage>Lib/distutils/versionpredicate.py

Python code coverage for Lib/distutils/versionpredicate.py

#countcontent
1n/a"""Module for parsing and testing package version predicate strings.
2n/a"""
3n/aimport re
4n/aimport distutils.version
5n/aimport operator
6n/a
7n/a
8n/are_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)",
9n/a re.ASCII)
10n/a# (package) (rest)
11n/a
12n/are_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses
13n/are_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
14n/a# (comp) (version)
15n/a
16n/a
17n/adef splitUp(pred):
18n/a """Parse a single version comparison.
19n/a
20n/a Return (comparison string, StrictVersion)
21n/a """
22n/a res = re_splitComparison.match(pred)
23n/a if not res:
24n/a raise ValueError("bad package restriction syntax: %r" % pred)
25n/a comp, verStr = res.groups()
26n/a return (comp, distutils.version.StrictVersion(verStr))
27n/a
28n/acompmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq,
29n/a ">": operator.gt, ">=": operator.ge, "!=": operator.ne}
30n/a
31n/aclass VersionPredicate:
32n/a """Parse and test package version predicates.
33n/a
34n/a >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)')
35n/a
36n/a The `name` attribute provides the full dotted name that is given::
37n/a
38n/a >>> v.name
39n/a 'pyepat.abc'
40n/a
41n/a The str() of a `VersionPredicate` provides a normalized
42n/a human-readable version of the expression::
43n/a
44n/a >>> print(v)
45n/a pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3)
46n/a
47n/a The `satisfied_by()` method can be used to determine with a given
48n/a version number is included in the set described by the version
49n/a restrictions::
50n/a
51n/a >>> v.satisfied_by('1.1')
52n/a True
53n/a >>> v.satisfied_by('1.4')
54n/a True
55n/a >>> v.satisfied_by('1.0')
56n/a False
57n/a >>> v.satisfied_by('4444.4')
58n/a False
59n/a >>> v.satisfied_by('1555.1b3')
60n/a False
61n/a
62n/a `VersionPredicate` is flexible in accepting extra whitespace::
63n/a
64n/a >>> v = VersionPredicate(' pat( == 0.1 ) ')
65n/a >>> v.name
66n/a 'pat'
67n/a >>> v.satisfied_by('0.1')
68n/a True
69n/a >>> v.satisfied_by('0.2')
70n/a False
71n/a
72n/a If any version numbers passed in do not conform to the
73n/a restrictions of `StrictVersion`, a `ValueError` is raised::
74n/a
75n/a >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)')
76n/a Traceback (most recent call last):
77n/a ...
78n/a ValueError: invalid version number '1.2zb3'
79n/a
80n/a It the module or package name given does not conform to what's
81n/a allowed as a legal module or package name, `ValueError` is
82n/a raised::
83n/a
84n/a >>> v = VersionPredicate('foo-bar')
85n/a Traceback (most recent call last):
86n/a ...
87n/a ValueError: expected parenthesized list: '-bar'
88n/a
89n/a >>> v = VersionPredicate('foo bar (12.21)')
90n/a Traceback (most recent call last):
91n/a ...
92n/a ValueError: expected parenthesized list: 'bar (12.21)'
93n/a
94n/a """
95n/a
96n/a def __init__(self, versionPredicateStr):
97n/a """Parse a version predicate string.
98n/a """
99n/a # Fields:
100n/a # name: package name
101n/a # pred: list of (comparison string, StrictVersion)
102n/a
103n/a versionPredicateStr = versionPredicateStr.strip()
104n/a if not versionPredicateStr:
105n/a raise ValueError("empty package restriction")
106n/a match = re_validPackage.match(versionPredicateStr)
107n/a if not match:
108n/a raise ValueError("bad package name in %r" % versionPredicateStr)
109n/a self.name, paren = match.groups()
110n/a paren = paren.strip()
111n/a if paren:
112n/a match = re_paren.match(paren)
113n/a if not match:
114n/a raise ValueError("expected parenthesized list: %r" % paren)
115n/a str = match.groups()[0]
116n/a self.pred = [splitUp(aPred) for aPred in str.split(",")]
117n/a if not self.pred:
118n/a raise ValueError("empty parenthesized list in %r"
119n/a % versionPredicateStr)
120n/a else:
121n/a self.pred = []
122n/a
123n/a def __str__(self):
124n/a if self.pred:
125n/a seq = [cond + " " + str(ver) for cond, ver in self.pred]
126n/a return self.name + " (" + ", ".join(seq) + ")"
127n/a else:
128n/a return self.name
129n/a
130n/a def satisfied_by(self, version):
131n/a """True if version is compatible with all the predicates in self.
132n/a The parameter version must be acceptable to the StrictVersion
133n/a constructor. It may be either a string or StrictVersion.
134n/a """
135n/a for cond, ver in self.pred:
136n/a if not compmap[cond](version, ver):
137n/a return False
138n/a return True
139n/a
140n/a
141n/a_provision_rx = None
142n/a
143n/adef split_provision(value):
144n/a """Return the name and optional version number of a provision.
145n/a
146n/a The version number, if given, will be returned as a `StrictVersion`
147n/a instance, otherwise it will be `None`.
148n/a
149n/a >>> split_provision('mypkg')
150n/a ('mypkg', None)
151n/a >>> split_provision(' mypkg( 1.2 ) ')
152n/a ('mypkg', StrictVersion ('1.2'))
153n/a """
154n/a global _provision_rx
155n/a if _provision_rx is None:
156n/a _provision_rx = re.compile(
157n/a r"([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$",
158n/a re.ASCII)
159n/a value = value.strip()
160n/a m = _provision_rx.match(value)
161n/a if not m:
162n/a raise ValueError("illegal provides specification: %r" % value)
163n/a ver = m.group(2) or None
164n/a if ver:
165n/a ver = distutils.version.StrictVersion(ver)
166n/a return m.group(1), ver