Voice et bot modif
This commit is contained in:
parent
189d56026b
commit
7333a22bcd
10774 changed files with 634644 additions and 933308 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -268,10 +268,18 @@ def _optional_dependencies(dist: Distribution, val: dict, _root_dir: StrPath | N
|
|||
def _ext_modules(dist: Distribution, val: list[dict]) -> list[Extension]:
|
||||
existing = dist.ext_modules or []
|
||||
args = ({k.replace("-", "_"): v for k, v in x.items()} for x in val)
|
||||
new = [Extension(**kw) for kw in args]
|
||||
new = (Extension(**_adjust_ext_attrs(kw)) for kw in args)
|
||||
return [*existing, *new]
|
||||
|
||||
|
||||
def _adjust_ext_attrs(attrs: dict) -> dict:
|
||||
# https://github.com/pypa/setuptools/issues/4810
|
||||
# In TOML there is no differentiation between tuples and lists,
|
||||
# and distutils requires tuples...
|
||||
attrs["define_macros"] = list(map(tuple, attrs.get("define_macros") or []))
|
||||
return attrs
|
||||
|
||||
|
||||
def _noop(_dist: Distribution, val: _T) -> _T:
|
||||
return val
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
The code contained in this directory was automatically generated using the
|
||||
following command:
|
||||
|
||||
python -m validate_pyproject.pre_compile --output-dir=setuptools/config/_validate_pyproject --enable-plugins setuptools distutils --very-verbose -t setuptools=setuptools/config/setuptools.schema.json -t distutils=setuptools/config/distutils.schema.json
|
||||
python -m validate_pyproject.pre_compile --output-dir=setuptools/config/_validate_pyproject --enable-plugins setuptools distutils --very-verbose -t distutils=setuptools/config/distutils.schema.json -t setuptools=setuptools/config/setuptools.schema.json
|
||||
|
||||
Please avoid changing it manually.
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
|
|
@ -6,7 +8,7 @@ import re
|
|||
import typing
|
||||
from contextlib import contextmanager
|
||||
from textwrap import indent, wrap
|
||||
from typing import Any, Dict, Generator, Iterator, List, Optional, Sequence, Union
|
||||
from typing import Any, Generator, Iterator, Sequence
|
||||
|
||||
from .fastjsonschema_exceptions import JsonSchemaValueException
|
||||
|
||||
|
|
@ -36,7 +38,7 @@ _SKIP_DETAILS = (
|
|||
_NEED_DETAILS = {"anyOf", "oneOf", "allOf", "contains", "propertyNames", "not", "items"}
|
||||
|
||||
_CAMEL_CASE_SPLITTER = re.compile(r"\W+|([A-Z][^A-Z\W]*)")
|
||||
_IDENTIFIER = re.compile(r"^[\w_]+$", re.I)
|
||||
_IDENTIFIER = re.compile(r"^[\w_]+$", re.IGNORECASE)
|
||||
|
||||
_TOML_JARGON = {
|
||||
"object": "table",
|
||||
|
|
@ -73,7 +75,7 @@ class ValidationError(JsonSchemaValueException):
|
|||
_original_message = ""
|
||||
|
||||
@classmethod
|
||||
def _from_jsonschema(cls, ex: JsonSchemaValueException) -> "Self":
|
||||
def _from_jsonschema(cls, ex: JsonSchemaValueException) -> Self:
|
||||
formatter = _ErrorFormatting(ex)
|
||||
obj = cls(str(formatter), ex.value, formatter.name, ex.definition, ex.rule)
|
||||
debug_code = os.getenv("JSONSCHEMA_DEBUG_CODE_GENERATION", "false").lower()
|
||||
|
|
@ -173,8 +175,8 @@ class _ErrorFormatting:
|
|||
class _SummaryWriter:
|
||||
_IGNORE = frozenset(("description", "default", "title", "examples"))
|
||||
|
||||
def __init__(self, jargon: Optional[Dict[str, str]] = None):
|
||||
self.jargon: Dict[str, str] = jargon or {}
|
||||
def __init__(self, jargon: dict[str, str] | None = None):
|
||||
self.jargon: dict[str, str] = jargon or {}
|
||||
# Clarify confusing terms
|
||||
self._terms = {
|
||||
"anyOf": "at least one of the following",
|
||||
|
|
@ -207,14 +209,14 @@ class _SummaryWriter:
|
|||
"multipleOf",
|
||||
]
|
||||
|
||||
def _jargon(self, term: Union[str, List[str]]) -> Union[str, List[str]]:
|
||||
def _jargon(self, term: str | list[str]) -> str | list[str]:
|
||||
if isinstance(term, list):
|
||||
return [self.jargon.get(t, t) for t in term]
|
||||
return self.jargon.get(term, term)
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
schema: Union[dict, List[dict]],
|
||||
schema: dict | list[dict],
|
||||
prefix: str = "",
|
||||
*,
|
||||
_path: Sequence[str] = (),
|
||||
|
|
@ -261,15 +263,15 @@ class _SummaryWriter:
|
|||
return any(key.startswith(k) for k in "$_") or key in self._IGNORE
|
||||
|
||||
def _filter_unecessary(
|
||||
self, schema: Dict[str, Any], path: Sequence[str]
|
||||
) -> Dict[str, Any]:
|
||||
self, schema: dict[str, Any], path: Sequence[str]
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
key: value
|
||||
for key, value in schema.items()
|
||||
if not self._is_unecessary([*path, key])
|
||||
}
|
||||
|
||||
def _handle_simple_dict(self, value: dict, path: Sequence[str]) -> Optional[str]:
|
||||
def _handle_simple_dict(self, value: dict, path: Sequence[str]) -> str | None:
|
||||
inline = any(p in value for p in self._guess_inline_defs)
|
||||
simple = not any(isinstance(v, (list, dict)) for v in value.values())
|
||||
if inline or simple:
|
||||
|
|
@ -328,7 +330,7 @@ class _SummaryWriter:
|
|||
return len(parent_prefix) * " " + child_prefix
|
||||
|
||||
|
||||
def _separate_terms(word: str) -> List[str]:
|
||||
def _separate_terms(word: str) -> list[str]:
|
||||
"""
|
||||
>>> _separate_terms("FooBar-foo")
|
||||
['foo', 'bar', 'foo']
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ difficult to express as a JSON Schema (or that are not supported by the current
|
|||
JSON Schema library).
|
||||
"""
|
||||
|
||||
import collections
|
||||
import itertools
|
||||
from inspect import cleandoc
|
||||
from typing import Mapping, TypeVar
|
||||
from typing import Generator, Iterable, Mapping, TypeVar
|
||||
|
||||
from .error_reporting import ValidationError
|
||||
|
||||
|
|
@ -19,8 +21,7 @@ class RedefiningStaticFieldAsDynamic(ValidationError):
|
|||
"""
|
||||
__doc__ = _DESC
|
||||
_URL = (
|
||||
"https://packaging.python.org/en/latest/specifications/"
|
||||
"pyproject-toml/#dynamic"
|
||||
"https://packaging.python.org/en/latest/specifications/pyproject-toml/#dynamic"
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -31,6 +32,24 @@ class IncludedDependencyGroupMustExist(ValidationError):
|
|||
_URL = "https://peps.python.org/pep-0735/"
|
||||
|
||||
|
||||
class ImportNameCollision(ValidationError):
|
||||
_DESC = """According to PEP 794:
|
||||
|
||||
All import-names and import-namespaces items must be unique.
|
||||
"""
|
||||
__doc__ = _DESC
|
||||
_URL = "https://peps.python.org/pep-0794/"
|
||||
|
||||
|
||||
class ImportNameMissing(ValidationError):
|
||||
_DESC = """According to PEP 794:
|
||||
|
||||
An import name must have all parents listed.
|
||||
"""
|
||||
__doc__ = _DESC
|
||||
_URL = "https://peps.python.org/pep-0794/"
|
||||
|
||||
|
||||
def validate_project_dynamic(pyproject: T) -> T:
|
||||
project_table = pyproject.get("project", {})
|
||||
dynamic = project_table.get("dynamic", [])
|
||||
|
|
@ -79,4 +98,54 @@ def validate_include_depenency(pyproject: T) -> T:
|
|||
return pyproject
|
||||
|
||||
|
||||
EXTRA_VALIDATIONS = (validate_project_dynamic, validate_include_depenency)
|
||||
def _remove_private(items: Iterable[str]) -> Generator[str, None, None]:
|
||||
for item in items:
|
||||
yield item.partition(";")[0].rstrip()
|
||||
|
||||
|
||||
def validate_import_name_issues(pyproject: T) -> T:
|
||||
project = pyproject.get("project", {})
|
||||
import_names = collections.Counter(_remove_private(project.get("import-names", [])))
|
||||
import_namespaces = collections.Counter(
|
||||
_remove_private(project.get("import-namespaces", []))
|
||||
)
|
||||
|
||||
duplicated = [k for k, v in (import_names + import_namespaces).items() if v > 1]
|
||||
|
||||
if duplicated:
|
||||
raise ImportNameCollision(
|
||||
message="Duplicated names are not allowed in import-names/import-namespaces",
|
||||
value=duplicated,
|
||||
name="data.project.importnames(paces)",
|
||||
definition={
|
||||
"description": cleandoc(ImportNameCollision._DESC),
|
||||
"see": ImportNameCollision._URL,
|
||||
},
|
||||
rule="PEP 794",
|
||||
)
|
||||
|
||||
names = frozenset(import_names + import_namespaces)
|
||||
for name in names:
|
||||
for parent in itertools.accumulate(
|
||||
name.split(".")[:-1], lambda a, b: f"{a}.{b}"
|
||||
):
|
||||
if parent not in names:
|
||||
raise ImportNameMissing(
|
||||
message="All parents of an import name must also be listed in import-namespace/import-names",
|
||||
value=name,
|
||||
name="data.project.importnames(paces)",
|
||||
definition={
|
||||
"description": cleandoc(ImportNameMissing._DESC),
|
||||
"see": ImportNameMissing._URL,
|
||||
},
|
||||
rule="PEP 794",
|
||||
)
|
||||
|
||||
return pyproject
|
||||
|
||||
|
||||
EXTRA_VALIDATIONS = (
|
||||
validate_project_dynamic,
|
||||
validate_include_depenency,
|
||||
validate_import_name_issues,
|
||||
)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -7,7 +7,9 @@ The correspondence is given by replacing the ``_`` character in the name of the
|
|||
function with a ``-`` to obtain the format name and vice versa.
|
||||
"""
|
||||
|
||||
import builtins
|
||||
from __future__ import annotations
|
||||
|
||||
import keyword
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
|
@ -16,6 +18,8 @@ import typing
|
|||
from itertools import chain as _chain
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
import builtins
|
||||
|
||||
from typing_extensions import Literal
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
|
@ -54,7 +58,9 @@ VERSION_PATTERN = r"""
|
|||
(?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
|
||||
"""
|
||||
|
||||
VERSION_REGEX = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.X | re.I)
|
||||
VERSION_REGEX = re.compile(
|
||||
r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE
|
||||
)
|
||||
|
||||
|
||||
def pep440(version: str) -> bool:
|
||||
|
|
@ -68,7 +74,7 @@ def pep440(version: str) -> bool:
|
|||
# PEP 508
|
||||
|
||||
PEP508_IDENTIFIER_PATTERN = r"([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])"
|
||||
PEP508_IDENTIFIER_REGEX = re.compile(f"^{PEP508_IDENTIFIER_PATTERN}$", re.I)
|
||||
PEP508_IDENTIFIER_REGEX = re.compile(f"^{PEP508_IDENTIFIER_PATTERN}$", re.IGNORECASE)
|
||||
|
||||
|
||||
def pep508_identifier(name: str) -> bool:
|
||||
|
|
@ -93,9 +99,9 @@ try:
|
|||
"""
|
||||
try:
|
||||
_req.Requirement(value)
|
||||
return True
|
||||
except _req.InvalidRequirement:
|
||||
return False
|
||||
return True
|
||||
|
||||
except ImportError: # pragma: no cover
|
||||
_logger.warning(
|
||||
|
|
@ -104,7 +110,7 @@ except ImportError: # pragma: no cover
|
|||
"To enforce validation, please install `packaging`."
|
||||
)
|
||||
|
||||
def pep508(value: str) -> bool:
|
||||
def pep508(value: str) -> bool: # noqa: ARG001
|
||||
return True
|
||||
|
||||
|
||||
|
|
@ -163,7 +169,7 @@ class _TroveClassifier:
|
|||
option (classifiers will be validated anyway during the upload to PyPI).
|
||||
"""
|
||||
|
||||
downloaded: typing.Union[None, "Literal[False]", typing.Set[str]]
|
||||
downloaded: None | Literal[False] | set[str]
|
||||
"""
|
||||
None => not cached yet
|
||||
False => unavailable
|
||||
|
|
@ -200,7 +206,7 @@ class _TroveClassifier:
|
|||
_logger.debug(msg)
|
||||
try:
|
||||
self.downloaded = set(_download_classifiers().splitlines())
|
||||
except Exception:
|
||||
except Exception: # noqa: BLE001
|
||||
self.downloaded = False
|
||||
_logger.debug("Problem with download, skipping validation")
|
||||
return True
|
||||
|
|
@ -253,21 +259,23 @@ def url(value: str) -> bool:
|
|||
"`scheme` prefix in your URL (e.g. 'http://'). "
|
||||
f"Given value: {value}"
|
||||
)
|
||||
if not (value.startswith("/") or value.startswith("\\") or "@" in value):
|
||||
if not (value.startswith(("/", "\\")) or "@" in value):
|
||||
parts = urlparse(f"http://{value}")
|
||||
|
||||
return bool(parts.scheme and parts.netloc)
|
||||
except Exception:
|
||||
except Exception: # noqa: BLE001
|
||||
return False
|
||||
|
||||
|
||||
# https://packaging.python.org/specifications/entry-points/
|
||||
ENTRYPOINT_PATTERN = r"[^\[\s=]([^=]*[^\s=])?"
|
||||
ENTRYPOINT_REGEX = re.compile(f"^{ENTRYPOINT_PATTERN}$", re.I)
|
||||
ENTRYPOINT_REGEX = re.compile(f"^{ENTRYPOINT_PATTERN}$", re.IGNORECASE)
|
||||
RECOMMEDED_ENTRYPOINT_PATTERN = r"[\w.-]+"
|
||||
RECOMMEDED_ENTRYPOINT_REGEX = re.compile(f"^{RECOMMEDED_ENTRYPOINT_PATTERN}$", re.I)
|
||||
RECOMMEDED_ENTRYPOINT_REGEX = re.compile(
|
||||
f"^{RECOMMEDED_ENTRYPOINT_PATTERN}$", re.IGNORECASE
|
||||
)
|
||||
ENTRYPOINT_GROUP_PATTERN = r"\w+(\.\w+)*"
|
||||
ENTRYPOINT_GROUP_REGEX = re.compile(f"^{ENTRYPOINT_GROUP_PATTERN}$", re.I)
|
||||
ENTRYPOINT_GROUP_REGEX = re.compile(f"^{ENTRYPOINT_GROUP_PATTERN}$", re.IGNORECASE)
|
||||
|
||||
|
||||
def python_identifier(value: str) -> bool:
|
||||
|
|
@ -368,11 +376,41 @@ def uint16(value: builtins.int) -> bool:
|
|||
return 0 <= value < 2**16
|
||||
|
||||
|
||||
def uint(value: builtins.int) -> bool:
|
||||
def uint32(value: builtins.int) -> bool:
|
||||
r"""Unsigned 32-bit integer (:math:`0 \leq x < 2^{32}`)"""
|
||||
return 0 <= value < 2**32
|
||||
|
||||
|
||||
def uint64(value: builtins.int) -> bool:
|
||||
r"""Unsigned 64-bit integer (:math:`0 \leq x < 2^{64}`)"""
|
||||
return 0 <= value < 2**64
|
||||
|
||||
|
||||
def uint(value: builtins.int) -> bool:
|
||||
r"""Signed 64-bit integer (:math:`0 \leq x < 2^{64}`)"""
|
||||
return 0 <= value < 2**64
|
||||
|
||||
|
||||
def int8(value: builtins.int) -> bool:
|
||||
r"""Signed 8-bit integer (:math:`-2^{7} \leq x < 2^{7}`)"""
|
||||
return -(2**7) <= value < 2**7
|
||||
|
||||
|
||||
def int16(value: builtins.int) -> bool:
|
||||
r"""Signed 16-bit integer (:math:`-2^{15} \leq x < 2^{15}`)"""
|
||||
return -(2**15) <= value < 2**15
|
||||
|
||||
|
||||
def int32(value: builtins.int) -> bool:
|
||||
r"""Signed 32-bit integer (:math:`-2^{31} \leq x < 2^{31}`)"""
|
||||
return -(2**31) <= value < 2**31
|
||||
|
||||
|
||||
def int64(value: builtins.int) -> bool:
|
||||
r"""Signed 64-bit integer (:math:`-2^{63} \leq x < 2^{63}`)"""
|
||||
return -(2**63) <= value < 2**63
|
||||
|
||||
|
||||
def int(value: builtins.int) -> bool:
|
||||
r"""Signed 64-bit integer (:math:`-2^{63} \leq x < 2^{63}`)"""
|
||||
return -(2**63) <= value < 2**63
|
||||
|
|
@ -387,9 +425,9 @@ try:
|
|||
"""
|
||||
try:
|
||||
_licenses.canonicalize_license_expression(value)
|
||||
return True
|
||||
except _licenses.InvalidLicenseExpression:
|
||||
return False
|
||||
return True
|
||||
|
||||
except ImportError: # pragma: no cover
|
||||
_logger.warning(
|
||||
|
|
@ -398,5 +436,29 @@ except ImportError: # pragma: no cover
|
|||
"To enforce validation, please install `packaging>=24.2`."
|
||||
)
|
||||
|
||||
def SPDX(value: str) -> bool:
|
||||
def SPDX(value: str) -> bool: # noqa: ARG001
|
||||
return True
|
||||
|
||||
|
||||
VALID_IMPORT_NAME = re.compile(
|
||||
r"""
|
||||
^ # start of string
|
||||
[A-Za-z_][A-Za-z_0-9]+ # a valid Python identifier
|
||||
(?:\.[A-Za-z_][A-Za-z_0-9]*)* # optionally followed by .identifier's
|
||||
(?:\s*;\s*private)? # optionally followed by ; private
|
||||
$ # end of string
|
||||
""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
|
||||
def import_name(value: str) -> bool:
|
||||
"""This is a valid import name. It has to be series of python identifiers
|
||||
(not keywords), separated by dots, optionally followed by a semicolon and
|
||||
the keyword "private".
|
||||
"""
|
||||
if VALID_IMPORT_NAME.match(value) is None:
|
||||
return False
|
||||
|
||||
idents, _, _ = value.partition(";")
|
||||
return all(not keyword.iskeyword(ident) for ident in idents.rstrip().split("."))
|
||||
|
|
|
|||
|
|
@ -134,6 +134,15 @@ def read_configuration(
|
|||
if "ext-modules" in setuptools_table:
|
||||
_ExperimentalConfiguration.emit(subject="[tool.setuptools.ext-modules]")
|
||||
|
||||
fields = ("import-names", "import-namespaces")
|
||||
places = (project_table, project_table.get("dynamic", []))
|
||||
if any(field in place for field in fields for place in places):
|
||||
raise NotImplementedError(
|
||||
"Setuptools does not support `import-names` and `import-namespaces`"
|
||||
" in `pyproject.toml` yet. If your are interested in this feature, "
|
||||
" please consider submitting a contribution via pull requests."
|
||||
)
|
||||
|
||||
with _ignore_errors(ignore_option_errors):
|
||||
# Don't complain about unrelated errors (e.g. tools not using the "tool" table)
|
||||
subset = {"project": project_table, "tool": {"setuptools": setuptools_table}}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@
|
|||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"propertyNames": {
|
||||
"anyOf": [{"type": "string", "format": "python-module-name"}, {"const": "*"}]
|
||||
"anyOf": [{"$ref": "#/definitions/package-name"}, {"const": "*"}]
|
||||
},
|
||||
"patternProperties": {
|
||||
"^.*$": {"type": "array", "items": {"type": "string"}}
|
||||
|
|
@ -140,7 +140,7 @@
|
|||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"propertyNames": {
|
||||
"anyOf": [{"type": "string", "format": "python-module-name"}, {"const": "*"}]
|
||||
"anyOf": [{"$ref": "#/definitions/package-name"}, {"const": "*"}]
|
||||
},
|
||||
"patternProperties": {
|
||||
"^.*$": {"type": "array", "items": {"type": "string"}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue