Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/packaging/markers.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
1 # This file is dual licensed under the terms of the Apache License, Version | |
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository | |
3 # for complete details. | |
4 from __future__ import absolute_import, division, print_function | |
5 | |
6 import operator | |
7 import os | |
8 import platform | |
9 import sys | |
10 | |
11 from pyparsing import ParseException, ParseResults, stringStart, stringEnd | |
12 from pyparsing import ZeroOrMore, Group, Forward, QuotedString | |
13 from pyparsing import Literal as L # noqa | |
14 | |
15 from ._compat import string_types | |
16 from ._typing import TYPE_CHECKING | |
17 from .specifiers import Specifier, InvalidSpecifier | |
18 | |
19 if TYPE_CHECKING: # pragma: no cover | |
20 from typing import Any, Callable, Dict, List, Optional, Tuple, Union | |
21 | |
22 Operator = Callable[[str, str], bool] | |
23 | |
24 | |
25 __all__ = [ | |
26 "InvalidMarker", | |
27 "UndefinedComparison", | |
28 "UndefinedEnvironmentName", | |
29 "Marker", | |
30 "default_environment", | |
31 ] | |
32 | |
33 | |
34 class InvalidMarker(ValueError): | |
35 """ | |
36 An invalid marker was found, users should refer to PEP 508. | |
37 """ | |
38 | |
39 | |
40 class UndefinedComparison(ValueError): | |
41 """ | |
42 An invalid operation was attempted on a value that doesn't support it. | |
43 """ | |
44 | |
45 | |
46 class UndefinedEnvironmentName(ValueError): | |
47 """ | |
48 A name was attempted to be used that does not exist inside of the | |
49 environment. | |
50 """ | |
51 | |
52 | |
53 class Node(object): | |
54 def __init__(self, value): | |
55 # type: (Any) -> None | |
56 self.value = value | |
57 | |
58 def __str__(self): | |
59 # type: () -> str | |
60 return str(self.value) | |
61 | |
62 def __repr__(self): | |
63 # type: () -> str | |
64 return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) | |
65 | |
66 def serialize(self): | |
67 # type: () -> str | |
68 raise NotImplementedError | |
69 | |
70 | |
71 class Variable(Node): | |
72 def serialize(self): | |
73 # type: () -> str | |
74 return str(self) | |
75 | |
76 | |
77 class Value(Node): | |
78 def serialize(self): | |
79 # type: () -> str | |
80 return '"{0}"'.format(self) | |
81 | |
82 | |
83 class Op(Node): | |
84 def serialize(self): | |
85 # type: () -> str | |
86 return str(self) | |
87 | |
88 | |
89 VARIABLE = ( | |
90 L("implementation_version") | |
91 | L("platform_python_implementation") | |
92 | L("implementation_name") | |
93 | L("python_full_version") | |
94 | L("platform_release") | |
95 | L("platform_version") | |
96 | L("platform_machine") | |
97 | L("platform_system") | |
98 | L("python_version") | |
99 | L("sys_platform") | |
100 | L("os_name") | |
101 | L("os.name") # PEP-345 | |
102 | L("sys.platform") # PEP-345 | |
103 | L("platform.version") # PEP-345 | |
104 | L("platform.machine") # PEP-345 | |
105 | L("platform.python_implementation") # PEP-345 | |
106 | L("python_implementation") # undocumented setuptools legacy | |
107 | L("extra") # PEP-508 | |
108 ) | |
109 ALIASES = { | |
110 "os.name": "os_name", | |
111 "sys.platform": "sys_platform", | |
112 "platform.version": "platform_version", | |
113 "platform.machine": "platform_machine", | |
114 "platform.python_implementation": "platform_python_implementation", | |
115 "python_implementation": "platform_python_implementation", | |
116 } | |
117 VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) | |
118 | |
119 VERSION_CMP = ( | |
120 L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<") | |
121 ) | |
122 | |
123 MARKER_OP = VERSION_CMP | L("not in") | L("in") | |
124 MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) | |
125 | |
126 MARKER_VALUE = QuotedString("'") | QuotedString('"') | |
127 MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) | |
128 | |
129 BOOLOP = L("and") | L("or") | |
130 | |
131 MARKER_VAR = VARIABLE | MARKER_VALUE | |
132 | |
133 MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) | |
134 MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) | |
135 | |
136 LPAREN = L("(").suppress() | |
137 RPAREN = L(")").suppress() | |
138 | |
139 MARKER_EXPR = Forward() | |
140 MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) | |
141 MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) | |
142 | |
143 MARKER = stringStart + MARKER_EXPR + stringEnd | |
144 | |
145 | |
146 def _coerce_parse_result(results): | |
147 # type: (Union[ParseResults, List[Any]]) -> List[Any] | |
148 if isinstance(results, ParseResults): | |
149 return [_coerce_parse_result(i) for i in results] | |
150 else: | |
151 return results | |
152 | |
153 | |
154 def _format_marker(marker, first=True): | |
155 # type: (Union[List[str], Tuple[Node, ...], str], Optional[bool]) -> str | |
156 | |
157 assert isinstance(marker, (list, tuple, string_types)) | |
158 | |
159 # Sometimes we have a structure like [[...]] which is a single item list | |
160 # where the single item is itself it's own list. In that case we want skip | |
161 # the rest of this function so that we don't get extraneous () on the | |
162 # outside. | |
163 if ( | |
164 isinstance(marker, list) | |
165 and len(marker) == 1 | |
166 and isinstance(marker[0], (list, tuple)) | |
167 ): | |
168 return _format_marker(marker[0]) | |
169 | |
170 if isinstance(marker, list): | |
171 inner = (_format_marker(m, first=False) for m in marker) | |
172 if first: | |
173 return " ".join(inner) | |
174 else: | |
175 return "(" + " ".join(inner) + ")" | |
176 elif isinstance(marker, tuple): | |
177 return " ".join([m.serialize() for m in marker]) | |
178 else: | |
179 return marker | |
180 | |
181 | |
182 _operators = { | |
183 "in": lambda lhs, rhs: lhs in rhs, | |
184 "not in": lambda lhs, rhs: lhs not in rhs, | |
185 "<": operator.lt, | |
186 "<=": operator.le, | |
187 "==": operator.eq, | |
188 "!=": operator.ne, | |
189 ">=": operator.ge, | |
190 ">": operator.gt, | |
191 } # type: Dict[str, Operator] | |
192 | |
193 | |
194 def _eval_op(lhs, op, rhs): | |
195 # type: (str, Op, str) -> bool | |
196 try: | |
197 spec = Specifier("".join([op.serialize(), rhs])) | |
198 except InvalidSpecifier: | |
199 pass | |
200 else: | |
201 return spec.contains(lhs) | |
202 | |
203 oper = _operators.get(op.serialize()) # type: Optional[Operator] | |
204 if oper is None: | |
205 raise UndefinedComparison( | |
206 "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) | |
207 ) | |
208 | |
209 return oper(lhs, rhs) | |
210 | |
211 | |
212 class Undefined(object): | |
213 pass | |
214 | |
215 | |
216 _undefined = Undefined() | |
217 | |
218 | |
219 def _get_env(environment, name): | |
220 # type: (Dict[str, str], str) -> str | |
221 value = environment.get(name, _undefined) # type: Union[str, Undefined] | |
222 | |
223 if isinstance(value, Undefined): | |
224 raise UndefinedEnvironmentName( | |
225 "{0!r} does not exist in evaluation environment.".format(name) | |
226 ) | |
227 | |
228 return value | |
229 | |
230 | |
231 def _evaluate_markers(markers, environment): | |
232 # type: (List[Any], Dict[str, str]) -> bool | |
233 groups = [[]] # type: List[List[bool]] | |
234 | |
235 for marker in markers: | |
236 assert isinstance(marker, (list, tuple, string_types)) | |
237 | |
238 if isinstance(marker, list): | |
239 groups[-1].append(_evaluate_markers(marker, environment)) | |
240 elif isinstance(marker, tuple): | |
241 lhs, op, rhs = marker | |
242 | |
243 if isinstance(lhs, Variable): | |
244 lhs_value = _get_env(environment, lhs.value) | |
245 rhs_value = rhs.value | |
246 else: | |
247 lhs_value = lhs.value | |
248 rhs_value = _get_env(environment, rhs.value) | |
249 | |
250 groups[-1].append(_eval_op(lhs_value, op, rhs_value)) | |
251 else: | |
252 assert marker in ["and", "or"] | |
253 if marker == "or": | |
254 groups.append([]) | |
255 | |
256 return any(all(item) for item in groups) | |
257 | |
258 | |
259 def format_full_version(info): | |
260 # type: (sys._version_info) -> str | |
261 version = "{0.major}.{0.minor}.{0.micro}".format(info) | |
262 kind = info.releaselevel | |
263 if kind != "final": | |
264 version += kind[0] + str(info.serial) | |
265 return version | |
266 | |
267 | |
268 def default_environment(): | |
269 # type: () -> Dict[str, str] | |
270 if hasattr(sys, "implementation"): | |
271 # Ignoring the `sys.implementation` reference for type checking due to | |
272 # mypy not liking that the attribute doesn't exist in Python 2.7 when | |
273 # run with the `--py27` flag. | |
274 iver = format_full_version(sys.implementation.version) # type: ignore | |
275 implementation_name = sys.implementation.name # type: ignore | |
276 else: | |
277 iver = "0" | |
278 implementation_name = "" | |
279 | |
280 return { | |
281 "implementation_name": implementation_name, | |
282 "implementation_version": iver, | |
283 "os_name": os.name, | |
284 "platform_machine": platform.machine(), | |
285 "platform_release": platform.release(), | |
286 "platform_system": platform.system(), | |
287 "platform_version": platform.version(), | |
288 "python_full_version": platform.python_version(), | |
289 "platform_python_implementation": platform.python_implementation(), | |
290 "python_version": ".".join(platform.python_version_tuple()[:2]), | |
291 "sys_platform": sys.platform, | |
292 } | |
293 | |
294 | |
295 class Marker(object): | |
296 def __init__(self, marker): | |
297 # type: (str) -> None | |
298 try: | |
299 self._markers = _coerce_parse_result(MARKER.parseString(marker)) | |
300 except ParseException as e: | |
301 err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( | |
302 marker, marker[e.loc : e.loc + 8] | |
303 ) | |
304 raise InvalidMarker(err_str) | |
305 | |
306 def __str__(self): | |
307 # type: () -> str | |
308 return _format_marker(self._markers) | |
309 | |
310 def __repr__(self): | |
311 # type: () -> str | |
312 return "<Marker({0!r})>".format(str(self)) | |
313 | |
314 def evaluate(self, environment=None): | |
315 # type: (Optional[Dict[str, str]]) -> bool | |
316 """Evaluate a marker. | |
317 | |
318 Return the boolean from evaluating the given marker against the | |
319 environment. environment is an optional argument to override all or | |
320 part of the determined environment. | |
321 | |
322 The environment is determined from the current Python process. | |
323 """ | |
324 current_environment = default_environment() | |
325 if environment is not None: | |
326 current_environment.update(environment) | |
327 | |
328 return _evaluate_markers(self._markers, current_environment) |