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