Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package mypy for openSUSE:Factory checked in at 2022-01-15 21:45:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mypy (Old) and /work/SRC/openSUSE:Factory/.mypy.new.1892 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mypy" Sat Jan 15 21:45:14 2022 rev:25 rq:946495 version:0.931 Changes: -------- --- /work/SRC/openSUSE:Factory/mypy/mypy.changes 2022-01-05 15:44:33.906257364 +0100 +++ /work/SRC/openSUSE:Factory/.mypy.new.1892/mypy.changes 2022-01-15 21:45:41.869629912 +0100 @@ -1,0 +2,21 @@ +Fri Jan 7 17:31:27 UTC 2022 - Sebastian Wagner <sebix+novell....@sebix.at> + +- Update to version 0.931: + - Fixes to Regressions + - Fix mypyc binary wheel (Michael R. Crusoe, PR 11862) + - Revert to treating multi-line strings as a single value for exclude in TOML files (Matt Bogosian, PR 11828) + - Revert to treating exclude in .ini as a single value (Matt Bogosian, PR 11881) + - Fix __slots__ regression (Nikita Sobolev, PR 11824) + - Fix regression with __module__ and similar non-final Enum attributes (Nikita Sobolev, PR 11823) + - Fix regression when a contextmanager yields a generic function (Anthony Sottile, PR 11870) + - Fix __reduce__ regression (Shantanu, PR 11866) + - Fix NoReturn type aliases (Nikita Sobolev, PR 11912) + - Fix regression in None handling with --no-strict-optional (Nikita Sobolev, PR 11717) + - Fix crash related to generics (Nikita Sobolev, PR 11924) + - Restore removed builtin_type() plugin API method (Jukka Lehtosalo, PR 11932) + - Other Fixes + - Always allow the use of type[T] in stubs (Nikita Sobolev, PR 11863) + - Fix PEP 585 type aliases in stubs (Shantanu, PR 11918) + - Fix bug with literal types in stubtest (Nikita Sobolev, PR 11931) + +------------------------------------------------------------------- Old: ---- mypy-0.930.tar.gz New: ---- mypy-0.931.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mypy.spec ++++++ --- /var/tmp/diff_new_pack.RUfyk6/_old 2022-01-15 21:45:42.341630162 +0100 +++ /var/tmp/diff_new_pack.RUfyk6/_new 2022-01-15 21:45:42.349630166 +0100 @@ -1,7 +1,7 @@ # # spec file for package mypy # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -21,7 +21,7 @@ %define skip_python2 1 %define typed_ast_version 1.5.1 Name: mypy -Version: 0.930 +Version: 0.931 Release: 0 Summary: Optional static typing for Python License: MIT ++++++ mypy-0.930.tar.gz -> mypy-0.931.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/PKG-INFO new/mypy-0.931/PKG-INFO --- old/mypy-0.930/PKG-INFO 2021-12-22 15:56:21.000000000 +0100 +++ new/mypy-0.931/PKG-INFO 2022-01-07 15:59:24.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: mypy -Version: 0.930 +Version: 0.931 Summary: Optional static typing for Python Home-page: http://www.mypy-lang.org/ Author: Jukka Lehtosalo diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/docs/source/config_file.rst new/mypy-0.931/docs/source/config_file.rst --- old/mypy-0.930/docs/source/config_file.rst 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/docs/source/config_file.rst 2022-01-07 15:58:59.000000000 +0100 @@ -197,23 +197,62 @@ .. confval:: exclude - :type: newline separated list of regular expressions + :type: regular expression - A newline list of regular expression that matches file names, directory names and paths + A regular expression that matches file names, directory names and paths which mypy should ignore while recursively discovering files to check. Use forward slashes on all platforms. .. code-block:: ini [mypy] - exclude = - ^file1\.py$ - ^file2\.py$ + exclude = (?x)( + ^one\.py$ # files named "one.py" + | two\.pyi$ # or files ending with "two.pyi" + | ^three\. # or files starting with "three." + ) + + Crafting a single regular expression that excludes multiple files while remaining + human-readable can be a challenge. The above example demonstrates one approach. + ``(?x)`` enables the ``VERBOSE`` flag for the subsequent regular expression, which + `ignores most whitespace and supports comments`__. The above is equivalent to: + ``(^one\.py$|two\.pyi$|^three\.)``. + + .. __: https://docs.python.org/3/library/re.html#re.X For more details, see :option:`--exclude <mypy --exclude>`. This option may only be set in the global section (``[mypy]``). + .. note:: + + Note that the TOML equivalent differs slightly. It can be either a single string + (including a multi-line string) -- which is treated as a single regular + expression -- or an array of such strings. The following TOML examples are + equivalent to the above INI example. + + Array of strings: + + .. code-block:: toml + + [tool.mypy] + exclude = [ + "^file1\\.py$", # TOML's double-quoted strings require escaping backslashes + '^file2\.py$', # but TOML's single-quoted strings do not + ] + + A single, multi-line string: + + .. code-block:: toml + + [tool.mypy] + exclude = '''(?x)( + ^file1\.py$ + |^file2\.py$, + )''' + + See :ref:`using-a-pyproject-toml`. + .. confval:: namespace_packages :type: boolean @@ -907,6 +946,8 @@ Controls how much debug output will be generated. Higher numbers are more verbose. +.. _using-a-pyproject-toml: + Using a pyproject.toml file *************************** @@ -965,6 +1006,10 @@ python_version = "2.7" warn_return_any = true warn_unused_configs = true + exclude = [ + '^file1\.py$', # TOML literal string (single-quotes, no escaping necessary) + "^file2\\.py$", # TOML basic string (double-quotes, backslash and other characters need escaping) + ] # mypy per-module options: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/checker.py new/mypy-0.931/mypy/checker.py --- old/mypy-0.930/mypy/checker.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/checker.py 2022-01-07 15:58:59.000000000 +0100 @@ -4550,17 +4550,16 @@ self._check_for_truthy_type(original_vartype, node) vartype = try_expanding_sum_type_to_union(original_vartype, "builtins.bool") - if_type = true_only(vartype) # type: Type - else_type = false_only(vartype) # type: Type - ref = node # type: Expression + if_type = true_only(vartype) + else_type = false_only(vartype) if_map = ( - {ref: if_type} - if not isinstance(get_proper_type(if_type), UninhabitedType) + {node: if_type} + if not isinstance(if_type, UninhabitedType) else None ) else_map = ( - {ref: else_type} - if not isinstance(get_proper_type(else_type), UninhabitedType) + {node: else_type} + if not isinstance(else_type, UninhabitedType) else None ) return if_map, else_map diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/config_parser.py new/mypy-0.931/mypy/config_parser.py --- old/mypy-0.930/mypy/config_parser.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/config_parser.py 2022-01-07 15:58:59.000000000 +0100 @@ -57,6 +57,12 @@ return os.path.expandvars(os.path.expanduser(path)) +def str_or_array_as_list(v: Union[str, Sequence[str]]) -> List[str]: + if isinstance(v, str): + return [v.strip()] if v.strip() else [] + return [p.strip() for p in v if p.strip()] + + def split_and_match_files_list(paths: Sequence[str]) -> List[str]: """Take a list of files/directories (with support for globbing through the glob library). @@ -126,7 +132,7 @@ 'cache_dir': expand_path, 'python_executable': expand_path, 'strict': bool, - 'exclude': lambda s: [p.strip() for p in s.split('\n') if p.strip()], + 'exclude': lambda s: [s.strip()], } # Reuse the ini_config_types and overwrite the diff @@ -143,6 +149,7 @@ 'disable_error_code': try_split, 'enable_error_code': try_split, 'package_root': try_split, + 'exclude': str_or_array_as_list, }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/erasetype.py new/mypy-0.931/mypy/erasetype.py --- old/mypy-0.930/mypy/erasetype.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/erasetype.py 2022-01-07 15:58:59.000000000 +0100 @@ -41,8 +41,7 @@ return t def visit_erased_type(self, t: ErasedType) -> ProperType: - # Should not get here. - raise RuntimeError() + return t def visit_partial_type(self, t: PartialType) -> ProperType: # Should not get here. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/fastparse.py new/mypy-0.931/mypy/fastparse.py --- old/mypy-0.930/mypy/fastparse.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/fastparse.py 2022-01-07 15:58:59.000000000 +0100 @@ -40,6 +40,7 @@ from mypy.errors import Errors from mypy.options import Options from mypy.reachability import mark_block_unreachable +from mypy.util import bytes_to_human_readable_repr try: # pull this into a final variable to make mypyc be quiet about the @@ -1638,17 +1639,3 @@ if sv is not None: return "{}.{}".format(sv, n.attr) return None # Can't do it. - - -def bytes_to_human_readable_repr(b: bytes) -> str: - """Converts bytes into some human-readable representation. Unprintable - bytes such as the nul byte are escaped. For example: - - >>> b = bytes([102, 111, 111, 10, 0]) - >>> s = bytes_to_human_readable_repr(b) - >>> print(s) - foo\n\x00 - >>> print(repr(s)) - 'foo\\n\\x00' - """ - return repr(b)[2:-1] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/fastparse2.py new/mypy-0.931/mypy/fastparse2.py --- old/mypy-0.930/mypy/fastparse2.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/fastparse2.py 2022-01-07 15:58:59.000000000 +0100 @@ -47,10 +47,11 @@ from mypy import message_registry, errorcodes as codes from mypy.errors import Errors from mypy.fastparse import ( - TypeConverter, parse_type_comment, bytes_to_human_readable_repr, parse_type_ignore_tag, + TypeConverter, parse_type_comment, parse_type_ignore_tag, TYPE_IGNORE_PATTERN, INVALID_TYPE_IGNORE ) from mypy.options import Options +from mypy.util import bytes_to_human_readable_repr from mypy.reachability import mark_block_unreachable try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/plugin.py new/mypy-0.931/mypy/plugin.py --- old/mypy-0.930/mypy/plugin.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/plugin.py 2022-01-07 15:58:59.000000000 +0100 @@ -258,6 +258,12 @@ raise NotImplementedError @abstractmethod + def builtin_type(self, fully_qualified_name: str) -> Instance: + """Legacy function -- use named_type() instead.""" + # NOTE: Do not delete this since many plugins may still use it. + raise NotImplementedError + + @abstractmethod def named_type_or_none(self, fullname: str, args: Optional[List[Type]] = None) -> Optional[Instance]: """Construct an instance of a type with given type arguments. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/plugins/dataclasses.py new/mypy-0.931/mypy/plugins/dataclasses.py --- old/mypy-0.930/mypy/plugins/dataclasses.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/plugins/dataclasses.py 2022-01-07 15:58:59.000000000 +0100 @@ -221,9 +221,12 @@ self._ctx.reason, ) return - if info.slots is not None or info.names.get('__slots__'): + + generated_slots = {attr.name for attr in attributes} + if ((info.slots is not None and info.slots != generated_slots) + or info.names.get('__slots__')): # This means we have a slots conflict. - # Class explicitly specifies `__slots__` field. + # Class explicitly specifies a different `__slots__` field. # And `@dataclass(slots=True)` is used. # In runtime this raises a type error. self._ctx.api.fail( @@ -234,7 +237,7 @@ ) return - info.slots = {attr.name for attr in attributes} + info.slots = generated_slots def reset_init_only_vars(self, info: TypeInfo, attributes: List[DataclassAttribute]) -> None: """Remove init-only vars from the class and reset init var declarations.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/plugins/default.py new/mypy-0.931/mypy/plugins/default.py --- old/mypy-0.930/mypy/plugins/default.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/plugins/default.py 2022-01-07 15:58:59.000000000 +0100 @@ -15,7 +15,6 @@ from mypy.subtypes import is_subtype from mypy.typeops import make_simplified_union from mypy.checkexpr import is_literal_type_like -from mypy.checker import detach_callable class DefaultPlugin(Plugin): @@ -192,12 +191,12 @@ and isinstance(default_return, CallableType)): # The stub signature doesn't preserve information about arguments so # add them back here. - return detach_callable(default_return.copy_modified( + return default_return.copy_modified( arg_types=arg_type.arg_types, arg_kinds=arg_type.arg_kinds, arg_names=arg_type.arg_names, variables=arg_type.variables, - is_ellipsis_args=arg_type.is_ellipsis_args)) + is_ellipsis_args=arg_type.is_ellipsis_args) return ctx.default_return_type diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/semanal.py new/mypy-0.931/mypy/semanal.py --- old/mypy-0.930/mypy/semanal.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/semanal.py 2022-01-07 15:58:59.000000000 +0100 @@ -2245,6 +2245,12 @@ return True # Assignment color = Color['RED'] defines a variable, not an alias. return not rv.node.is_enum + if isinstance(rv.node, Var): + return rv.node.fullname in ( + 'typing.NoReturn', + 'typing_extensions.NoReturn', + 'mypy_extensions.NoReturn', + ) if isinstance(rv, NameExpr): n = self.lookup(rv.name, rv) @@ -2629,7 +2635,6 @@ self.plugin, self.options, self.is_typeshed_stub_file, - allow_new_syntax=self.is_stub_file, allow_placeholder=allow_placeholder, in_dynamic_func=dynamic, global_scope=global_scope) @@ -4084,6 +4089,7 @@ name = target.type.fullname if (alias.no_args and # this avoids bogus errors for already reported aliases name in get_nongen_builtins(self.options.python_version) and + not self.is_stub_file and not alias.normalized): self.fail(no_subscript_builtin_alias(name, propose_alt=False), expr) # ...or directly. @@ -4559,6 +4565,10 @@ return Instance(node, args) return Instance(node, [AnyType(TypeOfAny.unannotated)] * len(node.defn.type_vars)) + def builtin_type(self, fully_qualified_name: str) -> Instance: + """Legacy function -- use named_type() instead.""" + return self.named_type(fully_qualified_name) + def lookup_current_scope(self, name: str) -> Optional[SymbolTableNode]: if self.locals[-1] is not None: return self.locals[-1].get(name) @@ -5183,8 +5193,7 @@ allow_tuple_literal=allow_tuple_literal, report_invalid_types=report_invalid_types, allow_placeholder=allow_placeholder, - allow_required=allow_required, - allow_new_syntax=self.is_stub_file) + allow_required=allow_required) tpan.in_dynamic_func = bool(self.function_stack and self.function_stack[-1].is_dynamic()) tpan.global_scope = not self.type and not self.function_stack return tpan diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/semanal_enum.py new/mypy-0.931/mypy/semanal_enum.py --- old/mypy-0.930/mypy/semanal_enum.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/semanal_enum.py 2022-01-07 15:58:59.000000000 +0100 @@ -21,6 +21,8 @@ )) ENUM_SPECIAL_PROPS: Final = frozenset(( 'name', 'value', '_name_', '_value_', '_order_', '__order__', + # Also attributes from `object`: + '__module__', '__annotations__', '__doc__', '__slots__', '__dict__', )) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/stubtest.py new/mypy-0.931/mypy/stubtest.py --- old/mypy-0.930/mypy/stubtest.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/stubtest.py 2022-01-07 15:58:59.000000000 +0100 @@ -25,7 +25,7 @@ from mypy import nodes from mypy.config_parser import parse_config_file from mypy.options import Options -from mypy.util import FancyFormatter +from mypy.util import FancyFormatter, bytes_to_human_readable_repr class Missing: @@ -942,6 +942,7 @@ ): # Pretend Literal[0, 1] is a subtype of bool to avoid unhelpful errors. return True + with mypy.state.strict_optional_set(True): return mypy.subtypes.is_subtype(left, right) @@ -1029,17 +1030,19 @@ return mypy.types.TupleType(items, fallback) fallback = mypy.types.Instance(type_info, [anytype() for _ in type_info.type_vars]) - try: - # Literals are supposed to be only bool, int, str, bytes or enums, but this seems to work - # well (when not using mypyc, for which bytes and enums are also problematic). - return mypy.types.LiteralType( - value=runtime, - fallback=fallback, - ) - except TypeError: - # Ask for forgiveness if we're using mypyc. + + value: Union[bool, int, str] + if isinstance(runtime, bytes): + value = bytes_to_human_readable_repr(runtime) + elif isinstance(runtime, enum.Enum): + value = runtime.name + elif isinstance(runtime, (bool, int, str)): + value = runtime + else: return fallback + return mypy.types.LiteralType(value=value, fallback=fallback) + _all_stubs: Dict[str, nodes.MypyFile] = {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/subtypes.py new/mypy-0.931/mypy/subtypes.py --- old/mypy-0.930/mypy/subtypes.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/subtypes.py 2022-01-07 15:58:59.000000000 +0100 @@ -1171,6 +1171,7 @@ def covers_at_runtime(item: Type, supertype: Type, ignore_promotions: bool) -> bool: """Will isinstance(item, supertype) always return True at runtime?""" item = get_proper_type(item) + supertype = get_proper_type(supertype) # Since runtime type checks will ignore type arguments, erase the types. supertype = erase_type(supertype) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/test/testreports.py new/mypy-0.931/mypy/test/testreports.py --- old/mypy-0.930/mypy/test/testreports.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/test/testreports.py 2022-01-07 15:58:59.000000000 +0100 @@ -4,8 +4,6 @@ from mypy.test.helpers import Suite, assert_equal from mypy.report import CoberturaPackage, get_line_rate -import lxml.etree as etree # type: ignore - class CoberturaReportSuite(Suite): def test_get_line_rate(self) -> None: @@ -13,6 +11,8 @@ assert_equal('0.3333', get_line_rate(1, 3)) def test_as_xml(self) -> None: + import lxml.etree as etree # type: ignore + cobertura_package = CoberturaPackage('foobar') cobertura_package.covered_lines = 21 cobertura_package.total_lines = 42 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/test/teststubtest.py new/mypy-0.931/mypy/test/teststubtest.py --- old/mypy-0.930/mypy/test/teststubtest.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/test/teststubtest.py 2022-01-07 15:58:59.000000000 +0100 @@ -750,6 +750,84 @@ error="X.__init__" ) + @collect_cases + def test_good_literal(self) -> Iterator[Case]: + yield Case( + stub=r""" + from typing_extensions import Literal + + import enum + class Color(enum.Enum): + RED: int + + NUM: Literal[1] + CHAR: Literal['a'] + FLAG: Literal[True] + NON: Literal[None] + BYT1: Literal[b'abc'] + BYT2: Literal[b'\x90'] + ENUM: Literal[Color.RED] + """, + runtime=r""" + import enum + class Color(enum.Enum): + RED = 3 + + NUM = 1 + CHAR = 'a' + NON = None + FLAG = True + BYT1 = b"abc" + BYT2 = b'\x90' + ENUM = Color.RED + """, + error=None, + ) + + @collect_cases + def test_bad_literal(self) -> Iterator[Case]: + yield Case("from typing_extensions import Literal", "", None) # dummy case + yield Case( + stub="INT_FLOAT_MISMATCH: Literal[1]", + runtime="INT_FLOAT_MISMATCH = 1.0", + error="INT_FLOAT_MISMATCH", + ) + yield Case( + stub="WRONG_INT: Literal[1]", + runtime="WRONG_INT = 2", + error="WRONG_INT", + ) + yield Case( + stub="WRONG_STR: Literal['a']", + runtime="WRONG_STR = 'b'", + error="WRONG_STR", + ) + yield Case( + stub="BYTES_STR_MISMATCH: Literal[b'value']", + runtime="BYTES_STR_MISMATCH = 'value'", + error="BYTES_STR_MISMATCH", + ) + yield Case( + stub="STR_BYTES_MISMATCH: Literal['value']", + runtime="STR_BYTES_MISMATCH = b'value'", + error="STR_BYTES_MISMATCH", + ) + yield Case( + stub="WRONG_BYTES: Literal[b'abc']", + runtime="WRONG_BYTES = b'xyz'", + error="WRONG_BYTES", + ) + yield Case( + stub="WRONG_BOOL_1: Literal[True]", + runtime="WRONG_BOOL_1 = False", + error='WRONG_BOOL_1', + ) + yield Case( + stub="WRONG_BOOL_2: Literal[False]", + runtime="WRONG_BOOL_2 = True", + error='WRONG_BOOL_2', + ) + def remove_color_code(s: str) -> str: return re.sub("\\x1b.*?m", "", s) # this works! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/typeanal.py new/mypy-0.931/mypy/typeanal.py --- old/mypy-0.930/mypy/typeanal.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/typeanal.py 2022-01-07 15:58:59.000000000 +0100 @@ -70,7 +70,6 @@ plugin: Plugin, options: Options, is_typeshed_stub: bool, - allow_new_syntax: bool = False, allow_placeholder: bool = False, in_dynamic_func: bool = False, global_scope: bool = True) -> Optional[Tuple[Type, Set[str]]]: @@ -81,12 +80,12 @@ Return None otherwise. 'node' must have been semantically analyzed. """ try: - type = expr_to_unanalyzed_type(node, options, allow_new_syntax) + type = expr_to_unanalyzed_type(node, options, api.is_stub_file) except TypeTranslationError: api.fail('Invalid type alias: expression is not a valid type', node) return None analyzer = TypeAnalyser(api, tvar_scope, plugin, options, is_typeshed_stub, - allow_new_syntax=allow_new_syntax, defining_alias=True, + defining_alias=True, allow_placeholder=allow_placeholder) analyzer.in_dynamic_func = in_dynamic_func analyzer.global_scope = global_scope @@ -127,7 +126,6 @@ is_typeshed_stub: bool, *, defining_alias: bool = False, allow_tuple_literal: bool = False, - allow_new_syntax: bool = False, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, allow_required: bool = False, @@ -144,8 +142,11 @@ # Positive if we are analyzing arguments of another (outer) type self.nesting_level = 0 # Should we allow new type syntax when targeting older Python versions - # like 'list[int]' or 'X | Y' (allowed in stubs)? - self.allow_new_syntax = allow_new_syntax + # like 'list[int]' or 'X | Y' (allowed in stubs and with `__future__` import)? + self.always_allow_new_syntax = ( + self.api.is_stub_file + or self.api.is_future_flag_set('annotations') + ) # Should we accept unbound type variables (always OK in aliases)? self.allow_unbound_tvars = allow_unbound_tvars or defining_alias # If false, record incomplete ref if we generate PlaceholderType. @@ -202,9 +203,8 @@ if hook is not None: return hook(AnalyzeTypeContext(t, t, self)) if (fullname in get_nongen_builtins(self.options.python_version) - and t.args and - not self.allow_new_syntax and - not self.api.is_future_flag_set("annotations")): + and t.args + and not self.always_allow_new_syntax): self.fail(no_subscript_builtin_alias(fullname, propose_alt=not self.defining_alias), t) tvar_def = self.tvar_scope.get_binding(sym) @@ -291,9 +291,8 @@ " in a variable annotation", t) return AnyType(TypeOfAny.from_error) elif (fullname == 'typing.Tuple' or - (fullname == 'builtins.tuple' and (self.options.python_version >= (3, 9) or - self.api.is_future_flag_set('annotations') or - self.allow_new_syntax))): + (fullname == 'builtins.tuple' + and (self.always_allow_new_syntax or self.options.python_version >= (3, 9)))): # Tuple is special because it is involved in builtin import cycle # and may be not ready when used. sym = self.api.lookup_fully_qualified_or_none('builtins.tuple') @@ -326,8 +325,8 @@ elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif (fullname == 'typing.Type' or - (fullname == 'builtins.type' and (self.options.python_version >= (3, 9) or - self.api.is_future_flag_set('annotations')))): + (fullname == 'builtins.type' + and (self.always_allow_new_syntax or self.options.python_version >= (3, 9)))): if len(t.args) == 0: if fullname == 'typing.Type': any_type = self.get_omitted_any(t) @@ -704,9 +703,8 @@ def visit_union_type(self, t: UnionType) -> Type: if (t.uses_pep604_syntax is True and t.is_evaluated is True - and self.api.is_stub_file is False - and self.options.python_version < (3, 10) - and self.api.is_future_flag_set('annotations') is False): + and not self.always_allow_new_syntax + and not self.options.python_version >= (3, 10)): self.fail("X | Y syntax for unions requires Python 3.10", t) return UnionType(self.anal_array(t.items), t.line) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/typeops.py new/mypy-0.931/mypy/typeops.py --- old/mypy-0.930/mypy/typeops.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/typeops.py 2022-01-07 15:58:59.000000000 +0100 @@ -723,7 +723,10 @@ typ = get_proper_type(typ) if isinstance(typ, UnionType): - items = [try_expanding_sum_type_to_union(item, target_fullname) for item in typ.items] + items = [ + try_expanding_sum_type_to_union(item, target_fullname) + for item in typ.relevant_items() + ] return make_simplified_union(items, contract_literals=False) elif isinstance(typ, Instance) and typ.type.fullname == target_fullname: if typ.type.is_enum: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/typeshed/stdlib/builtins.pyi new/mypy-0.931/mypy/typeshed/stdlib/builtins.pyi --- old/mypy-0.930/mypy/typeshed/stdlib/builtins.pyi 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/typeshed/stdlib/builtins.pyi 2022-01-07 15:58:59.000000000 +0100 @@ -100,11 +100,13 @@ def __getattribute__(self, __name: str) -> Any: ... def __delattr__(self, __name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> str | Tuple[object, ...]: ... + # return type of pickle methods is rather hard to express in the current type system + # see #6661 and https://docs.python.org/3/library/pickle.html#object.__reduce__ + def __reduce__(self) -> str | Tuple[Any, ...]: ... if sys.version_info >= (3, 8): - def __reduce_ex__(self, __protocol: SupportsIndex) -> str | Tuple[object, ...]: ... + def __reduce_ex__(self, __protocol: SupportsIndex) -> str | Tuple[Any, ...]: ... else: - def __reduce_ex__(self, __protocol: int) -> str | Tuple[object, ...]: ... + def __reduce_ex__(self, __protocol: int) -> str | Tuple[Any, ...]: ... def __dir__(self) -> Iterable[str]: ... def __init_subclass__(cls) -> None: ... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/util.py new/mypy-0.931/mypy/util.py --- old/mypy-0.930/mypy/util.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/util.py 2022-01-07 15:58:59.000000000 +0100 @@ -105,6 +105,20 @@ return default_encoding, -1 +def bytes_to_human_readable_repr(b: bytes) -> str: + """Converts bytes into some human-readable representation. Unprintable + bytes such as the nul byte are escaped. For example: + + >>> b = bytes([102, 111, 111, 10, 0]) + >>> s = bytes_to_human_readable_repr(b) + >>> print(s) + foo\n\x00 + >>> print(repr(s)) + 'foo\\n\\x00' + """ + return repr(b)[2:-1] + + class DecodeError(Exception): """Exception raised when a file cannot be decoded due to an unknown encoding type. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy/version.py new/mypy-0.931/mypy/version.py --- old/mypy-0.930/mypy/version.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypy/version.py 2022-01-07 15:58:59.000000000 +0100 @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.930' +__version__ = '0.931' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypy.egg-info/PKG-INFO new/mypy-0.931/mypy.egg-info/PKG-INFO --- old/mypy-0.930/mypy.egg-info/PKG-INFO 2021-12-22 15:56:20.000000000 +0100 +++ new/mypy-0.931/mypy.egg-info/PKG-INFO 2022-01-07 15:59:23.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: mypy -Version: 0.930 +Version: 0.931 Summary: Optional static typing for Python Home-page: http://www.mypy-lang.org/ Author: Jukka Lehtosalo diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/mypyc/test/config.py new/mypy-0.931/mypyc/test/config.py --- old/mypy-0.930/mypyc/test/config.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/mypyc/test/config.py 2022-01-07 15:58:59.000000000 +0100 @@ -1,7 +1,11 @@ import os -this_file_dir = os.path.dirname(os.path.realpath(__file__)) -prefix = os.path.dirname(os.path.dirname(this_file_dir)) +provided_prefix = os.getenv('MYPY_TEST_PREFIX', None) +if provided_prefix: + PREFIX = provided_prefix +else: + this_file_dir = os.path.dirname(os.path.realpath(__file__)) + PREFIX = os.path.dirname(os.path.dirname(this_file_dir)) -# Locations of test data files such as test case descriptions (.test). -test_data_prefix = os.path.join(prefix, 'mypyc', 'test-data') +# Location of test data files such as test case descriptions. +test_data_prefix = os.path.join(PREFIX, 'mypyc', 'test-data') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/setup.py new/mypy-0.931/setup.py --- old/mypy-0.930/setup.py 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/setup.py 2022-01-07 15:58:59.000000000 +0100 @@ -107,6 +107,8 @@ )) + ( # Don't want to grab this accidentally os.path.join('mypyc', 'lib-rt', 'setup.py'), + # Uses __file__ at top level https://github.com/mypyc/mypyc/issues/700 + os.path.join('mypyc', '__main__.py'), ) everything = ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/check-dataclasses.test new/mypy-0.931/test-data/unit/check-dataclasses.test --- old/mypy-0.930/test-data/unit/check-dataclasses.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/check-dataclasses.test 2022-01-07 15:58:59.000000000 +0100 @@ -1456,3 +1456,69 @@ __slots__ = ('x',) x: int [builtins fixtures/dataclasses.pyi] + + +[case testSlotsDefinitionWithTwoPasses1] +# flags: --python-version 3.10 +# https://github.com/python/mypy/issues/11821 +from typing import TypeVar, Protocol, Generic +from dataclasses import dataclass + +C = TypeVar("C", bound="Comparable") + +class Comparable(Protocol): + pass + +V = TypeVar("V", bound=Comparable) + +@dataclass(slots=True) +class Node(Generic[V]): # Error was here + data: V +[builtins fixtures/dataclasses.pyi] + +[case testSlotsDefinitionWithTwoPasses2] +# flags: --python-version 3.10 +from typing import TypeVar, Protocol, Generic +from dataclasses import dataclass + +C = TypeVar("C", bound="Comparable") + +class Comparable(Protocol): + pass + +V = TypeVar("V", bound=Comparable) + +@dataclass(slots=True) # Explicit slots are still not ok: +class Node(Generic[V]): # E: "Node" both defines "__slots__" and is used with "slots=True" + __slots__ = ('data',) + data: V +[builtins fixtures/dataclasses.pyi] + +[case testSlotsDefinitionWithTwoPasses3] +# flags: --python-version 3.10 +from typing import TypeVar, Protocol, Generic +from dataclasses import dataclass + +C = TypeVar("C", bound="Comparable") + +class Comparable(Protocol): + pass + +V = TypeVar("V", bound=Comparable) + +@dataclass(slots=True) # Explicit slots are still not ok, even empty ones: +class Node(Generic[V]): # E: "Node" both defines "__slots__" and is used with "slots=True" + __slots__ = () + data: V +[builtins fixtures/dataclasses.pyi] + +[case testSlotsDefinitionWithTwoPasses4] +# flags: --python-version 3.10 +import dataclasses as dtc + +PublishedMessagesVar = dict[int, 'PublishedMessages'] + +@dtc.dataclass(frozen=True, slots=True) +class PublishedMessages: + left: int +[builtins fixtures/dataclasses.pyi] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/check-default-plugin.test new/mypy-0.931/test-data/unit/check-default-plugin.test --- old/mypy-0.930/test-data/unit/check-default-plugin.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/check-default-plugin.test 2022-01-07 15:58:59.000000000 +0100 @@ -24,56 +24,15 @@ [typing fixtures/typing-medium.pyi] [builtins fixtures/tuple.pyi] -[case testContextManagerWithGenericFunctionAndSendType] -from contextlib import contextmanager -from typing import TypeVar, Generator - -T = TypeVar('T') -S = TypeVar('S') - -@contextmanager -def yield_id(item: T) -> Generator[T, S, None]: - yield item - -reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> contextlib.GeneratorContextManager[T`-1]" - -with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" - -f = yield_id -def g(x, y): pass -f = g # E: Incompatible types in assignment (expression has type "Callable[[Any, Any], Any]", variable has type "Callable[[T], GeneratorContextManager[T]]") -[typing fixtures/typing-medium.pyi] -[builtins fixtures/tuple.pyi] - [case testAsyncContextManagerWithGenericFunction] # flags: --python-version 3.7 from contextlib import asynccontextmanager -from typing import TypeVar, AsyncIterator - -T = TypeVar('T') - -@asynccontextmanager -async def yield_id(item: T) -> AsyncIterator[T]: - yield item - -reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" - -async with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" -[typing fixtures/typing-async.pyi] -[builtins fixtures/tuple.pyi] - -[case testAsyncContextManagerWithGenericFunctionAndSendType] -# flags: --python-version 3.7 -from contextlib import asynccontextmanager from typing import TypeVar, AsyncGenerator T = TypeVar('T') -S = TypeVar('S') @asynccontextmanager -async def yield_id(item: T) -> AsyncGenerator[T, S]: +async def yield_id(item: T) -> AsyncGenerator[T, None]: yield item reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" @@ -83,6 +42,36 @@ [typing fixtures/typing-async.pyi] [builtins fixtures/tuple.pyi] +[case testContextManagerReturnsGenericFunction] +import contextlib +from typing import Callable +from typing import Generator +from typing import Iterable +from typing import TypeVar + +TArg = TypeVar('TArg') +TRet = TypeVar('TRet') + +@contextlib.contextmanager +def _thread_mapper(maxsize: int) -> Generator[ + Callable[[Callable[[TArg], TRet], Iterable[TArg]], Iterable[TRet]], + None, None, +]: + # defined inline as there isn't a builtins.map fixture + def my_map(f: Callable[[TArg], TRet], it: Iterable[TArg]) -> Iterable[TRet]: + for x in it: + yield f(x) + + yield my_map + +def identity(x: int) -> int: return x + +with _thread_mapper(1) as m: + lst = list(m(identity, [2, 3])) + reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int*]" +[typing fixtures/typing-medium.pyi] +[builtins fixtures/list.pyi] + [case testContextManagerWithUnspecifiedArguments] from contextlib import contextmanager from typing import Callable, Iterator diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/check-enum.test new/mypy-0.931/test-data/unit/check-enum.test --- old/mypy-0.930/test-data/unit/check-enum.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/check-enum.test 2022-01-07 15:58:59.000000000 +0100 @@ -1689,6 +1689,11 @@ _value_ = 'b2' _order_ = 'X Y' __order__ = 'X Y' + __slots__ = () + __doc__ = 'doc' + __module__ = 'module' + __annotations__ = {'a': int} + __dict__ = {'a': 1} class EI(IntEnum): name = 'a' @@ -1697,10 +1702,15 @@ _value_ = 2 _order_ = 'X Y' __order__ = 'X Y' + __slots__ = () + __doc__ = 'doc' + __module__ = 'module' + __annotations__ = {'a': int} + __dict__ = {'a': 1} E._order_ = 'a' # E: Cannot assign to final attribute "_order_" EI.value = 2 # E: Cannot assign to final attribute "value" -[builtins fixtures/bool.pyi] +[builtins fixtures/dict.pyi] [case testEnumNotFinalWithMethodsAndUninitializedValues] # https://github.com/python/mypy/issues/11578 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/check-generic-alias.test new/mypy-0.931/test-data/unit/check-generic-alias.test --- old/mypy-0.930/test-data/unit/check-generic-alias.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/check-generic-alias.test 2022-01-07 15:58:59.000000000 +0100 @@ -273,6 +273,8 @@ import m reveal_type(m.a) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(m.b) # N: Revealed type is "builtins.list[builtins.list[builtins.int]]" +m.C # has complex representation, ignored +reveal_type(m.d) # N: Revealed type is "Type[builtins.str]" [file m.pyi] A = list[int] @@ -281,4 +283,16 @@ b: B class C(list[int]): pass +d: type[str] +[builtins fixtures/list.pyi] + + +[case testTypeAliasWithBuiltinListAliasInStub] +# flags: --python-version 3.6 +import m +reveal_type(m.a()[0]) # N: Revealed type is "builtins.int*" + +[file m.pyi] +List = list +a = List[int] [builtins fixtures/list.pyi] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/check-inference.test new/mypy-0.931/test-data/unit/check-inference.test --- old/mypy-0.930/test-data/unit/check-inference.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/check-inference.test 2022-01-07 15:58:59.000000000 +0100 @@ -3210,3 +3210,48 @@ k = [k] reveal_type(k) # N: Revealed type is "builtins.list[Any]" [builtins fixtures/list.pyi] + +[case testErasedTypeRuntimeCoverage] +# https://github.com/python/mypy/issues/11913 +from typing import TypeVar, Type, Generic, Callable, Iterable + +class DataType: ... + +T1 = TypeVar('T1') +T2 = TypeVar("T2", bound=DataType) + +def map(__func: T1) -> None: ... + +def collection_from_dict_value(model: Type[T2]) -> None: + map(lambda i: i if isinstance(i, model) else i) +[builtins fixtures/isinstancelist.pyi] + +[case testRegression11705_Strict] +# flags: --strict-optional +# See: https://github.com/python/mypy/issues/11705 +from typing import Dict, Optional, NamedTuple +class C(NamedTuple): + x: int + +t: Optional[C] +d: Dict[C, bytes] +x = t and d[t] +reveal_type(x) # N: Revealed type is "Union[None, builtins.bytes*]" +if x: + reveal_type(x) # N: Revealed type is "builtins.bytes*" +[builtins fixtures/dict.pyi] + +[case testRegression11705_NoStrict] +# flags: --no-strict-optional +# See: https://github.com/python/mypy/issues/11705 +from typing import Dict, Optional, NamedTuple +class C(NamedTuple): + x: int + +t: Optional[C] +d: Dict[C, bytes] +x = t and d[t] +reveal_type(x) # N: Revealed type is "builtins.bytes*" +if x: + reveal_type(x) # N: Revealed type is "builtins.bytes*" +[builtins fixtures/dict.pyi] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/check-type-aliases.test new/mypy-0.931/test-data/unit/check-type-aliases.test --- old/mypy-0.930/test-data/unit/check-type-aliases.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/check-type-aliases.test 2022-01-07 15:58:59.000000000 +0100 @@ -50,6 +50,14 @@ f(1) f('x') +[case testNoReturnTypeAlias] +# https://github.com/python/mypy/issues/11903 +from typing import NoReturn +Never = NoReturn +a: Never # Used to be an error here + +def f(a: Never): ... +f(5) # E: Argument 1 to "f" has incompatible type "int"; expected "NoReturn" [case testImportUnionAlias] import typing from _m import U diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/cmdline.pyproject.test new/mypy-0.931/test-data/unit/cmdline.pyproject.test --- old/mypy-0.930/test-data/unit/cmdline.pyproject.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/cmdline.pyproject.test 2022-01-07 15:58:59.000000000 +0100 @@ -80,3 +80,48 @@ [out] pyproject.toml: toml config file contains [[tool.mypy.overrides]] sections with conflicting values. Module 'x' has two different values for 'disallow_untyped_defs' == Return code: 0 + +[case testMultilineLiteralExcludePyprojectTOML] +# cmd: mypy x +[file pyproject.toml] +\[tool.mypy] +exclude = '''(?x)( + (^|/)[^/]*skipme_\.py$ + |(^|/)_skipme[^/]*\.py$ +)''' +[file x/__init__.py] +i: int = 0 +[file x/_skipme_please.py] +This isn't even syntatically valid! +[file x/please_skipme_.py] +Neither is this! + +[case testMultilineBasicExcludePyprojectTOML] +# cmd: mypy x +[file pyproject.toml] +\[tool.mypy] +exclude = """(?x)( + (^|/)[^/]*skipme_\\.py$ + |(^|/)_skipme[^/]*\\.py$ +)""" +[file x/__init__.py] +i: int = 0 +[file x/_skipme_please.py] +This isn't even syntatically valid! +[file x/please_skipme_.py] +Neither is this! + +[case testSequenceExcludePyprojectTOML] +# cmd: mypy x +[file pyproject.toml] +\[tool.mypy] +exclude = [ + '(^|/)[^/]*skipme_\.py$', # literal (no escaping) + "(^|/)_skipme[^/]*\\.py$", # basic (backslash needs escaping) +] +[file x/__init__.py] +i: int = 0 +[file x/_skipme_please.py] +This isn't even syntatically valid! +[file x/please_skipme_.py] +Neither is this! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mypy-0.930/test-data/unit/cmdline.test new/mypy-0.931/test-data/unit/cmdline.test --- old/mypy-0.930/test-data/unit/cmdline.test 2021-12-22 15:55:56.000000000 +0100 +++ new/mypy-0.931/test-data/unit/cmdline.test 2022-01-07 15:58:59.000000000 +0100 @@ -1354,9 +1354,10 @@ # cmd: mypy . [file mypy.ini] \[mypy] -exclude = - abc - b +exclude = (?x)( + ^abc/ + |^b/ + ) [file abc/apkg.py] 1() [file b/bpkg.py]