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) |
