diff --git a/distutils/command/build_py.py b/distutils/command/build_py.py index a20b076f..d2a4fd12 100644 --- a/distutils/command/build_py.py +++ b/distutils/command/build_py.py @@ -360,6 +360,10 @@ def build_modules(self) -> None: self.build_module(module, module_file, package) def build_packages(self) -> None: + if self.packages is None: + raise TypeError( + f"{type(self).__name__}.packages is None. Is the Distribution missing packages ?" + ) for package in self.packages: # Get list of (package, module, module_file) tuples based on # scanning the package directory. 'package' is only included diff --git a/distutils/compilers/C/base.py b/distutils/compilers/C/base.py index 93385e13..8128b483 100644 --- a/distutils/compilers/C/base.py +++ b/distutils/compilers/C/base.py @@ -70,7 +70,7 @@ class Compiler: # dictionary (see below -- used by the 'new_compiler()' factory # function) -- authors of new compiler interface classes are # responsible for updating 'compiler_class'! - compiler_type: ClassVar[str] = None # type: ignore[assignment] + compiler_type: ClassVar[str] = None # pyright: ignore[reportAssignmentType] # XXX things not handled by this compiler abstraction model: # * client can't provide additional options for a compiler, diff --git a/distutils/dist.py b/distutils/dist.py index b9552a8b..90101e37 100644 --- a/distutils/dist.py +++ b/distutils/dist.py @@ -1198,7 +1198,7 @@ def _read_list(name): self.description = _read_field('summary') if 'keywords' in msg: - self.keywords = _read_field('keywords').split(',') + self.keywords = _read_field('keywords').split(',') # type:ignore[union-attr] # Manually checked self.platforms = _read_list('platform') self.classifiers = _read_list('classifier') diff --git a/distutils/filelist.py b/distutils/filelist.py index 70dc0fde..628cbb4f 100644 --- a/distutils/filelist.py +++ b/distutils/filelist.py @@ -261,6 +261,7 @@ def include_pattern( # delayed loading of allfiles list if self.allfiles is None: self.findall() + assert self.allfiles is not None for name in self.allfiles: if pattern_re.search(name): diff --git a/distutils/sysconfig.py b/distutils/sysconfig.py index 7ddc869a..fe2d3270 100644 --- a/distutils/sysconfig.py +++ b/distutils/sysconfig.py @@ -324,6 +324,16 @@ def customize_compiler(compiler: CCompiler) -> None: 'AR', 'ARFLAGS', ) + assert isinstance(cc, str) + assert isinstance(cxx, str) + assert isinstance(cflags, str) + assert isinstance(ccshared, str) + assert isinstance(ldshared, str) + assert isinstance(ldcxxshared, str) + assert isinstance(shlib_suffix, str) + assert isinstance(ar_flags, str) + ar = os.environ.get('AR', ar) + assert isinstance(ar, str) cxxflags = cflags @@ -354,8 +364,6 @@ def customize_compiler(compiler: CCompiler) -> None: ldshared = _add_flags(ldshared, 'CPP') ldcxxshared = _add_flags(ldcxxshared, 'CPP') - ar = os.environ.get('AR', ar) - archiver = ar + ' ' + os.environ.get('ARFLAGS', ar_flags) cc_cmd = cc + ' ' + cflags cxx_cmd = cxx + ' ' + cxxflags diff --git a/distutils/util.py b/distutils/util.py index 17e86fed..ffb41042 100644 --- a/distutils/util.py +++ b/distutils/util.py @@ -232,14 +232,9 @@ def grok_environment_error(exc: object, prefix: str = "error: ") -> str: # Needed by 'split_quoted()' -_wordchars_re = _squote_re = _dquote_re = None - - -def _init_regex(): - global _wordchars_re, _squote_re, _dquote_re - _wordchars_re = re.compile(rf'[^\\\'\"{string.whitespace} ]*') - _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") - _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') +_wordchars_re = re.compile(rf'[^\\\'\"{string.whitespace} ]*') +_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") +_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') def split_quoted(s: str) -> list[str]: @@ -256,8 +251,6 @@ def split_quoted(s: str) -> list[str]: # This is a nice algorithm for splitting up a single string, since it # doesn't require character-by-character examination. It was a little # bit of a brain-bender to get it working right, though... - if _wordchars_re is None: - _init_regex() s = s.strip() words = [] @@ -265,6 +258,7 @@ def split_quoted(s: str) -> list[str]: while s: m = _wordchars_re.match(s, pos) + assert m is not None end = m.end() if end == len(s): words.append(s[:end]) @@ -305,9 +299,6 @@ def split_quoted(s: str) -> list[str]: return words -# split_quoted () - - def execute( func: Callable[[Unpack[_Ts]], object], args: tuple[Unpack[_Ts]], diff --git a/mypy.ini b/mypy.ini index 146222a5..26b04200 100644 --- a/mypy.ini +++ b/mypy.ini @@ -16,20 +16,21 @@ disable_error_code = # local + # Code that is too dynamic using variable command names; + # and code that uses platform checks mypy doesn't understand + attr-defined, + # These reveal issues in distutils/_modified.py that should be fixed + return-value, + type-var, # TODO: Resolve and re-enable these gradually operator, - attr-defined, arg-type, assignment, call-overload, - return-value, index, - type-var, func-returns-value, - union-attr, str-bytes-safe, misc, - has-type, # stdlib's test module is not typed on typeshed [mypy-test.*]