update
This commit is contained in:
@@ -8,41 +8,44 @@ To read project metadata, consider using
|
||||
For simple scenarios, you can also try parsing the file directly
|
||||
with the help of ``configparser``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import functools
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from functools import partial
|
||||
from functools import wraps
|
||||
from functools import partial, wraps
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Callable,
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Generic,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from packaging.markers import default_environment as marker_env
|
||||
from packaging.requirements import InvalidRequirement, Requirement
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from packaging.version import InvalidVersion, Version
|
||||
|
||||
from .._path import StrPath
|
||||
from ..errors import FileError, OptionError
|
||||
from ..extern.packaging.markers import default_environment as marker_env
|
||||
from ..extern.packaging.requirements import InvalidRequirement, Requirement
|
||||
from ..extern.packaging.specifiers import SpecifierSet
|
||||
from ..extern.packaging.version import InvalidVersion, Version
|
||||
from ..warnings import SetuptoolsDeprecationWarning
|
||||
from . import expand
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from distutils.dist import DistributionMetadata # noqa
|
||||
from setuptools.dist import Distribution
|
||||
|
||||
from setuptools.dist import Distribution # noqa
|
||||
from distutils.dist import DistributionMetadata
|
||||
|
||||
_Path = Union[str, os.PathLike]
|
||||
SingleCommandOptions = Dict["str", Tuple["str", Any]]
|
||||
"""Dict that associate the name of the options of a particular command to a
|
||||
tuple. The first element of the tuple indicates the origin of the option value
|
||||
@@ -54,7 +57,7 @@ Target = TypeVar("Target", bound=Union["Distribution", "DistributionMetadata"])
|
||||
|
||||
|
||||
def read_configuration(
|
||||
filepath: _Path, find_others=False, ignore_option_errors=False
|
||||
filepath: StrPath, find_others=False, ignore_option_errors=False
|
||||
) -> dict:
|
||||
"""Read given configuration file and returns options from it as a dict.
|
||||
|
||||
@@ -79,7 +82,7 @@ def read_configuration(
|
||||
return configuration_to_dict(handlers)
|
||||
|
||||
|
||||
def apply_configuration(dist: "Distribution", filepath: _Path) -> "Distribution":
|
||||
def apply_configuration(dist: Distribution, filepath: StrPath) -> Distribution:
|
||||
"""Apply the configuration from a ``setup.cfg`` file into an existing
|
||||
distribution object.
|
||||
"""
|
||||
@@ -89,11 +92,11 @@ def apply_configuration(dist: "Distribution", filepath: _Path) -> "Distribution"
|
||||
|
||||
|
||||
def _apply(
|
||||
dist: "Distribution",
|
||||
filepath: _Path,
|
||||
other_files: Iterable[_Path] = (),
|
||||
dist: Distribution,
|
||||
filepath: StrPath,
|
||||
other_files: Iterable[StrPath] = (),
|
||||
ignore_option_errors: bool = False,
|
||||
) -> Tuple["ConfigHandler", ...]:
|
||||
) -> tuple[ConfigHandler, ...]:
|
||||
"""Read configuration from ``filepath`` and applies to the ``dist`` object."""
|
||||
from setuptools.dist import _Distribution
|
||||
|
||||
@@ -107,7 +110,8 @@ def _apply(
|
||||
filenames = [*other_files, filepath]
|
||||
|
||||
try:
|
||||
_Distribution.parse_config_files(dist, filenames=filenames)
|
||||
# TODO: Temporary cast until mypy 1.12 is released with upstream fixes from typeshed
|
||||
_Distribution.parse_config_files(dist, filenames=cast(List[str], filenames))
|
||||
handlers = parse_configuration(
|
||||
dist, dist.command_options, ignore_option_errors=ignore_option_errors
|
||||
)
|
||||
@@ -130,7 +134,7 @@ def _get_option(target_obj: Target, key: str):
|
||||
return getter()
|
||||
|
||||
|
||||
def configuration_to_dict(handlers: Tuple["ConfigHandler", ...]) -> dict:
|
||||
def configuration_to_dict(handlers: tuple[ConfigHandler, ...]) -> dict:
|
||||
"""Returns configuration data gathered by given handlers as a dict.
|
||||
|
||||
:param list[ConfigHandler] handlers: Handlers list,
|
||||
@@ -149,10 +153,10 @@ def configuration_to_dict(handlers: Tuple["ConfigHandler", ...]) -> dict:
|
||||
|
||||
|
||||
def parse_configuration(
|
||||
distribution: "Distribution",
|
||||
distribution: Distribution,
|
||||
command_options: AllCommandOptions,
|
||||
ignore_option_errors=False,
|
||||
) -> Tuple["ConfigMetadataHandler", "ConfigOptionsHandler"]:
|
||||
) -> tuple[ConfigMetadataHandler, ConfigOptionsHandler]:
|
||||
"""Performs additional parsing of configuration options
|
||||
for a distribution.
|
||||
|
||||
@@ -235,7 +239,7 @@ class ConfigHandler(Generic[Target]):
|
||||
|
||||
"""
|
||||
|
||||
aliases: Dict[str, str] = {}
|
||||
aliases: dict[str, str] = {}
|
||||
"""Options aliases.
|
||||
For compatibility with various packages. E.g.: d2to1 and pbr.
|
||||
Note: `-` in keys is replaced with `_` by config parser.
|
||||
@@ -252,15 +256,17 @@ class ConfigHandler(Generic[Target]):
|
||||
self.ignore_option_errors = ignore_option_errors
|
||||
self.target_obj = target_obj
|
||||
self.sections = dict(self._section_options(options))
|
||||
self.set_options: List[str] = []
|
||||
self.set_options: list[str] = []
|
||||
self.ensure_discovered = ensure_discovered
|
||||
self._referenced_files: Set[str] = set()
|
||||
self._referenced_files: set[str] = set()
|
||||
"""After parsing configurations, this property will enumerate
|
||||
all files referenced by the "file:" directive. Private API for setuptools only.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _section_options(cls, options: AllCommandOptions):
|
||||
def _section_options(
|
||||
cls, options: AllCommandOptions
|
||||
) -> Iterator[tuple[str, SingleCommandOptions]]:
|
||||
for full_name, value in options.items():
|
||||
pre, sep, name = full_name.partition(cls.section_prefix)
|
||||
if pre:
|
||||
@@ -274,7 +280,7 @@ class ConfigHandler(Generic[Target]):
|
||||
'%s must provide .parsers property' % self.__class__.__name__
|
||||
)
|
||||
|
||||
def __setitem__(self, option_name, value):
|
||||
def __setitem__(self, option_name, value) -> None:
|
||||
target_obj = self.target_obj
|
||||
|
||||
# Translate alias into real name.
|
||||
@@ -282,8 +288,8 @@ class ConfigHandler(Generic[Target]):
|
||||
|
||||
try:
|
||||
current_value = getattr(target_obj, option_name)
|
||||
except AttributeError:
|
||||
raise KeyError(option_name)
|
||||
except AttributeError as e:
|
||||
raise KeyError(option_name) from e
|
||||
|
||||
if current_value:
|
||||
# Already inhabited. Skipping.
|
||||
@@ -370,7 +376,7 @@ class ConfigHandler(Generic[Target]):
|
||||
|
||||
return parser
|
||||
|
||||
def _parse_file(self, value, root_dir: _Path):
|
||||
def _parse_file(self, value, root_dir: StrPath):
|
||||
"""Represents value as a string, allowing including text
|
||||
from nearest files using `file:` directive.
|
||||
|
||||
@@ -396,7 +402,7 @@ class ConfigHandler(Generic[Target]):
|
||||
self._referenced_files.update(filepaths)
|
||||
return expand.read_files(filepaths, root_dir)
|
||||
|
||||
def _parse_attr(self, value, package_dir, root_dir: _Path):
|
||||
def _parse_attr(self, value, package_dir, root_dir: StrPath):
|
||||
"""Represents value as a module attribute.
|
||||
|
||||
Examples:
|
||||
@@ -474,7 +480,7 @@ class ConfigHandler(Generic[Target]):
|
||||
# Keep silent for a new option may appear anytime.
|
||||
self[name] = value
|
||||
|
||||
def parse(self):
|
||||
def parse(self) -> None:
|
||||
"""Parses configuration file items from one
|
||||
or more related sections.
|
||||
|
||||
@@ -484,7 +490,7 @@ class ConfigHandler(Generic[Target]):
|
||||
if section_name: # [section.option] variant
|
||||
method_postfix = '_%s' % section_name
|
||||
|
||||
section_parser_method: Optional[Callable] = getattr(
|
||||
section_parser_method: Callable | None = getattr(
|
||||
self,
|
||||
# Dots in section names are translated into dunderscores.
|
||||
('parse_section%s' % method_postfix).replace('.', '__'),
|
||||
@@ -533,12 +539,12 @@ class ConfigMetadataHandler(ConfigHandler["DistributionMetadata"]):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
target_obj: "DistributionMetadata",
|
||||
target_obj: DistributionMetadata,
|
||||
options: AllCommandOptions,
|
||||
ignore_option_errors: bool,
|
||||
ensure_discovered: expand.EnsurePackagesDiscovered,
|
||||
package_dir: Optional[dict] = None,
|
||||
root_dir: _Path = os.curdir,
|
||||
package_dir: dict | None = None,
|
||||
root_dir: StrPath = os.curdir,
|
||||
):
|
||||
super().__init__(target_obj, options, ignore_option_errors, ensure_discovered)
|
||||
self.package_dir = package_dir
|
||||
@@ -556,23 +562,9 @@ class ConfigMetadataHandler(ConfigHandler["DistributionMetadata"]):
|
||||
'platforms': parse_list,
|
||||
'keywords': parse_list,
|
||||
'provides': parse_list,
|
||||
'requires': self._deprecated_config_handler(
|
||||
parse_list,
|
||||
"The requires parameter is deprecated, please use "
|
||||
"install_requires for runtime dependencies.",
|
||||
due_date=(2023, 10, 30),
|
||||
# Warning introduced in 27 Oct 2018
|
||||
),
|
||||
'obsoletes': parse_list,
|
||||
'classifiers': self._get_parser_compound(parse_file, parse_list),
|
||||
'license': exclude_files_parser('license'),
|
||||
'license_file': self._deprecated_config_handler(
|
||||
exclude_files_parser('license_file'),
|
||||
"The license_file parameter is deprecated, "
|
||||
"use license_files instead.",
|
||||
due_date=(2023, 10, 30),
|
||||
# Warning introduced in 23 May 2021
|
||||
),
|
||||
'license_files': parse_list,
|
||||
'description': parse_file,
|
||||
'long_description': parse_file,
|
||||
@@ -595,11 +587,11 @@ class ConfigMetadataHandler(ConfigHandler["DistributionMetadata"]):
|
||||
# accidentally include newlines and other unintended content
|
||||
try:
|
||||
Version(version)
|
||||
except InvalidVersion:
|
||||
except InvalidVersion as e:
|
||||
raise OptionError(
|
||||
f'Version loaded from {value} does not '
|
||||
f'comply with PEP 440: {version}'
|
||||
)
|
||||
) from e
|
||||
|
||||
return version
|
||||
|
||||
@@ -611,14 +603,14 @@ class ConfigOptionsHandler(ConfigHandler["Distribution"]):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
target_obj: "Distribution",
|
||||
target_obj: Distribution,
|
||||
options: AllCommandOptions,
|
||||
ignore_option_errors: bool,
|
||||
ensure_discovered: expand.EnsurePackagesDiscovered,
|
||||
):
|
||||
super().__init__(target_obj, options, ignore_option_errors, ensure_discovered)
|
||||
self.root_dir = target_obj.src_root
|
||||
self.package_dir: Dict[str, str] = {} # To be filled by `find_packages`
|
||||
self.package_dir: dict[str, str] = {} # To be filled by `find_packages`
|
||||
|
||||
@classmethod
|
||||
def _parse_list_semicolon(cls, value):
|
||||
@@ -660,7 +652,6 @@ class ConfigOptionsHandler(ConfigHandler["Distribution"]):
|
||||
self._parse_requirements_list, "install_requires"
|
||||
),
|
||||
'setup_requires': self._parse_list_semicolon,
|
||||
'tests_require': self._parse_list_semicolon,
|
||||
'packages': self._parse_packages,
|
||||
'entry_points': self._parse_file_in_root,
|
||||
'py_modules': parse_list,
|
||||
@@ -708,9 +699,9 @@ class ConfigOptionsHandler(ConfigHandler["Distribution"]):
|
||||
|
||||
valid_keys = ['where', 'include', 'exclude']
|
||||
|
||||
find_kwargs = dict(
|
||||
[(k, v) for k, v in section_data.items() if k in valid_keys and v]
|
||||
)
|
||||
find_kwargs = dict([
|
||||
(k, v) for k, v in section_data.items() if k in valid_keys and v
|
||||
])
|
||||
|
||||
where = find_kwargs.get('where')
|
||||
if where is not None:
|
||||
|
||||
Reference in New Issue
Block a user