Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix most mypy attr-defined & pyright reportAttributeAccessIssue by explicitly defining attributes on classes #4535

Merged
merged 3 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ exclude = (?x)(
# Too many false-positives
disable_error_code = overload-overlap

# Ignoring attr-defined because setuptools wraps a lot of distutils classes, adding new attributes,
# w/o updating all the attributes and return types from the base classes for type-checkers to understand
# Especially with setuptools.dist.command vs distutils.dist.command vs setuptools._distutils.dist.command
# DistributionMetadata.license_files and DistributionMetadata.license_file
# are dynamically patched in setuptools/_core_metadata.py
# and no DistributionMetadata subclass exists in setuptools
[mypy-setuptools.*]
disable_error_code = attr-defined

Expand Down
2 changes: 2 additions & 0 deletions setuptools/command/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from distutils.sysconfig import customize_compiler, get_config_var
from distutils import log

from setuptools.dist import Distribution
from setuptools.errors import BaseError
from setuptools.extension import Extension, Library

Expand Down Expand Up @@ -84,6 +85,7 @@ def get_abi3_suffix():


class build_ext(_build_ext):
distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
editable_mode: bool = False
inplace: bool = False

Expand Down
4 changes: 3 additions & 1 deletion setuptools/command/build_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
from typing import Iterable, Iterator

from more_itertools import unique_everseen
from ..warnings import SetuptoolsDeprecationWarning

from ..dist import Distribution
from ..warnings import SetuptoolsDeprecationWarning

_IMPLICIT_DATA_FILES = ('*.pyi', 'py.typed')

Expand All @@ -34,6 +35,7 @@ class build_py(orig.build_py):
'py_modules' and 'packages' in the same setup operation.
"""

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
editable_mode: bool = False
existing_egg_info_dir: str | None = None #: Private API, internal use only.

Expand Down
1 change: 1 addition & 0 deletions setuptools/command/editable_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ def run(self):
self._create_wheel_file(bdist_wheel)
except Exception:
traceback.print_exc()
# TODO: Fix false-positive [attr-defined] in typeshed
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

project = self.distribution.name or self.distribution.get_name()
_DebuggingTips.emit(project=project)
raise
Expand Down
6 changes: 4 additions & 2 deletions setuptools/command/egg_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
from setuptools.command.sdist import walk_revctrl
from setuptools.command.setopt import edit_config
from setuptools.command import bdist_egg
from setuptools.dist import Distribution
import setuptools.unicode_utils as unicode_utils
from setuptools.glob import glob

import packaging
import packaging.requirements
import packaging.version
from ..warnings import SetuptoolsDeprecationWarning


PY_MAJOR = '{}.{}'.format(*sys.version_info)


Expand Down Expand Up @@ -520,6 +521,7 @@ def _safe_path(self, path):


class manifest_maker(sdist):
distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
template = "MANIFEST.in"

def initialize_options(self):
Expand Down
3 changes: 3 additions & 0 deletions setuptools/command/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from typing import Any, ClassVar, cast

import setuptools
from ..dist import Distribution
from ..warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning
from .bdist_egg import bdist_egg as bdist_egg_cls

Expand All @@ -20,6 +21,8 @@
class install(orig.install):
"""Use easy_install to install the package, w/dependencies"""

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution

user_options = orig.install.user_options + [
('old-and-unmanageable', None, "Try not to use this!"),
(
Expand Down
4 changes: 4 additions & 0 deletions setuptools/command/install_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
import sys
from itertools import product, starmap
import distutils.command.install_lib as orig

from .._path import StrPath
from ..dist import Distribution


class install_lib(orig.install_lib):
"""Don't add compiled flags to filenames of non-Python files"""

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution

def run(self):
self.build()
outfiles = self.install()
Expand Down
3 changes: 3 additions & 0 deletions setuptools/command/install_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
import sys

from .._path import ensure_directory
from ..dist import Distribution


class install_scripts(orig.install_scripts):
"""Do normal script install, plus any egg_info wrapper scripts"""

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution

def initialize_options(self):
orig.install_scripts.initialize_options(self)
self.no_ep = False
Expand Down
2 changes: 2 additions & 0 deletions setuptools/command/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from itertools import chain

from .._importlib import metadata
from ..dist import Distribution
from .build import _ORIGINAL_SUBCOMMANDS

_default_revctrl = list
Expand Down Expand Up @@ -43,6 +44,7 @@ class sdist(orig.sdist):
),
]

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
negative_opt = {}

README_EXTENSIONS = ['', '.rst', '.txt', '.md']
Expand Down
3 changes: 3 additions & 0 deletions setuptools/command/upload.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from distutils import log
from distutils.command import upload as orig

from setuptools.dist import Distribution
from setuptools.errors import RemovedCommandError


class upload(orig.upload):
"""Formerly used to upload packages to PyPI."""

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution

def run(self):
msg = (
"The upload command has been removed, use twine to upload "
Expand Down
2 changes: 1 addition & 1 deletion setuptools/config/pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def read_configuration(
# the default would be an improvement.
# `ini2toml` backfills include_package_data=False when nothing is explicitly given,
# therefore setting a default here is backwards compatible.
if dist and getattr(dist, "include_package_data", None) is not None:
if dist and dist.include_package_data is not None:
setuptools_table.setdefault("include-package-data", dist.include_package_data)
else:
setuptools_table.setdefault("include-package-data", True)
Expand Down
2 changes: 2 additions & 0 deletions setuptools/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ def __init__(self, attrs: MutableMapping | None = None) -> None:
self.package_data: dict[str, list[str]] = {}
attrs = attrs or {}
self.dist_files: list[tuple[str, str, str]] = []
self.include_package_data: bool | None = None
self.exclude_package_data: dict[str, list[str]] | None = None
# Filter-out setuptools' specific options.
self.src_root = attrs.pop("src_root", None)
self.dependency_links = attrs.pop('dependency_links', [])
Expand Down
8 changes: 8 additions & 0 deletions setuptools/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ class Extension(_Extension):
specified on Windows. (since v63)
"""

# These 4 are set and used in setuptools/command/build_ext.py
# The lack of a default value and risk of `AttributeError` is purposeful
# to avoid people forgetting to call finalize_options if they modify the extension list
abravalheri marked this conversation as resolved.
Show resolved Hide resolved
_full_name: str #: Private API, internal use only.
_links_to_dynamic: bool #: Private API, internal use only.
_needs_stub: bool #: Private API, internal use only.
_file_name: str #: Private API, internal use only.

def __init__(self, name, sources, *args, **kw):
# The *args is needed for compatibility as calls may use positional
# arguments. py_limited_api may be set only via keyword.
Expand Down
9 changes: 4 additions & 5 deletions setuptools/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@

__all__ = ['fail_on_ascii']

locale_encoding = (
locale.getencoding()
if sys.version_info >= (3, 11)
else locale.getpreferredencoding(False)
)
if sys.version_info >= (3, 11):
locale_encoding = locale.getencoding()
else:
locale_encoding = locale.getpreferredencoding(False)
is_ascii = locale_encoding == 'ANSI_X3.4-1968'
fail_on_ascii = pytest.mark.xfail(is_ascii, reason="Test fails in this locale")
1 change: 1 addition & 0 deletions setuptools/tests/test_build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ def get_build_ext_cmd(self, optional: bool, **opts):
dist = Distribution(dict(ext_modules=[extension]))
dist.script_name = 'setup.py'
cmd = build_ext(dist)
# TODO: False-positive [attr-defined], raise upstream
vars(cmd).update(build_lib=".build/lib", build_temp=".build/tmp", **opts)
cmd.ensure_finalized()
return cmd
Expand Down
Loading