aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-03-28 11:49:43 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-03-28 11:59:36 +0300
commit4900300c1bfd2592c46ab2ff17bf007b3b502a77 (patch)
tree139bfa0aa47c21744d3dab91e8283f0ba5b608a6
parentc4e006fc945df7b2c1ff8c507943c2d1154f7a1e (diff)
downloadydb-4900300c1bfd2592c46ab2ff17bf007b3b502a77.tar.gz
Intermediate changes
-rw-r--r--contrib/python/setuptools/py3/.dist-info/METADATA8
-rw-r--r--contrib/python/setuptools/py3/pkg_resources/__init__.py68
-rw-r--r--contrib/python/setuptools/py3/setuptools/__init__.py11
-rw-r--r--contrib/python/setuptools/py3/setuptools/_core_metadata.py2
-rw-r--r--contrib/python/setuptools/py3/setuptools/_normalization.py4
-rw-r--r--contrib/python/setuptools/py3/setuptools/_path.py9
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/_requirestxt.py2
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/build_ext.py13
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/dist_info.py4
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/easy_install.py41
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/editable_wheel.py70
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/install.py5
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/rotate.py3
-rw-r--r--contrib/python/setuptools/py3/setuptools/command/upload_docs.py2
-rw-r--r--contrib/python/setuptools/py3/setuptools/compat/py39.py9
-rw-r--r--contrib/python/setuptools/py3/setuptools/config/_apply_pyprojecttoml.py22
-rw-r--r--contrib/python/setuptools/py3/setuptools/config/_validate_pyproject/fastjsonschema_validations.py1
-rw-r--r--contrib/python/setuptools/py3/setuptools/config/expand.py33
-rw-r--r--contrib/python/setuptools/py3/setuptools/config/pyprojecttoml.py21
-rw-r--r--contrib/python/setuptools/py3/setuptools/config/setupcfg.py20
-rw-r--r--contrib/python/setuptools/py3/setuptools/discovery.py29
-rw-r--r--contrib/python/setuptools/py3/setuptools/dist.py18
-rw-r--r--contrib/python/setuptools/py3/setuptools/extension.py8
-rw-r--r--contrib/python/setuptools/py3/setuptools/monkey.py7
-rw-r--r--contrib/python/setuptools/py3/setuptools/msvc.py6
-rw-r--r--contrib/python/setuptools/py3/setuptools/namespaces.py5
-rw-r--r--contrib/python/setuptools/py3/setuptools/sandbox.py13
-rw-r--r--contrib/python/setuptools/py3/ya.make3
28 files changed, 246 insertions, 191 deletions
diff --git a/contrib/python/setuptools/py3/.dist-info/METADATA b/contrib/python/setuptools/py3/.dist-info/METADATA
index 237cc66f13..3ccc19e703 100644
--- a/contrib/python/setuptools/py3/.dist-info/METADATA
+++ b/contrib/python/setuptools/py3/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: setuptools
-Version: 69.1.1
+Version: 69.2.0
Summary: Easily download, build, install, upgrade, and uninstall Python packages
Home-page: https://github.com/pypa/setuptools
Author: Python Packaging Authority
@@ -39,13 +39,12 @@ Provides-Extra: testing
Requires-Dist: pytest >=6 ; extra == 'testing'
Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'testing'
Requires-Dist: pytest-enabler >=2.2 ; extra == 'testing'
-Requires-Dist: flake8-2020 ; extra == 'testing'
Requires-Dist: virtualenv >=13.0.0 ; extra == 'testing'
Requires-Dist: wheel ; extra == 'testing'
Requires-Dist: pip >=19.1 ; extra == 'testing'
Requires-Dist: packaging >=23.2 ; extra == 'testing'
Requires-Dist: jaraco.envs >=2.2 ; extra == 'testing'
-Requires-Dist: pytest-xdist ; extra == 'testing'
+Requires-Dist: pytest-xdist >=3 ; extra == 'testing'
Requires-Dist: jaraco.path >=3.2.0 ; extra == 'testing'
Requires-Dist: build[virtualenv] ; extra == 'testing'
Requires-Dist: filelock >=3.4.0 ; extra == 'testing'
@@ -53,6 +52,9 @@ Requires-Dist: ini2toml[lite] >=0.9 ; extra == 'testing'
Requires-Dist: tomli-w >=1.0.0 ; extra == 'testing'
Requires-Dist: pytest-timeout ; extra == 'testing'
Requires-Dist: pytest-home >=0.5 ; extra == 'testing'
+Requires-Dist: mypy ==1.9 ; extra == 'testing'
+Requires-Dist: tomli ; extra == 'testing'
+Requires-Dist: importlib-metadata ; extra == 'testing'
Provides-Extra: testing-integration
Requires-Dist: pytest ; extra == 'testing-integration'
Requires-Dist: pytest-xdist ; extra == 'testing-integration'
diff --git a/contrib/python/setuptools/py3/pkg_resources/__init__.py b/contrib/python/setuptools/py3/pkg_resources/__init__.py
index d83283ff1c..7b166f43b8 100644
--- a/contrib/python/setuptools/py3/pkg_resources/__init__.py
+++ b/contrib/python/setuptools/py3/pkg_resources/__init__.py
@@ -27,7 +27,7 @@ import io
import time
import re
import types
-from typing import Protocol
+from typing import List, Protocol
import zipfile
import zipimport
import warnings
@@ -85,9 +85,7 @@ __import__('pkg_resources.extern.packaging.utils')
require = None
working_set = None
add_activation_listener = None
-resources_stream = None
cleanup_resources = None
-resource_dir = None
resource_stream = None
set_extraction_path = None
resource_isdir = None
@@ -491,19 +489,6 @@ def compatible_platforms(provided, required):
return False
-def run_script(dist_spec, script_name):
- """Locate distribution `dist_spec` and run its `script_name` script"""
- ns = sys._getframe(1).f_globals
- name = ns['__name__']
- ns.clear()
- ns['__name__'] = name
- require(dist_spec)[0].run_script(script_name, ns)
-
-
-# backward compatibility
-run_main = run_script
-
-
def get_distribution(dist):
"""Return a current distribution object for a Requirement or string"""
if isinstance(dist, str):
@@ -531,7 +516,7 @@ def get_entry_info(dist, group, name):
class IMetadataProvider(Protocol):
- def has_metadata(self, name):
+ def has_metadata(self, name) -> bool:
"""Does the package's distribution contain the named metadata?"""
def get_metadata(self, name):
@@ -543,7 +528,7 @@ class IMetadataProvider(Protocol):
Leading and trailing whitespace is stripped from each line, and lines
with ``#`` as the first non-blank character are omitted."""
- def metadata_isdir(self, name):
+ def metadata_isdir(self, name) -> bool:
"""Is the named metadata a directory? (like ``os.path.isdir()``)"""
def metadata_listdir(self, name):
@@ -566,8 +551,8 @@ class IResourceProvider(IMetadataProvider, Protocol):
`manager` must be an ``IResourceManager``"""
- def get_resource_string(self, manager, resource_name):
- """Return a string containing the contents of `resource_name`
+ def get_resource_string(self, manager, resource_name) -> bytes:
+ """Return the contents of `resource_name` as :obj:`bytes`
`manager` must be an ``IResourceManager``"""
@@ -1203,8 +1188,8 @@ class ResourceManager:
self, resource_name
)
- def resource_string(self, package_or_requirement, resource_name):
- """Return specified resource as a string"""
+ def resource_string(self, package_or_requirement, resource_name) -> bytes:
+ """Return specified resource as :obj:`bytes`"""
return get_provider(package_or_requirement).get_resource_string(
self, resource_name
)
@@ -1339,7 +1324,7 @@ class ResourceManager:
self.extraction_path = path
- def cleanup_resources(self, force=False):
+ def cleanup_resources(self, force=False) -> List[str]:
"""
Delete all extracted resource files and directories, returning a list
of the file and directory names that could not be successfully removed.
@@ -1351,6 +1336,7 @@ class ResourceManager:
directory used for extractions.
"""
# XXX
+ return []
def get_default_cache():
@@ -1479,7 +1465,7 @@ class NullProvider:
def get_resource_stream(self, manager, resource_name):
return io.BytesIO(self.get_resource_string(manager, resource_name))
- def get_resource_string(self, manager, resource_name):
+ def get_resource_string(self, manager, resource_name) -> bytes:
return self._get(self._fn(self.module_path, resource_name))
def has_resource(self, resource_name):
@@ -1488,9 +1474,9 @@ class NullProvider:
def _get_metadata_path(self, name):
return self._fn(self.egg_info, name)
- def has_metadata(self, name):
+ def has_metadata(self, name) -> bool:
if not self.egg_info:
- return self.egg_info
+ return False
path = self._get_metadata_path(name)
return self._has(path)
@@ -1514,8 +1500,8 @@ class NullProvider:
def resource_isdir(self, resource_name):
return self._isdir(self._fn(self.module_path, resource_name))
- def metadata_isdir(self, name):
- return self.egg_info and self._isdir(self._fn(self.egg_info, name))
+ def metadata_isdir(self, name) -> bool:
+ return bool(self.egg_info and self._isdir(self._fn(self.egg_info, name)))
def resource_listdir(self, resource_name):
return self._listdir(self._fn(self.module_path, resource_name))
@@ -1554,12 +1540,12 @@ class NullProvider:
script_code = compile(script_text, script_filename, 'exec')
exec(script_code, namespace, namespace)
- def _has(self, path):
+ def _has(self, path) -> bool:
raise NotImplementedError(
"Can't perform this operation for unregistered loader type"
)
- def _isdir(self, path):
+ def _isdir(self, path) -> bool:
raise NotImplementedError(
"Can't perform this operation for unregistered loader type"
)
@@ -1649,7 +1635,7 @@ is not allowed.
DeprecationWarning,
)
- def _get(self, path):
+ def _get(self, path) -> bytes:
if hasattr(self.loader, 'get_data'):
return self.loader.get_data(path)
raise NotImplementedError(
@@ -1694,10 +1680,10 @@ class EggProvider(NullProvider):
class DefaultProvider(EggProvider):
"""Provides access to package resources in the filesystem"""
- def _has(self, path):
+ def _has(self, path) -> bool:
return os.path.exists(path)
- def _isdir(self, path):
+ def _isdir(self, path) -> bool:
return os.path.isdir(path)
def _listdir(self, path):
@@ -1706,7 +1692,7 @@ class DefaultProvider(EggProvider):
def get_resource_stream(self, manager, resource_name):
return open(self._fn(self.module_path, resource_name), 'rb')
- def _get(self, path):
+ def _get(self, path) -> bytes:
with open(path, 'rb') as stream:
return stream.read()
@@ -1731,8 +1717,8 @@ class EmptyProvider(NullProvider):
_isdir = _has = lambda self, path: False
- def _get(self, path):
- return ''
+ def _get(self, path) -> bytes:
+ return b''
def _listdir(self, path):
return []
@@ -1939,11 +1925,11 @@ class ZipProvider(EggProvider):
self._dirindex = ind
return ind
- def _has(self, fspath):
+ def _has(self, fspath) -> bool:
zip_path = self._zipinfo_name(fspath)
return zip_path in self.zipinfo or zip_path in self._index()
- def _isdir(self, fspath):
+ def _isdir(self, fspath) -> bool:
return self._zipinfo_name(fspath) in self._index()
def _listdir(self, fspath):
@@ -1977,7 +1963,7 @@ class FileMetadata(EmptyProvider):
def _get_metadata_path(self, name):
return self.path
- def has_metadata(self, name):
+ def has_metadata(self, name) -> bool:
return name == 'PKG-INFO' and os.path.isfile(self.path)
def get_metadata(self, name):
@@ -3207,7 +3193,9 @@ def _find_adapter(registry, ob):
for t in types:
if t in registry:
return registry[t]
- return None
+ # _find_adapter would previously return None, and immediately be called.
+ # So we're raising a TypeError to keep backward compatibility if anyone depended on that behaviour.
+ raise TypeError(f"Could not find adapter for {registry} and {ob}")
def ensure_directory(path):
diff --git a/contrib/python/setuptools/py3/setuptools/__init__.py b/contrib/python/setuptools/py3/setuptools/__init__.py
index 563ca1c4ba..7c88c7e19b 100644
--- a/contrib/python/setuptools/py3/setuptools/__init__.py
+++ b/contrib/python/setuptools/py3/setuptools/__init__.py
@@ -3,6 +3,7 @@
import functools
import os
import re
+from typing import TYPE_CHECKING
import _distutils_hack.override # noqa: F401
import distutils.core
@@ -105,8 +106,11 @@ def setup(**attrs):
setup.__doc__ = distutils.core.setup.__doc__
-
-_Command = monkey.get_unpatched(distutils.core.Command)
+if TYPE_CHECKING:
+ # Work around a mypy issue where type[T] can't be used as a base: https://github.com/python/mypy/issues/10962
+ _Command = distutils.core.Command
+else:
+ _Command = monkey.get_unpatched(distutils.core.Command)
class Command(_Command):
@@ -165,8 +169,9 @@ class Command(_Command):
"""
command_consumes_arguments = False
+ distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
- def __init__(self, dist, **kw):
+ def __init__(self, dist: Distribution, **kw):
"""
Construct the command for dist, updating
vars(self) with any keyword parameters.
diff --git a/contrib/python/setuptools/py3/setuptools/_core_metadata.py b/contrib/python/setuptools/py3/setuptools/_core_metadata.py
index 4bf3c7c947..5dd97c7719 100644
--- a/contrib/python/setuptools/py3/setuptools/_core_metadata.py
+++ b/contrib/python/setuptools/py3/setuptools/_core_metadata.py
@@ -62,7 +62,7 @@ def _read_list_from_msg(msg: Message, field: str) -> Optional[List[str]]:
def _read_payload_from_msg(msg: Message) -> Optional[str]:
- value = msg.get_payload().strip()
+ value = str(msg.get_payload()).strip()
if value == 'UNKNOWN' or not value:
return None
return value
diff --git a/contrib/python/setuptools/py3/setuptools/_normalization.py b/contrib/python/setuptools/py3/setuptools/_normalization.py
index 8f211b8bfb..e858052ccd 100644
--- a/contrib/python/setuptools/py3/setuptools/_normalization.py
+++ b/contrib/python/setuptools/py3/setuptools/_normalization.py
@@ -4,13 +4,9 @@ and core metadata
"""
import re
-from pathlib import Path
-from typing import Union
from .extern import packaging
-_Path = Union[str, Path]
-
# https://packaging.python.org/en/latest/specifications/core-metadata/#name
_VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I)
_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.I)
diff --git a/contrib/python/setuptools/py3/setuptools/_path.py b/contrib/python/setuptools/py3/setuptools/_path.py
index b99d9dadcf..fb8ef0e198 100644
--- a/contrib/python/setuptools/py3/setuptools/_path.py
+++ b/contrib/python/setuptools/py3/setuptools/_path.py
@@ -2,7 +2,10 @@ import os
import sys
from typing import Union
-_Path = Union[str, os.PathLike]
+if sys.version_info >= (3, 9):
+ StrPath = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath
+else:
+ StrPath = Union[str, os.PathLike]
def ensure_directory(path):
@@ -11,7 +14,7 @@ def ensure_directory(path):
os.makedirs(dirname, exist_ok=True)
-def same_path(p1: _Path, p2: _Path) -> bool:
+def same_path(p1: StrPath, p2: StrPath) -> bool:
"""Differs from os.path.samefile because it does not require paths to exist.
Purely string based (no comparison between i-nodes).
>>> same_path("a/b", "./a/b")
@@ -30,7 +33,7 @@ def same_path(p1: _Path, p2: _Path) -> bool:
return normpath(p1) == normpath(p2)
-def normpath(filename: _Path) -> str:
+def normpath(filename: StrPath) -> str:
"""Normalize a file/dir name for comparison purposes."""
# See pkg_resources.normalize_path for notes about cygwin
file = os.path.abspath(filename) if sys.platform == 'cygwin' else filename
diff --git a/contrib/python/setuptools/py3/setuptools/command/_requirestxt.py b/contrib/python/setuptools/py3/setuptools/command/_requirestxt.py
index 7b732b11ab..b0c2d7059a 100644
--- a/contrib/python/setuptools/py3/setuptools/command/_requirestxt.py
+++ b/contrib/python/setuptools/py3/setuptools/command/_requirestxt.py
@@ -35,7 +35,7 @@ def _prepare(
def _convert_extras_requirements(
- extras_require: _StrOrIter,
+ extras_require: Mapping[str, _StrOrIter],
) -> Mapping[str, _Ordered[Requirement]]:
"""
Convert requirements in `extras_require` of the form
diff --git a/contrib/python/setuptools/py3/setuptools/command/build_ext.py b/contrib/python/setuptools/py3/setuptools/command/build_ext.py
index 780afe3aec..b5c98c86dc 100644
--- a/contrib/python/setuptools/py3/setuptools/command/build_ext.py
+++ b/contrib/python/setuptools/py3/setuptools/command/build_ext.py
@@ -16,7 +16,7 @@ from setuptools.extension import Extension, Library
try:
# Attempt to use Cython for building extensions, if available
- from Cython.Distutils.build_ext import build_ext as _build_ext
+ from Cython.Distutils.build_ext import build_ext as _build_ext # type: ignore[import-not-found] # Cython not installed on CI tests
# Additionally, assert that the compiler module will load
# also. Ref #1229.
@@ -26,7 +26,9 @@ except ImportError:
# make sure _config_vars is initialized
get_config_var("LDSHARED")
-from distutils.sysconfig import _config_vars as _CONFIG_VARS # noqa
+# Not publicly exposed in typeshed distutils stubs, but this is done on purpose
+# See https://github.com/pypa/setuptools/pull/4228#issuecomment-1959856400
+from distutils.sysconfig import _config_vars as _CONFIG_VARS # type: ignore # noqa
def _customize_compiler_for_shlib(compiler):
@@ -58,7 +60,7 @@ if sys.platform == "darwin":
use_stubs = True
elif os.name != 'nt':
try:
- import dl
+ import dl # type: ignore[import-not-found] # https://github.com/python/mypy/issues/13002
use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW')
except ImportError:
@@ -378,7 +380,10 @@ class build_ext(_build_ext):
optimize = self.get_finalized_command('install_lib').optimize
if optimize > 0:
byte_compile(
- [stub_file], optimize=optimize, force=True, dry_run=self.dry_run
+ [stub_file],
+ optimize=optimize,
+ force=True,
+ dry_run=self.dry_run,
)
if os.path.exists(stub_file) and not self.dry_run:
os.unlink(stub_file)
diff --git a/contrib/python/setuptools/py3/setuptools/command/dist_info.py b/contrib/python/setuptools/py3/setuptools/command/dist_info.py
index f5061afaaf..52c0721903 100644
--- a/contrib/python/setuptools/py3/setuptools/command/dist_info.py
+++ b/contrib/python/setuptools/py3/setuptools/command/dist_info.py
@@ -9,8 +9,10 @@ from contextlib import contextmanager
from distutils import log
from distutils.core import Command
from pathlib import Path
+from typing import cast
from .. import _normalization
+from .egg_info import egg_info as egg_info_cls
class dist_info(Command):
@@ -50,7 +52,7 @@ class dist_info(Command):
project_dir = dist.src_root or os.curdir
self.output_dir = Path(self.output_dir or project_dir)
- egg_info = self.reinitialize_command("egg_info")
+ egg_info = cast(egg_info_cls, self.reinitialize_command("egg_info"))
egg_info.egg_base = str(self.output_dir)
if self.tag_date:
diff --git a/contrib/python/setuptools/py3/setuptools/command/easy_install.py b/contrib/python/setuptools/py3/setuptools/command/easy_install.py
index cc0c409123..858fb20f83 100644
--- a/contrib/python/setuptools/py3/setuptools/command/easy_install.py
+++ b/contrib/python/setuptools/py3/setuptools/command/easy_install.py
@@ -25,6 +25,7 @@ from distutils.spawn import find_executable
from distutils.command import install
import sys
import os
+from typing import Dict, List
import zipimport
import shutil
import tempfile
@@ -43,7 +44,6 @@ import io
import configparser
import sysconfig
-
from sysconfig import get_path
from setuptools import Command
@@ -74,7 +74,7 @@ from pkg_resources import (
DEVELOP_DIST,
)
import pkg_resources
-from ..compat import py311
+from ..compat import py39, py311
from .._path import ensure_directory
from ..extern.jaraco.text import yield_lines
@@ -491,7 +491,7 @@ class easy_install(Command):
try:
if test_exists:
os.unlink(testfile)
- open(testfile, 'w').close()
+ open(testfile, 'wb').close()
os.unlink(testfile)
except OSError:
self.cant_write_to_target()
@@ -576,7 +576,7 @@ class easy_install(Command):
_one_liner(
"""
import os
- f = open({ok_file!r}, 'w')
+ f = open({ok_file!r}, 'w', encoding="utf-8")
f.write('OK')
f.close()
"""
@@ -588,7 +588,8 @@ class easy_install(Command):
os.unlink(ok_file)
dirname = os.path.dirname(ok_file)
os.makedirs(dirname, exist_ok=True)
- f = open(pth_file, 'w')
+ f = open(pth_file, 'w', encoding=py39.LOCALE_ENCODING)
+ # ^-- Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
except OSError:
self.cant_write_to_target()
else:
@@ -872,7 +873,7 @@ class easy_install(Command):
ensure_directory(target)
if os.path.exists(target):
os.unlink(target)
- with open(target, "w" + mode) as f:
+ with open(target, "w" + mode) as f: # TODO: is it safe to use utf-8?
f.write(contents)
chmod(target, 0o777 - mask)
@@ -1016,7 +1017,7 @@ class easy_install(Command):
# Write EGG-INFO/PKG-INFO
if not os.path.exists(pkg_inf):
- f = open(pkg_inf, 'w')
+ f = open(pkg_inf, 'w') # TODO: probably it is safe to use utf-8
f.write('Metadata-Version: 1.0\n')
for k, v in cfg.items('metadata'):
if k != 'target_version':
@@ -1087,7 +1088,7 @@ class easy_install(Command):
if locals()[name]:
txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt')
if not os.path.exists(txt):
- f = open(txt, 'w')
+ f = open(txt, 'w') # TODO: probably it is safe to use utf-8
f.write('\n'.join(locals()[name]) + '\n')
f.close()
@@ -1277,7 +1278,9 @@ class easy_install(Command):
filename = os.path.join(self.install_dir, 'setuptools.pth')
if os.path.islink(filename):
os.unlink(filename)
- with open(filename, 'wt') as f:
+
+ with open(filename, 'wt', encoding=py39.LOCALE_ENCODING) as f:
+ # Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
f.write(self.pth_file.make_relative(dist.location) + '\n')
def unpack_progress(self, src, dst):
@@ -1503,9 +1506,9 @@ def expand_paths(inputs): # noqa: C901 # is too complex (11) # FIXME
continue
# Read the .pth file
- f = open(os.path.join(dirname, name))
- lines = list(yield_lines(f))
- f.close()
+ with open(os.path.join(dirname, name), encoding=py39.LOCALE_ENCODING) as f:
+ # Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
+ lines = list(yield_lines(f))
# Yield existing non-dupe, non-import directory lines from it
for line in lines:
@@ -1619,7 +1622,8 @@ class PthDistributions(Environment):
paths = []
dirty = saw_import = False
seen = dict.fromkeys(self.sitedirs)
- f = open(self.filename, 'rt')
+ f = open(self.filename, 'rt', encoding=py39.LOCALE_ENCODING)
+ # ^-- Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
for line in f:
path = line.rstrip()
# still keep imports and empty/commented lines for formatting
@@ -1690,7 +1694,8 @@ class PthDistributions(Environment):
data = '\n'.join(lines) + '\n'
if os.path.islink(self.filename):
os.unlink(self.filename)
- with open(self.filename, 'wt') as f:
+ with open(self.filename, 'wt', encoding=py39.LOCALE_ENCODING) as f:
+ # Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
f.write(data)
elif os.path.exists(self.filename):
log.debug("Deleting empty %s", self.filename)
@@ -1765,7 +1770,7 @@ class RewritePthDistributions(PthDistributions):
if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite':
- PthDistributions = RewritePthDistributions
+ PthDistributions = RewritePthDistributions # type: ignore[misc] # Overwriting type
def _first_line_re():
@@ -2015,7 +2020,7 @@ try:
from os import chmod as _chmod
except ImportError:
# Jython compatibility
- def _chmod(*args):
+ def _chmod(*args: object, **kwargs: object) -> None: # type: ignore[misc] # Mypy re-uses the imported definition anyway
pass
@@ -2033,8 +2038,8 @@ class CommandSpec(list):
those passed to Popen.
"""
- options = []
- split_args = dict()
+ options: List[str] = []
+ split_args: Dict[str, bool] = dict()
@classmethod
def best(cls):
diff --git a/contrib/python/setuptools/py3/setuptools/command/editable_wheel.py b/contrib/python/setuptools/py3/setuptools/command/editable_wheel.py
index 8a4ae7928f..4d21e2253f 100644
--- a/contrib/python/setuptools/py3/setuptools/command/editable_wheel.py
+++ b/contrib/python/setuptools/py3/setuptools/command/editable_wheel.py
@@ -14,7 +14,6 @@ import logging
import io
import os
import shutil
-import sys
import traceback
from contextlib import suppress
from enum import Enum
@@ -33,7 +32,7 @@ from typing import (
Protocol,
Tuple,
TypeVar,
- Union,
+ cast,
)
from .. import (
@@ -43,6 +42,8 @@ from .. import (
errors,
namespaces,
)
+from .._path import StrPath
+from ..compat import py39
from ..discovery import find_package_path
from ..dist import Distribution
from ..warnings import (
@@ -50,13 +51,17 @@ from ..warnings import (
SetuptoolsDeprecationWarning,
SetuptoolsWarning,
)
+from .build import build as build_cls
from .build_py import build_py as build_py_cls
+from .dist_info import dist_info as dist_info_cls
+from .egg_info import egg_info as egg_info_cls
+from .install import install as install_cls
+from .install_scripts import install_scripts as install_scripts_cls
if TYPE_CHECKING:
- from wheel.wheelfile import WheelFile # noqa
+ from wheel.wheelfile import WheelFile # type:ignore[import-untyped] # noqa
-_Path = Union[str, Path]
-_P = TypeVar("_P", bound=_Path)
+_P = TypeVar("_P", bound=StrPath)
_logger = logging.getLogger(__name__)
@@ -156,7 +161,7 @@ class editable_wheel(Command):
def _ensure_dist_info(self):
if self.dist_info_dir is None:
- dist_info = self.reinitialize_command("dist_info")
+ dist_info = cast(dist_info_cls, self.reinitialize_command("dist_info"))
dist_info.output_dir = self.dist_dir
dist_info.ensure_finalized()
dist_info.run()
@@ -181,7 +186,7 @@ class editable_wheel(Command):
return next(candidates, None)
def _configure_build(
- self, name: str, unpacked_wheel: _Path, build_lib: _Path, tmp_dir: _Path
+ self, name: str, unpacked_wheel: StrPath, build_lib: StrPath, tmp_dir: StrPath
):
"""Configure commands to behave in the following ways:
@@ -203,12 +208,18 @@ class editable_wheel(Command):
scripts = str(Path(unpacked_wheel, f"{name}.data", "scripts"))
# egg-info may be generated again to create a manifest (used for package data)
- egg_info = dist.reinitialize_command("egg_info", reinit_subcommands=True)
+ egg_info = cast(
+ egg_info_cls, dist.reinitialize_command("egg_info", reinit_subcommands=True)
+ )
egg_info.egg_base = str(tmp_dir)
egg_info.ignore_egg_info_in_manifest = True
- build = dist.reinitialize_command("build", reinit_subcommands=True)
- install = dist.reinitialize_command("install", reinit_subcommands=True)
+ build = cast(
+ build_cls, dist.reinitialize_command("build", reinit_subcommands=True)
+ )
+ install = cast(
+ install_cls, dist.reinitialize_command("install", reinit_subcommands=True)
+ )
build.build_platlib = build.build_purelib = build.build_lib = build_lib
install.install_purelib = install.install_platlib = install.install_lib = wheel
@@ -216,12 +227,14 @@ class editable_wheel(Command):
install.install_headers = headers
install.install_data = data
- install_scripts = dist.get_command_obj("install_scripts")
+ install_scripts = cast(
+ install_scripts_cls, dist.get_command_obj("install_scripts")
+ )
install_scripts.no_ep = True
build.build_temp = str(tmp_dir)
- build_py = dist.get_command_obj("build_py")
+ build_py = cast(build_py_cls, dist.get_command_obj("build_py"))
build_py.compile = False
build_py.existing_egg_info_dir = self._find_egg_info_dir()
@@ -234,6 +247,7 @@ class editable_wheel(Command):
"""Set the ``editable_mode`` flag in the build sub-commands"""
dist = self.distribution
build = dist.get_command_obj("build")
+ # TODO: Update typeshed distutils stubs to overload non-None return type by default
for cmd_name in build.get_sub_commands():
cmd = dist.get_command_obj(cmd_name)
if hasattr(cmd, "editable_mode"):
@@ -256,7 +270,11 @@ class editable_wheel(Command):
return files, mapping
def _run_build_commands(
- self, dist_name: str, unpacked_wheel: _Path, build_lib: _Path, tmp_dir: _Path
+ self,
+ dist_name: str,
+ unpacked_wheel: StrPath,
+ build_lib: StrPath,
+ tmp_dir: StrPath,
) -> Tuple[List[str], Dict[str, str]]:
self._configure_build(dist_name, unpacked_wheel, build_lib, tmp_dir)
self._run_build_subcommands()
@@ -266,7 +284,7 @@ class editable_wheel(Command):
self._run_install("data")
return files, mapping
- def _run_build_subcommands(self):
+ def _run_build_subcommands(self) -> None:
"""
Issue #3501 indicates that some plugins/customizations might rely on:
@@ -280,7 +298,7 @@ class editable_wheel(Command):
# TODO: Once plugins/customisations had the chance to catch up, replace
# `self._run_build_subcommands()` with `self.run_command("build")`.
# Also remove _safely_run, TestCustomBuildPy. Suggested date: Aug/2023.
- build: Command = self.get_finalized_command("build")
+ build = self.get_finalized_command("build")
for name in build.get_sub_commands():
cmd = self.get_finalized_command(name)
if name == "build_py" and type(cmd) != build_py_cls:
@@ -354,7 +372,7 @@ class editable_wheel(Command):
self,
name: str,
tag: str,
- build_lib: _Path,
+ build_lib: StrPath,
) -> "EditableStrategy":
"""Decides which strategy to use to implement an editable installation."""
build_name = f"__editable__.{name}-{tag}"
@@ -424,12 +442,13 @@ class _LinkTree(_StaticPth):
self,
dist: Distribution,
name: str,
- auxiliary_dir: _Path,
- build_lib: _Path,
+ auxiliary_dir: StrPath,
+ build_lib: StrPath,
):
self.auxiliary_dir = Path(auxiliary_dir)
self.build_lib = Path(build_lib).resolve()
- self._file = dist.get_command_obj("build_py").copy_file
+ # TODO: Update typeshed distutils stubs to overload non-None return type by default
+ self._file = dist.get_command_obj("build_py").copy_file # type: ignore[union-attr]
super().__init__(dist, name, [self.auxiliary_dir])
def __call__(self, wheel: "WheelFile", files: List[str], mapping: Dict[str, str]):
@@ -447,7 +466,9 @@ class _LinkTree(_StaticPth):
dest = self.auxiliary_dir / relative_output
if not dest.parent.is_dir():
dest.parent.mkdir(parents=True)
- self._file(src_file, dest, link=link)
+ # TODO: Update typeshed distutils stubs so distutils.cmd.Command.copy_file, accepts PathLike
+ # same with methods used by copy_file
+ self._file(src_file, dest, link=link) # type: ignore[arg-type]
def _create_links(self, outputs, output_mapping):
self.auxiliary_dir.mkdir(parents=True, exist_ok=True)
@@ -537,9 +558,8 @@ def _encode_pth(content: str) -> bytes:
(There seems to be some variety in the way different version of Python handle
``encoding=None``, not all of them use ``locale.getpreferredencoding(False)``).
"""
- encoding = "locale" if sys.version_info >= (3, 10) else None
with io.BytesIO() as buffer:
- wrapper = io.TextIOWrapper(buffer, encoding)
+ wrapper = io.TextIOWrapper(buffer, encoding=py39.LOCALE_ENCODING)
wrapper.write(content)
wrapper.flush()
buffer.seek(0)
@@ -567,7 +587,7 @@ def _can_symlink_files(base_dir: Path) -> bool:
def _simple_layout(
- packages: Iterable[str], package_dir: Dict[str, str], project_dir: Path
+ packages: Iterable[str], package_dir: Dict[str, str], project_dir: StrPath
) -> bool:
"""Return ``True`` if:
- all packages are contained by the same parent directory, **and**
@@ -649,7 +669,7 @@ def _find_top_level_modules(dist: Distribution) -> Iterator[str]:
def _find_package_roots(
packages: Iterable[str],
package_dir: Mapping[str, str],
- src_root: _Path,
+ src_root: StrPath,
) -> Dict[str, str]:
pkg_roots: Dict[str, str] = {
pkg: _absolute_root(find_package_path(pkg, package_dir, src_root))
@@ -659,7 +679,7 @@ def _find_package_roots(
return _remove_nested(pkg_roots)
-def _absolute_root(path: _Path) -> str:
+def _absolute_root(path: StrPath) -> str:
"""Works for packages and top-level modules"""
path_ = Path(path)
parent = path_.parent
diff --git a/contrib/python/setuptools/py3/setuptools/command/install.py b/contrib/python/setuptools/py3/setuptools/command/install.py
index b97a9b4713..56c1155b50 100644
--- a/contrib/python/setuptools/py3/setuptools/command/install.py
+++ b/contrib/python/setuptools/py3/setuptools/command/install.py
@@ -3,9 +3,11 @@ import inspect
import glob
import platform
import distutils.command.install as orig
+from typing import cast
import setuptools
from ..warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning
+from .bdist_egg import bdist_egg as bdist_egg_cls
# Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for
# now. See https://github.com/pypa/setuptools/issues/199/
@@ -135,7 +137,8 @@ class install(orig.install):
cmd.package_index.scan(glob.glob('*.egg'))
self.run_command('bdist_egg')
- args = [self.distribution.get_command_obj('bdist_egg').egg_output]
+ bdist_egg = cast(bdist_egg_cls, self.distribution.get_command_obj('bdist_egg'))
+ args = [bdist_egg.egg_output]
if setuptools.bootstrap_install_from:
# Bootstrap self-installation of setuptools
diff --git a/contrib/python/setuptools/py3/setuptools/command/rotate.py b/contrib/python/setuptools/py3/setuptools/command/rotate.py
index cfb78ce52d..6f73721c70 100644
--- a/contrib/python/setuptools/py3/setuptools/command/rotate.py
+++ b/contrib/python/setuptools/py3/setuptools/command/rotate.py
@@ -3,6 +3,7 @@ from distutils import log
from distutils.errors import DistutilsOptionError
import os
import shutil
+from typing import List
from setuptools import Command
@@ -17,7 +18,7 @@ class rotate(Command):
('keep=', 'k', "number of matching distributions to keep"),
]
- boolean_options = []
+ boolean_options: List[str] = []
def initialize_options(self):
self.match = None
diff --git a/contrib/python/setuptools/py3/setuptools/command/upload_docs.py b/contrib/python/setuptools/py3/setuptools/command/upload_docs.py
index 32c9abd796..3fbbb62553 100644
--- a/contrib/python/setuptools/py3/setuptools/command/upload_docs.py
+++ b/contrib/python/setuptools/py3/setuptools/command/upload_docs.py
@@ -50,7 +50,7 @@ class upload_docs(upload):
and metadata.entry_points(group='distutils.commands', name='build_sphinx')
)
- sub_commands = [('build_sphinx', has_sphinx)]
+ sub_commands = [('build_sphinx', has_sphinx)] # type: ignore[list-item] # TODO: Fix in typeshed distutils stubs
def initialize_options(self):
upload.initialize_options(self)
diff --git a/contrib/python/setuptools/py3/setuptools/compat/py39.py b/contrib/python/setuptools/py3/setuptools/compat/py39.py
new file mode 100644
index 0000000000..04a4abe5a9
--- /dev/null
+++ b/contrib/python/setuptools/py3/setuptools/compat/py39.py
@@ -0,0 +1,9 @@
+import sys
+
+# Explicitly use the ``"locale"`` encoding in versions that support it,
+# otherwise just rely on the implicit handling of ``encoding=None``.
+# Since all platforms that support ``EncodingWarning`` also support
+# ``encoding="locale"``, this can be used to suppress the warning.
+# However, please try to use UTF-8 when possible
+# (.pth files are the notorious exception: python/cpython#77102, pypa/setuptools#3937).
+LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None
diff --git a/contrib/python/setuptools/py3/setuptools/config/_apply_pyprojecttoml.py b/contrib/python/setuptools/py3/setuptools/config/_apply_pyprojecttoml.py
index 32fb00131e..3626282a79 100644
--- a/contrib/python/setuptools/py3/setuptools/config/_apply_pyprojecttoml.py
+++ b/contrib/python/setuptools/py3/setuptools/config/_apply_pyprojecttoml.py
@@ -29,24 +29,24 @@ from typing import (
Union,
cast,
)
-
+from .._path import StrPath
from ..errors import RemovedConfigError
from ..warnings import SetuptoolsWarning
if TYPE_CHECKING:
+ from distutils.dist import _OptionsList
from setuptools._importlib import metadata # noqa
from setuptools.dist import Distribution # noqa
EMPTY: Mapping = MappingProxyType({}) # Immutable dict-like
-_Path = Union[os.PathLike, str]
_DictOrStr = Union[dict, str]
-_CorrespFn = Callable[["Distribution", Any, _Path], None]
+_CorrespFn = Callable[["Distribution", Any, StrPath], None]
_Correspondence = Union[str, _CorrespFn]
_logger = logging.getLogger(__name__)
-def apply(dist: "Distribution", config: dict, filename: _Path) -> "Distribution":
+def apply(dist: "Distribution", config: dict, filename: StrPath) -> "Distribution":
"""Apply configuration dict read with :func:`read_configuration`"""
if not config:
@@ -68,7 +68,7 @@ def apply(dist: "Distribution", config: dict, filename: _Path) -> "Distribution"
return dist
-def _apply_project_table(dist: "Distribution", config: dict, root_dir: _Path):
+def _apply_project_table(dist: "Distribution", config: dict, root_dir: StrPath):
project_table = config.get("project", {}).copy()
if not project_table:
return # short-circuit
@@ -85,7 +85,7 @@ def _apply_project_table(dist: "Distribution", config: dict, root_dir: _Path):
_set_config(dist, corresp, value)
-def _apply_tool_table(dist: "Distribution", config: dict, filename: _Path):
+def _apply_tool_table(dist: "Distribution", config: dict, filename: StrPath):
tool_table = config.get("tool", {}).get("setuptools", {})
if not tool_table:
return # short-circuit
@@ -153,7 +153,7 @@ def _guess_content_type(file: str) -> Optional[str]:
raise ValueError(f"Undefined content type for {file}, {msg}")
-def _long_description(dist: "Distribution", val: _DictOrStr, root_dir: _Path):
+def _long_description(dist: "Distribution", val: _DictOrStr, root_dir: StrPath):
from setuptools.config import expand
if isinstance(val, str):
@@ -174,7 +174,7 @@ def _long_description(dist: "Distribution", val: _DictOrStr, root_dir: _Path):
dist._referenced_files.add(cast(str, file))
-def _license(dist: "Distribution", val: dict, root_dir: _Path):
+def _license(dist: "Distribution", val: dict, root_dir: StrPath):
from setuptools.config import expand
if "file" in val:
@@ -184,7 +184,7 @@ def _license(dist: "Distribution", val: dict, root_dir: _Path):
_set_config(dist, "license", val["text"])
-def _people(dist: "Distribution", val: List[dict], _root_dir: _Path, kind: str):
+def _people(dist: "Distribution", val: List[dict], _root_dir: StrPath, kind: str):
field = []
email_field = []
for person in val:
@@ -244,7 +244,7 @@ def _unify_entry_points(project_table: dict):
# intentional (for resetting configurations that are missing `dynamic`).
-def _copy_command_options(pyproject: dict, dist: "Distribution", filename: _Path):
+def _copy_command_options(pyproject: dict, dist: "Distribution", filename: StrPath):
tool_table = pyproject.get("tool", {})
cmdclass = tool_table.get("setuptools", {}).get("cmdclass", {})
valid_options = _valid_command_options(cmdclass)
@@ -294,7 +294,7 @@ def _normalise_cmd_option_key(name: str) -> str:
return json_compatible_key(name).strip("_=")
-def _normalise_cmd_options(desc: List[Tuple[str, Optional[str], str]]) -> Set[str]:
+def _normalise_cmd_options(desc: "_OptionsList") -> Set[str]:
return {_normalise_cmd_option_key(fancy_option[0]) for fancy_option in desc}
diff --git a/contrib/python/setuptools/py3/setuptools/config/_validate_pyproject/fastjsonschema_validations.py b/contrib/python/setuptools/py3/setuptools/config/_validate_pyproject/fastjsonschema_validations.py
index b81d13c119..8b852bbfd4 100644
--- a/contrib/python/setuptools/py3/setuptools/config/_validate_pyproject/fastjsonschema_validations.py
+++ b/contrib/python/setuptools/py3/setuptools/config/_validate_pyproject/fastjsonschema_validations.py
@@ -1,5 +1,4 @@
# noqa
-# type: ignore
# flake8: noqa
# pylint: skip-file
# mypy: ignore-errors
diff --git a/contrib/python/setuptools/py3/setuptools/config/expand.py b/contrib/python/setuptools/py3/setuptools/config/expand.py
index b48fc1187e..0d8d58add8 100644
--- a/contrib/python/setuptools/py3/setuptools/config/expand.py
+++ b/contrib/python/setuptools/py3/setuptools/config/expand.py
@@ -46,7 +46,7 @@ from types import ModuleType
from distutils.errors import DistutilsOptionError
-from .._path import same_path as _same_path
+from .._path import same_path as _same_path, StrPath
from ..warnings import SetuptoolsWarning
if TYPE_CHECKING:
@@ -55,7 +55,6 @@ if TYPE_CHECKING:
from distutils.dist import DistributionMetadata # noqa
chain_iter = chain.from_iterable
-_Path = Union[str, os.PathLike]
_K = TypeVar("_K")
_V = TypeVar("_V", covariant=True)
@@ -64,7 +63,7 @@ class StaticModule:
"""Proxy to a module object that avoids executing arbitrary code."""
def __init__(self, name: str, spec: ModuleSpec):
- module = ast.parse(pathlib.Path(spec.origin).read_bytes())
+ module = ast.parse(pathlib.Path(spec.origin).read_bytes()) # type: ignore[arg-type] # Let it raise an error on None
vars(self).update(locals())
del self.self
@@ -88,7 +87,7 @@ class StaticModule:
def glob_relative(
- patterns: Iterable[str], root_dir: Optional[_Path] = None
+ patterns: Iterable[str], root_dir: Optional[StrPath] = None
) -> List[str]:
"""Expand the list of glob patterns, but preserving relative paths.
@@ -120,7 +119,7 @@ def glob_relative(
return expanded_values
-def read_files(filepaths: Union[str, bytes, Iterable[_Path]], root_dir=None) -> str:
+def read_files(filepaths: Union[str, bytes, Iterable[StrPath]], root_dir=None) -> str:
"""Return the content of the files concatenated using ``\n`` as str
This function is sandboxed and won't reach anything outside ``root_dir``
@@ -138,7 +137,7 @@ def read_files(filepaths: Union[str, bytes, Iterable[_Path]], root_dir=None) ->
)
-def _filter_existing_files(filepaths: Iterable[_Path]) -> Iterator[_Path]:
+def _filter_existing_files(filepaths: Iterable[StrPath]) -> Iterator[StrPath]:
for path in filepaths:
if os.path.isfile(path):
yield path
@@ -146,12 +145,12 @@ def _filter_existing_files(filepaths: Iterable[_Path]) -> Iterator[_Path]:
SetuptoolsWarning.emit(f"File {path!r} cannot be found")
-def _read_file(filepath: Union[bytes, _Path]) -> str:
+def _read_file(filepath: Union[bytes, StrPath]) -> str:
with open(filepath, encoding='utf-8') as f:
return f.read()
-def _assert_local(filepath: _Path, root_dir: str):
+def _assert_local(filepath: StrPath, root_dir: str):
if Path(os.path.abspath(root_dir)) not in Path(os.path.abspath(filepath)).parents:
msg = f"Cannot access {filepath!r} (or anything outside {root_dir!r})"
raise DistutilsOptionError(msg)
@@ -162,7 +161,7 @@ def _assert_local(filepath: _Path, root_dir: str):
def read_attr(
attr_desc: str,
package_dir: Optional[Mapping[str, str]] = None,
- root_dir: Optional[_Path] = None,
+ root_dir: Optional[StrPath] = None,
):
"""Reads the value of an attribute from a module.
@@ -197,7 +196,7 @@ def read_attr(
return getattr(module, attr_name)
-def _find_spec(module_name: str, module_path: Optional[_Path]) -> ModuleSpec:
+def _find_spec(module_name: str, module_path: Optional[StrPath]) -> ModuleSpec:
spec = importlib.util.spec_from_file_location(module_name, module_path)
spec = spec or importlib.util.find_spec(module_name)
@@ -218,8 +217,8 @@ def _load_spec(spec: ModuleSpec, module_name: str) -> ModuleType:
def _find_module(
- module_name: str, package_dir: Optional[Mapping[str, str]], root_dir: _Path
-) -> Tuple[_Path, Optional[str], str]:
+ module_name: str, package_dir: Optional[Mapping[str, str]], root_dir: StrPath
+) -> Tuple[StrPath, Optional[str], str]:
"""Given a module (that could normally be imported by ``module_name``
after the build is complete), find the path to the parent directory where
it is contained and the canonical name that could be used to import it
@@ -254,7 +253,7 @@ def _find_module(
def resolve_class(
qualified_class_name: str,
package_dir: Optional[Mapping[str, str]] = None,
- root_dir: Optional[_Path] = None,
+ root_dir: Optional[StrPath] = None,
) -> Callable:
"""Given a qualified class name, return the associated class object"""
root_dir = root_dir or os.getcwd()
@@ -270,7 +269,7 @@ def resolve_class(
def cmdclass(
values: Dict[str, str],
package_dir: Optional[Mapping[str, str]] = None,
- root_dir: Optional[_Path] = None,
+ root_dir: Optional[StrPath] = None,
) -> Dict[str, Callable]:
"""Given a dictionary mapping command names to strings for qualified class
names, apply :func:`resolve_class` to the dict values.
@@ -282,7 +281,7 @@ def find_packages(
*,
namespaces=True,
fill_package_dir: Optional[Dict[str, str]] = None,
- root_dir: Optional[_Path] = None,
+ root_dir: Optional[StrPath] = None,
**kwargs,
) -> List[str]:
"""Works similarly to :func:`setuptools.find_packages`, but with all
@@ -331,7 +330,7 @@ def find_packages(
return packages
-def _nest_path(parent: _Path, path: _Path) -> str:
+def _nest_path(parent: StrPath, path: StrPath) -> str:
path = parent if path in {".", ""} else os.path.join(parent, path)
return os.path.normpath(path)
@@ -361,7 +360,7 @@ def canonic_package_data(package_data: dict) -> dict:
def canonic_data_files(
- data_files: Union[list, dict], root_dir: Optional[_Path] = None
+ data_files: Union[list, dict], root_dir: Optional[StrPath] = None
) -> List[Tuple[str, List[str]]]:
"""For compatibility with ``setup.py``, ``data_files`` should be a list
of pairs instead of a dict.
diff --git a/contrib/python/setuptools/py3/setuptools/config/pyprojecttoml.py b/contrib/python/setuptools/py3/setuptools/config/pyprojecttoml.py
index 9b9788eff4..ff97679895 100644
--- a/contrib/python/setuptools/py3/setuptools/config/pyprojecttoml.py
+++ b/contrib/python/setuptools/py3/setuptools/config/pyprojecttoml.py
@@ -13,8 +13,9 @@ import logging
import os
from contextlib import contextmanager
from functools import partial
-from typing import TYPE_CHECKING, Callable, Dict, Mapping, Optional, Set, Union
+from typing import TYPE_CHECKING, Callable, Dict, Mapping, Optional, Set
+from .._path import StrPath
from ..errors import FileError, InvalidConfigError
from ..warnings import SetuptoolsWarning
from . import expand as _expand
@@ -23,19 +24,19 @@ from ._apply_pyprojecttoml import apply as _apply
if TYPE_CHECKING:
from setuptools.dist import Distribution # noqa
+ from typing_extensions import Self
-_Path = Union[str, os.PathLike]
_logger = logging.getLogger(__name__)
-def load_file(filepath: _Path) -> dict:
+def load_file(filepath: StrPath) -> dict:
from ..compat.py310 import tomllib
with open(filepath, "rb") as file:
return tomllib.load(file)
-def validate(config: dict, filepath: _Path) -> bool:
+def validate(config: dict, filepath: StrPath) -> bool:
from . import _validate_pyproject as validator
trove_classifier = validator.FORMAT_FUNCTIONS.get("trove-classifier")
@@ -58,7 +59,7 @@ def validate(config: dict, filepath: _Path) -> bool:
def apply_configuration(
dist: "Distribution",
- filepath: _Path,
+ filepath: StrPath,
ignore_option_errors=False,
) -> "Distribution":
"""Apply the configuration from a ``pyproject.toml`` file into an existing
@@ -69,7 +70,7 @@ def apply_configuration(
def read_configuration(
- filepath: _Path,
+ filepath: StrPath,
expand=True,
ignore_option_errors=False,
dist: Optional["Distribution"] = None,
@@ -136,7 +137,7 @@ def read_configuration(
def expand_configuration(
config: dict,
- root_dir: Optional[_Path] = None,
+ root_dir: Optional[StrPath] = None,
ignore_option_errors: bool = False,
dist: Optional["Distribution"] = None,
) -> dict:
@@ -161,7 +162,7 @@ class _ConfigExpander:
def __init__(
self,
config: dict,
- root_dir: Optional[_Path] = None,
+ root_dir: Optional[StrPath] = None,
ignore_option_errors: bool = False,
dist: Optional["Distribution"] = None,
):
@@ -271,7 +272,7 @@ class _ConfigExpander:
def _expand_directive(
self, specifier: str, directive, package_dir: Mapping[str, str]
):
- from setuptools.extern.more_itertools import always_iterable # type: ignore
+ from setuptools.extern.more_itertools import always_iterable
with _ignore_errors(self.ignore_option_errors):
root_dir = self.root_dir
@@ -401,7 +402,7 @@ class _EnsurePackagesDiscovered(_expand.EnsurePackagesDiscovered):
self._project_cfg = project_cfg
self._setuptools_cfg = setuptools_cfg
- def __enter__(self):
+ def __enter__(self) -> "Self":
"""When entering the context, the values of ``packages``, ``py_modules`` and
``package_dir`` that are missing in ``dist`` are copied from ``setuptools_cfg``.
"""
diff --git a/contrib/python/setuptools/py3/setuptools/config/setupcfg.py b/contrib/python/setuptools/py3/setuptools/config/setupcfg.py
index a7f02714cb..2912d3e143 100644
--- a/contrib/python/setuptools/py3/setuptools/config/setupcfg.py
+++ b/contrib/python/setuptools/py3/setuptools/config/setupcfg.py
@@ -30,6 +30,7 @@ from typing import (
Union,
)
+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
@@ -43,7 +44,6 @@ if TYPE_CHECKING:
from setuptools.dist import Distribution # noqa
-_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
@@ -55,7 +55,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.
@@ -80,7 +80,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.
"""
@@ -91,8 +91,8 @@ def apply_configuration(dist: "Distribution", filepath: _Path) -> "Distribution"
def _apply(
dist: "Distribution",
- filepath: _Path,
- other_files: Iterable[_Path] = (),
+ filepath: StrPath,
+ other_files: Iterable[StrPath] = (),
ignore_option_errors: bool = False,
) -> Tuple["ConfigHandler", ...]:
"""Read configuration from ``filepath`` and applies to the ``dist`` object."""
@@ -108,7 +108,7 @@ def _apply(
filenames = [*other_files, filepath]
try:
- _Distribution.parse_config_files(dist, filenames=filenames)
+ _Distribution.parse_config_files(dist, filenames=filenames) # type: ignore[arg-type] # TODO: fix in disutils stubs
handlers = parse_configuration(
dist, dist.command_options, ignore_option_errors=ignore_option_errors
)
@@ -371,7 +371,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.
@@ -397,7 +397,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:
@@ -475,7 +475,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.
@@ -539,7 +539,7 @@ class ConfigMetadataHandler(ConfigHandler["DistributionMetadata"]):
ignore_option_errors: bool,
ensure_discovered: expand.EnsurePackagesDiscovered,
package_dir: Optional[dict] = None,
- root_dir: _Path = os.curdir,
+ root_dir: StrPath = os.curdir,
):
super().__init__(target_obj, options, ignore_option_errors, ensure_discovered)
self.package_dir = package_dir
diff --git a/contrib/python/setuptools/py3/setuptools/discovery.py b/contrib/python/setuptools/py3/setuptools/discovery.py
index 50a948750f..571be12bf4 100644
--- a/contrib/python/setuptools/py3/setuptools/discovery.py
+++ b/contrib/python/setuptools/py3/setuptools/discovery.py
@@ -51,15 +51,14 @@ from typing import (
Mapping,
Optional,
Tuple,
- Union,
)
import _distutils_hack.override # noqa: F401
+from ._path import StrPath
from distutils import log
from distutils.util import convert_path
-_Path = Union[str, os.PathLike]
StrIter = Iterator[str]
chain_iter = itertools.chain.from_iterable
@@ -68,7 +67,7 @@ if TYPE_CHECKING:
from setuptools import Distribution # noqa
-def _valid_name(path: _Path) -> bool:
+def _valid_name(path: StrPath) -> bool:
# Ignore invalid names that cannot be imported directly
return os.path.basename(path).isidentifier()
@@ -98,7 +97,7 @@ class _Finder:
@classmethod
def find(
cls,
- where: _Path = '.',
+ where: StrPath = '.',
exclude: Iterable[str] = (),
include: Iterable[str] = ('*',),
) -> List[str]:
@@ -131,7 +130,7 @@ class _Finder:
)
@classmethod
- def _find_iter(cls, where: _Path, exclude: _Filter, include: _Filter) -> StrIter:
+ def _find_iter(cls, where: StrPath, exclude: _Filter, include: _Filter) -> StrIter:
raise NotImplementedError
@@ -143,7 +142,7 @@ class PackageFinder(_Finder):
ALWAYS_EXCLUDE = ("ez_setup", "*__pycache__")
@classmethod
- def _find_iter(cls, where: _Path, exclude: _Filter, include: _Filter) -> StrIter:
+ def _find_iter(cls, where: StrPath, exclude: _Filter, include: _Filter) -> StrIter:
"""
All the packages found in 'where' that pass the 'include' filter, but
not the 'exclude' filter.
@@ -175,14 +174,14 @@ class PackageFinder(_Finder):
dirs.append(dir)
@staticmethod
- def _looks_like_package(path: _Path, _package_name: str) -> bool:
+ def _looks_like_package(path: StrPath, _package_name: str) -> bool:
"""Does a directory look like a package?"""
return os.path.isfile(os.path.join(path, '__init__.py'))
class PEP420PackageFinder(PackageFinder):
@staticmethod
- def _looks_like_package(_path: _Path, _package_name: str) -> bool:
+ def _looks_like_package(_path: StrPath, _package_name: str) -> bool:
return True
@@ -192,7 +191,7 @@ class ModuleFinder(_Finder):
"""
@classmethod
- def _find_iter(cls, where: _Path, exclude: _Filter, include: _Filter) -> StrIter:
+ def _find_iter(cls, where: StrPath, exclude: _Filter, include: _Filter) -> StrIter:
for file in glob(os.path.join(where, "*.py")):
module, _ext = os.path.splitext(os.path.basename(file))
@@ -255,7 +254,7 @@ class FlatLayoutPackageFinder(PEP420PackageFinder):
"""Reserved package names"""
@staticmethod
- def _looks_like_package(_path: _Path, package_name: str) -> bool:
+ def _looks_like_package(_path: StrPath, package_name: str) -> bool:
names = package_name.split('.')
# Consider PEP 561
root_pkg_is_valid = names[0].isidentifier() or names[0].endswith("-stubs")
@@ -292,7 +291,7 @@ class FlatLayoutModuleFinder(ModuleFinder):
"""Reserved top-level module names"""
-def _find_packages_within(root_pkg: str, pkg_dir: _Path) -> List[str]:
+def _find_packages_within(root_pkg: str, pkg_dir: StrPath) -> List[str]:
nested = PEP420PackageFinder.find(pkg_dir)
return [root_pkg] + [".".join((root_pkg, n)) for n in nested]
@@ -325,7 +324,7 @@ class ConfigDiscovery:
self._skip_ext_modules = True
@property
- def _root_dir(self) -> _Path:
+ def _root_dir(self) -> StrPath:
# The best is to wait until `src_root` is set in dist, before using _root_dir.
return self.dist.src_root or os.curdir
@@ -551,7 +550,7 @@ def remove_stubs(packages: List[str]) -> List[str]:
def find_parent_package(
- packages: List[str], package_dir: Mapping[str, str], root_dir: _Path
+ packages: List[str], package_dir: Mapping[str, str], root_dir: StrPath
) -> Optional[str]:
"""Find the parent package that is not a namespace."""
packages = sorted(packages, key=len)
@@ -575,7 +574,7 @@ def find_parent_package(
def find_package_path(
- name: str, package_dir: Mapping[str, str], root_dir: _Path
+ name: str, package_dir: Mapping[str, str], root_dir: StrPath
) -> str:
"""Given a package name, return the path where it should be found on
disk, considering the ``package_dir`` option.
@@ -608,7 +607,7 @@ def find_package_path(
return os.path.join(root_dir, *parent.split("/"), *parts)
-def construct_package_dir(packages: List[str], package_path: _Path) -> Dict[str, str]:
+def construct_package_dir(packages: List[str], package_path: StrPath) -> Dict[str, str]:
parent_pkgs = remove_nested_packages(packages)
prefix = Path(package_path).parts
return {pkg: "/".join([*prefix, *pkg.split(".")]) for pkg in parent_pkgs}
diff --git a/contrib/python/setuptools/py3/setuptools/dist.py b/contrib/python/setuptools/py3/setuptools/dist.py
index d5787ed474..6350e38100 100644
--- a/contrib/python/setuptools/py3/setuptools/dist.py
+++ b/contrib/python/setuptools/py3/setuptools/dist.py
@@ -10,7 +10,7 @@ import sys
from contextlib import suppress
from glob import iglob
from pathlib import Path
-from typing import List, Optional, Set
+from typing import TYPE_CHECKING, Dict, List, MutableMapping, Optional, Set, Tuple
import distutils.cmd
import distutils.command
@@ -202,7 +202,11 @@ def check_packages(dist, attr, value):
)
-_Distribution = get_unpatched(distutils.core.Distribution)
+if TYPE_CHECKING:
+ # Work around a mypy issue where type[T] can't be used as a base: https://github.com/python/mypy/issues/10962
+ _Distribution = distutils.core.Distribution
+else:
+ _Distribution = get_unpatched(distutils.core.Distribution)
class Distribution(_Distribution):
@@ -283,12 +287,12 @@ class Distribution(_Distribution):
dist._version = _normalization.safe_version(str(attrs['version']))
self._patched_dist = dist
- def __init__(self, attrs=None):
+ def __init__(self, attrs: Optional[MutableMapping] = None) -> None:
have_package_data = hasattr(self, "package_data")
if not have_package_data:
- self.package_data = {}
+ self.package_data: Dict[str, List[str]] = {}
attrs = attrs or {}
- self.dist_files = []
+ self.dist_files: List[Tuple[str, str, str]] = []
# Filter-out setuptools' specific options.
self.src_root = attrs.pop("src_root", None)
self.patch_missing_pkg_info(attrs)
@@ -381,7 +385,7 @@ class Distribution(_Distribution):
k: list(map(str, _reqs.parse(v or []))) for k, v in extras_require.items()
}
- def _finalize_license_files(self):
+ def _finalize_license_files(self) -> None:
"""Compute names of all license files which should be included."""
license_files: Optional[List[str]] = self.metadata.license_files
patterns: List[str] = license_files if license_files else []
@@ -394,7 +398,7 @@ class Distribution(_Distribution):
# Default patterns match the ones wheel uses
# See https://wheel.readthedocs.io/en/stable/user_guide.html
# -> 'Including license files in the generated wheel file'
- patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')
+ patterns = ['LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*']
self.metadata.license_files = list(
unique_everseen(self._expand_patterns(patterns))
diff --git a/contrib/python/setuptools/py3/setuptools/extension.py b/contrib/python/setuptools/py3/setuptools/extension.py
index 58c023f6b4..8caad78d4b 100644
--- a/contrib/python/setuptools/py3/setuptools/extension.py
+++ b/contrib/python/setuptools/py3/setuptools/extension.py
@@ -3,6 +3,7 @@ import functools
import distutils.core
import distutils.errors
import distutils.extension
+from typing import TYPE_CHECKING
from .monkey import get_unpatched
@@ -23,8 +24,11 @@ def _have_cython():
# for compatibility
have_pyrex = _have_cython
-
-_Extension = get_unpatched(distutils.core.Extension)
+if TYPE_CHECKING:
+ # Work around a mypy issue where type[T] can't be used as a base: https://github.com/python/mypy/issues/10962
+ _Extension = distutils.core.Extension
+else:
+ _Extension = get_unpatched(distutils.core.Extension)
class Extension(_Extension):
diff --git a/contrib/python/setuptools/py3/setuptools/monkey.py b/contrib/python/setuptools/py3/setuptools/monkey.py
index da0993506c..fd07d91dec 100644
--- a/contrib/python/setuptools/py3/setuptools/monkey.py
+++ b/contrib/python/setuptools/py3/setuptools/monkey.py
@@ -8,11 +8,14 @@ import platform
import sys
import types
from importlib import import_module
+from typing import List, TypeVar
import distutils.filelist
-__all__ = []
+_T = TypeVar("_T")
+
+__all__: List[str] = []
"""
Everything is private. Contact the project team
if you think you need this functionality.
@@ -33,7 +36,7 @@ def _get_mro(cls):
return inspect.getmro(cls)
-def get_unpatched(item):
+def get_unpatched(item: _T) -> _T:
lookup = (
get_unpatched_class
if isinstance(item, type)
diff --git a/contrib/python/setuptools/py3/setuptools/msvc.py b/contrib/python/setuptools/py3/setuptools/msvc.py
index 53fe7b0de1..b2a0f2bebb 100644
--- a/contrib/python/setuptools/py3/setuptools/msvc.py
+++ b/contrib/python/setuptools/py3/setuptools/msvc.py
@@ -20,9 +20,11 @@ import platform
import itertools
import subprocess
import distutils.errors
+from typing import Dict, TYPE_CHECKING
from setuptools.extern.more_itertools import unique_everseen
-if platform.system() == 'Windows':
+# https://github.com/python/mypy/issues/8166
+if not TYPE_CHECKING and platform.system() == 'Windows':
import winreg
from os import environ
else:
@@ -34,7 +36,7 @@ else:
HKEY_LOCAL_MACHINE = None
HKEY_CLASSES_ROOT = None
- environ = dict()
+ environ: Dict[str, str] = dict()
def _msvc14_find_vc2015():
diff --git a/contrib/python/setuptools/py3/setuptools/namespaces.py b/contrib/python/setuptools/py3/setuptools/namespaces.py
index e8f2941d45..0185d55f94 100644
--- a/contrib/python/setuptools/py3/setuptools/namespaces.py
+++ b/contrib/python/setuptools/py3/setuptools/namespaces.py
@@ -2,6 +2,8 @@ import os
from distutils import log
import itertools
+from .compat import py39
+
flatten = itertools.chain.from_iterable
@@ -23,7 +25,8 @@ class Installer:
list(lines)
return
- with open(filename, 'wt') as f:
+ with open(filename, 'wt', encoding=py39.LOCALE_ENCODING) as f:
+ # Requires encoding="locale" instead of "utf-8" (python/cpython#77102).
f.writelines(lines)
def uninstall_namespaces(self):
diff --git a/contrib/python/setuptools/py3/setuptools/sandbox.py b/contrib/python/setuptools/py3/setuptools/sandbox.py
index 7634b1320b..6c095e029e 100644
--- a/contrib/python/setuptools/py3/setuptools/sandbox.py
+++ b/contrib/python/setuptools/py3/setuptools/sandbox.py
@@ -9,6 +9,7 @@ import contextlib
import pickle
import textwrap
import builtins
+from typing import Union, List
import pkg_resources
from distutils.errors import DistutilsError
@@ -19,7 +20,7 @@ if sys.platform.startswith('java'):
else:
_os = sys.modules[os.name]
try:
- _file = file
+ _file = file # type: ignore[name-defined] # Check for global variable
except NameError:
_file = None
_open = open
@@ -298,7 +299,7 @@ class AbstractSandbox:
with self:
return func()
- def _mk_dual_path_wrapper(name):
+ def _mk_dual_path_wrapper(name: str): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
original = getattr(_os, name)
def wrap(self, src, dst, *args, **kw):
@@ -312,7 +313,7 @@ class AbstractSandbox:
if hasattr(_os, name):
locals()[name] = _mk_dual_path_wrapper(name)
- def _mk_single_path_wrapper(name, original=None):
+ def _mk_single_path_wrapper(name: str, original=None): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
original = original or getattr(_os, name)
def wrap(self, path, *args, **kw):
@@ -349,7 +350,7 @@ class AbstractSandbox:
if hasattr(_os, name):
locals()[name] = _mk_single_path_wrapper(name)
- def _mk_single_with_return(name):
+ def _mk_single_with_return(name: str): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
original = getattr(_os, name)
def wrap(self, path, *args, **kw):
@@ -364,7 +365,7 @@ class AbstractSandbox:
if hasattr(_os, name):
locals()[name] = _mk_single_with_return(name)
- def _mk_query(name):
+ def _mk_query(name: str): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
original = getattr(_os, name)
def wrap(self, *args, **kw):
@@ -424,7 +425,7 @@ class DirectorySandbox(AbstractSandbox):
"tempnam",
])
- _exception_patterns = []
+ _exception_patterns: List[Union[str, re.Pattern]] = []
"exempt writing to paths that match the pattern"
def __init__(self, sandbox, exceptions=_EXCEPTIONS):
diff --git a/contrib/python/setuptools/py3/ya.make b/contrib/python/setuptools/py3/ya.make
index 4210fba192..4e2b62dbce 100644
--- a/contrib/python/setuptools/py3/ya.make
+++ b/contrib/python/setuptools/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(69.1.1)
+VERSION(69.2.0)
LICENSE(MIT)
@@ -216,6 +216,7 @@ PY_SRCS(
setuptools/compat/__init__.py
setuptools/compat/py310.py
setuptools/compat/py311.py
+ setuptools/compat/py39.py
setuptools/config/__init__.py
setuptools/config/_apply_pyprojecttoml.py
setuptools/config/_validate_pyproject/__init__.py