Buckets:
| ####################################################################################### | |
| # | |
| # Adapted from: | |
| # https://github.com/pypa/hatch/blob/5352e44/backend/src/hatchling/licenses/parse.py | |
| # | |
| # MIT License | |
| # | |
| # Copyright (c) 2017-present Ofek Lev <oss@ofek.dev> | |
| # | |
| # Permission is hereby granted, free of charge, to any person obtaining a copy of this | |
| # software and associated documentation files (the "Software"), to deal in the Software | |
| # without restriction, including without limitation the rights to use, copy, modify, | |
| # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to | |
| # permit persons to whom the Software is furnished to do so, subject to the following | |
| # conditions: | |
| # | |
| # The above copyright notice and this permission notice shall be included in all copies | |
| # or substantial portions of the Software. | |
| # | |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |
| # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |
| # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
| # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | |
| # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| # | |
| # | |
| # With additional allowance of arbitrary `LicenseRef-` identifiers, not just | |
| # `LicenseRef-Public-Domain` and `LicenseRef-Proprietary`. | |
| # | |
| ####################################################################################### | |
| from __future__ import annotations | |
| import re | |
| from typing import NewType, cast | |
| from pip._vendor.packaging.licenses._spdx import EXCEPTIONS, LICENSES | |
| __all__ = [ | |
| "InvalidLicenseExpression", | |
| "NormalizedLicenseExpression", | |
| "canonicalize_license_expression", | |
| ] | |
| license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$") | |
| NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str) | |
| class InvalidLicenseExpression(ValueError): | |
| """Raised when a license-expression string is invalid | |
| >>> canonicalize_license_expression("invalid") | |
| Traceback (most recent call last): | |
| ... | |
| packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid' | |
| """ | |
| def canonicalize_license_expression( | |
| raw_license_expression: str, | |
| ) -> NormalizedLicenseExpression: | |
| if not raw_license_expression: | |
| message = f"Invalid license expression: {raw_license_expression!r}" | |
| raise InvalidLicenseExpression(message) | |
| # Pad any parentheses so tokenization can be achieved by merely splitting on | |
| # whitespace. | |
| license_expression = raw_license_expression.replace("(", " ( ").replace(")", " ) ") | |
| licenseref_prefix = "LicenseRef-" | |
| license_refs = { | |
| ref.lower(): "LicenseRef-" + ref[len(licenseref_prefix) :] | |
| for ref in license_expression.split() | |
| if ref.lower().startswith(licenseref_prefix.lower()) | |
| } | |
| # Normalize to lower case so we can look up licenses/exceptions | |
| # and so boolean operators are Python-compatible. | |
| license_expression = license_expression.lower() | |
| tokens = license_expression.split() | |
| # Rather than implementing boolean logic, we create an expression that Python can | |
| # parse. Everything that is not involved with the grammar itself is treated as | |
| # `False` and the expression should evaluate as such. | |
| python_tokens = [] | |
| for token in tokens: | |
| if token not in {"or", "and", "with", "(", ")"}: | |
| python_tokens.append("False") | |
| elif token == "with": | |
| python_tokens.append("or") | |
| elif token == "(" and python_tokens and python_tokens[-1] not in {"or", "and"}: | |
| message = f"Invalid license expression: {raw_license_expression!r}" | |
| raise InvalidLicenseExpression(message) | |
| else: | |
| python_tokens.append(token) | |
| python_expression = " ".join(python_tokens) | |
| try: | |
| invalid = eval(python_expression, globals(), locals()) | |
| except Exception: | |
| invalid = True | |
| if invalid is not False: | |
| message = f"Invalid license expression: {raw_license_expression!r}" | |
| raise InvalidLicenseExpression(message) from None | |
| # Take a final pass to check for unknown licenses/exceptions. | |
| normalized_tokens = [] | |
| for token in tokens: | |
| if token in {"or", "and", "with", "(", ")"}: | |
| normalized_tokens.append(token.upper()) | |
| continue | |
| if normalized_tokens and normalized_tokens[-1] == "WITH": | |
| if token not in EXCEPTIONS: | |
| message = f"Unknown license exception: {token!r}" | |
| raise InvalidLicenseExpression(message) | |
| normalized_tokens.append(EXCEPTIONS[token]["id"]) | |
| else: | |
| if token.endswith("+"): | |
| final_token = token[:-1] | |
| suffix = "+" | |
| else: | |
| final_token = token | |
| suffix = "" | |
| if final_token.startswith("licenseref-"): | |
| if not license_ref_allowed.match(final_token): | |
| message = f"Invalid licenseref: {final_token!r}" | |
| raise InvalidLicenseExpression(message) | |
| normalized_tokens.append(license_refs[final_token] + suffix) | |
| else: | |
| if final_token not in LICENSES: | |
| message = f"Unknown license: {final_token!r}" | |
| raise InvalidLicenseExpression(message) | |
| normalized_tokens.append(LICENSES[final_token]["id"] + suffix) | |
| normalized_expression = " ".join(normalized_tokens) | |
| return cast( | |
| NormalizedLicenseExpression, | |
| normalized_expression.replace("( ", "(").replace(" )", ")"), | |
| ) | |
Xet Storage Details
- Size:
- 5.73 kB
- Xet hash:
- 0fd8e3cffe315d760dd32d2d662c3a0e8071949b1a2723e96da27c6253b2ee9e
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.