diff --git a/requirements-tests.txt b/requirements-tests.txt index 811c4f7747e1..33ec06e6fd8c 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -1,6 +1,6 @@ # Type checkers that we test our stubs against. These should always # be pinned to a specific version to make failure reproducible. -mypy==1.15.0 +mypy==1.16.0 pyright==1.1.400 # pytype can be installed on Windows, but requires building wheels, let's not do that on the CI pytype==2024.10.11; platform_system != "Windows" and python_version >= "3.10" and python_version < "3.13" diff --git a/stdlib/@tests/stubtest_allowlists/common.txt b/stdlib/@tests/stubtest_allowlists/common.txt index a036c227f118..130c6d2b8285 100644 --- a/stdlib/@tests/stubtest_allowlists/common.txt +++ b/stdlib/@tests/stubtest_allowlists/common.txt @@ -210,6 +210,8 @@ _?ast.stmt.__init__ _ast.ImportFrom.level # None on the class, but never None on instances +argparse.Namespace.__setattr__ # should allow setting any attribute + ast.ImportFrom.level # None on the class, but never None on instances ast.NodeVisitor.visit_\w+ # Methods are discovered dynamically, see #3796 _?asyncio.Future.__init__ # Usually initialized from c object @@ -272,7 +274,9 @@ _?ctypes.Array._length_ # _length_ is abstract, https://github.com/python/types _?ctypes.Array.raw # exists but stubtest can't see it; only available if _CT == c_char ctypes.CDLL._FuncPtr # None at class level but initialized in __init__ to this value _?ctypes.Structure.__getattr__ # doesn't exist, but makes things easy if we pretend it does +_?ctypes.Structure.__setattr__ # doesn't exist, but makes things easy if we pretend it does _?ctypes.Union.__getattr__ # doesn't exist, but makes things easy if we pretend it does +_?ctypes.Union.__setattr__ # doesn't exist, but makes things easy if we pretend it does # Iterable classes that don't define __iter__ at runtime (usually iterable via __getitem__) # These would ideally be special-cased by type checkers; see https://github.com/python/mypy/issues/2220 @@ -323,6 +327,8 @@ inspect.Signature.__init__ inspect.Parameter.empty # set as private marker _empty inspect.Signature.empty # set as private marker _empty +logging.LogRecord.__setattr__ # doesn't exist, but makes things easy if we pretend it does + # Iterable classes that don't define __iter__ at runtime (usually iterable via __getitem__) # These would ideally be special-cased by type checkers; see https://github.com/python/mypy/issues/2220 mmap.mmap.__iter__ @@ -380,7 +386,9 @@ multiprocessing.synchronize.SemLock.acquire multiprocessing.synchronize.SemLock.release numbers.Number.__hash__ # typeshed marks this as abstract but code just sets this as None + optparse.Values.__getattr__ # Some attributes are set in __init__ using setattr +optparse.Values.__setattr__ # doesn't exist, but makes things easy if we pretend it does os._wrap_close.read # Methods that come from __getattr__() at runtime os._wrap_close.readable # Methods that come from __getattr__() at runtime diff --git a/stdlib/@tests/stubtest_allowlists/py312.txt b/stdlib/@tests/stubtest_allowlists/py312.txt index 6b225d0594bd..a424779a4f9b 100644 --- a/stdlib/@tests/stubtest_allowlists/py312.txt +++ b/stdlib/@tests/stubtest_allowlists/py312.txt @@ -13,6 +13,10 @@ zoneinfo.ZoneInfo.from_file # Pos-only parameters had different "names" in diff typing_extensions.TypeAliasType.__parameters__ typing_extensions.TypeAliasType.__value__ +# Types that require `__setattr__` and `__delattr__` for typing purposes: +types.SimpleNamespace.__setattr__ +types.SimpleNamespace.__delattr__ + # ==================================== # Pre-existing errors from Python 3.11 diff --git a/stdlib/@tests/stubtest_allowlists/py313.txt b/stdlib/@tests/stubtest_allowlists/py313.txt index 9ef94b218899..7cd834acf7b2 100644 --- a/stdlib/@tests/stubtest_allowlists/py313.txt +++ b/stdlib/@tests/stubtest_allowlists/py313.txt @@ -18,6 +18,10 @@ zoneinfo.ZoneInfo.from_file # Pos-only parameters had different "names" in diff typing_extensions.TypeAliasType.__parameters__ typing_extensions.TypeAliasType.__value__ +# Types that require `__setattr__` and `__delattr__` for typing purposes: +types.SimpleNamespace.__setattr__ +types.SimpleNamespace.__delattr__ + # ======= # >= 3.11 diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index 38949fb66b8e..be30c523eff1 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -55,6 +55,10 @@ functools.partialmethod.__new__ zoneinfo.ZoneInfo.from_file # Pos-only parameters had different "names" in different Python versions +# Types that require `__setattr__` and `__delattr__` for typing purposes: +types.SimpleNamespace.__setattr__ +types.SimpleNamespace.__delattr__ + # ======= # >= 3.11 @@ -101,10 +105,6 @@ typing(_extensions)?\.IO\.writelines # Allowlist entries that cannot or should not be fixed; >= 3.14 # ============================================================= -# Internal annotations machinery -.*\.__annotate_func__ -.*\.__annotations_cache__ - # Undocumented private attributes .*\.ForwardRef\.__arg__ .*\.ForwardRef\.__ast_node__ diff --git a/stubs/WTForms/@tests/stubtest_allowlist.txt b/stubs/WTForms/@tests/stubtest_allowlist.txt index 18057b0c2330..0bf5472acba9 100644 --- a/stubs/WTForms/@tests/stubtest_allowlist.txt +++ b/stubs/WTForms/@tests/stubtest_allowlist.txt @@ -9,6 +9,14 @@ wtforms.fields.core.Field.__get__ # to let mypy know that arbitrary attribute access is possible wtforms.meta.DefaultMeta.__getattr__ +# Should allow setting and deleting any attribute +wtforms.Flags.__delattr__ +wtforms.Flags.__setattr__ +wtforms.fields.Flags.__delattr__ +wtforms.fields.Flags.__setattr__ +wtforms.fields.core.Flags.__delattr__ +wtforms.fields.core.Flags.__setattr__ + # Error: variable differs from runtime # ====================== # _unbound_fields has some weird semantics: due to the metaclass it diff --git a/stubs/openpyxl/@tests/test_cases/check_base_descriptors.py b/stubs/openpyxl/@tests/test_cases/check_base_descriptors.py index 3dcbdc337228..a0d5e6d03330 100644 --- a/stubs/openpyxl/@tests/test_cases/check_base_descriptors.py +++ b/stubs/openpyxl/@tests/test_cases/check_base_descriptors.py @@ -177,27 +177,27 @@ class WithDescriptorsStrict(Strict): assert_type(with_descriptors.match_pattern_bytes, ReadableBuffer) assert_type(with_descriptors.match_pattern_bytes_none, Union[ReadableBuffer, None]) -assert_type(with_descriptors.convertible_not_none, int) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.convertible_not_none, int) assert_type(with_descriptors.convertible_none, Union[int, None]) -assert_type(with_descriptors.minmax_float, float) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.minmax_float, float) assert_type(with_descriptors.minmax_float_none, Union[float, None]) -assert_type(with_descriptors.minmax_int, int) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.minmax_int, int) assert_type(with_descriptors.minmax_int_none, Union[int, None]) -assert_type(with_descriptors.bool_not_none, bool) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.bool_not_none, bool) assert_type(with_descriptors.bool_none, Union[bool, None]) -assert_type(with_descriptors.datetime_not_none, datetime) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.datetime_not_none, datetime) assert_type(with_descriptors.datetime_none, Union[datetime, None]) -assert_type(with_descriptors.string_not_none, str) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.string_not_none, str) assert_type(with_descriptors.string_none, Union[str, None]) -assert_type(with_descriptors.float_not_none, float) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.float_not_none, float) assert_type(with_descriptors.float_none, Union[float, None]) -assert_type(with_descriptors.integer_not_none, int) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.integer_not_none, int) assert_type(with_descriptors.integer_none, Union[int, None]) @@ -289,8 +289,8 @@ class WithDescriptorsStrict(Strict): with_descriptors.convertible_not_none = 0 with_descriptors.convertible_not_none = "0" -with_descriptors.convertible_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy -with_descriptors.convertible_not_none = object() # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.convertible_not_none = None # type: ignore +with_descriptors.convertible_not_none = object() # type: ignore with_descriptors.convertible_none = 0 with_descriptors.convertible_none = "0" @@ -301,7 +301,7 @@ class WithDescriptorsStrict(Strict): with_descriptors.minmax_float = 0 with_descriptors.minmax_float = "0" with_descriptors.minmax_float = 0.0 -with_descriptors.minmax_float = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.minmax_float = None # type: ignore with_descriptors.minmax_float = object() # type: ignore with_descriptors.minmax_float_none = 0 @@ -313,7 +313,7 @@ class WithDescriptorsStrict(Strict): with_descriptors.minmax_int = 0 with_descriptors.minmax_int = "0" with_descriptors.minmax_int = 0.0 -with_descriptors.minmax_int = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.minmax_int = None # type: ignore with_descriptors.minmax_int = object() # type: ignore with_descriptors.minmax_int_none = 0 @@ -354,7 +354,7 @@ class WithDescriptorsStrict(Strict): with_descriptors.string_not_none = "" -with_descriptors.string_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.string_not_none = None # type: ignore with_descriptors.string_not_none = 0 # type: ignore with_descriptors.string_none = "" @@ -366,8 +366,8 @@ class WithDescriptorsStrict(Strict): with_descriptors.float_not_none = 0.0 with_descriptors.float_not_none = "0" with_descriptors.float_not_none = b"0" -with_descriptors.float_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy -with_descriptors.float_not_none = object() # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.float_not_none = None # type: ignore +with_descriptors.float_not_none = object() # type: ignore with_descriptors.float_none = 0 with_descriptors.float_none = 0.0 @@ -381,8 +381,8 @@ class WithDescriptorsStrict(Strict): with_descriptors.integer_not_none = 0.0 with_descriptors.integer_not_none = "0" with_descriptors.integer_not_none = b"0" -with_descriptors.integer_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy -with_descriptors.integer_not_none = object() # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.integer_not_none = None # type: ignore +with_descriptors.integer_not_none = object() # type: ignore with_descriptors.integer_none = 0 with_descriptors.integer_none = 0.0 diff --git a/stubs/openpyxl/@tests/test_cases/check_nested_descriptors.py b/stubs/openpyxl/@tests/test_cases/check_nested_descriptors.py index e28920ed8c83..1526334acbe2 100644 --- a/stubs/openpyxl/@tests/test_cases/check_nested_descriptors.py +++ b/stubs/openpyxl/@tests/test_cases/check_nested_descriptors.py @@ -167,19 +167,19 @@ class WithDescriptorsStrict(Strict): assert_type(with_descriptors.minmax_int, int) assert_type(with_descriptors.minmax_int_none, Union[int, None]) -assert_type(with_descriptors.bool_not_none, bool) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.bool_not_none, bool) assert_type(with_descriptors.bool_none, Union[bool, None]) assert_type(with_descriptors.emptytag_not_none, bool) assert_type(with_descriptors.emptytag_none, Union[bool, None]) -assert_type(with_descriptors.string_not_none, str) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.string_not_none, str) assert_type(with_descriptors.string_none, Union[str, None]) -assert_type(with_descriptors.float_not_none, float) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.float_not_none, float) assert_type(with_descriptors.float_none, Union[float, None]) -assert_type(with_descriptors.integer_not_none, int) # type: ignore[assert-type] # False-positive in mypy +assert_type(with_descriptors.integer_not_none, int) assert_type(with_descriptors.integer_none, Union[int, None]) @@ -264,15 +264,11 @@ class WithDescriptorsStrict(Strict): with_descriptors.convertible_not_none = 0 with_descriptors.convertible_not_none = "0" -with_descriptors.convertible_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy -with_descriptors.convertible_not_none = object() # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.convertible_not_none = None # type: ignore +with_descriptors.convertible_not_none = object() # type: ignore with_descriptors.convertible_not_none = cast(_HasTagAndGet[str], _) -with_descriptors.convertible_not_none = cast( # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy - _HasTagAndGet[None], _ -) -with_descriptors.convertible_not_none = cast( # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy - _HasTagAndGet[object], _ -) +with_descriptors.convertible_not_none = cast(_HasTagAndGet[None], _) # type: ignore +with_descriptors.convertible_not_none = cast(_HasTagAndGet[object], _) # type: ignore with_descriptors.convertible_none = 0 with_descriptors.convertible_none = "0" @@ -426,15 +422,11 @@ class WithDescriptorsStrict(Strict): with_descriptors.float_not_none = 0.0 with_descriptors.float_not_none = "0" with_descriptors.float_not_none = b"0" -with_descriptors.float_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy -with_descriptors.float_not_none = object() # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.float_not_none = None # type: ignore +with_descriptors.float_not_none = object() # type: ignore with_descriptors.float_not_none = cast(_HasTagAndGet[float], _) -with_descriptors.float_not_none = cast( # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy - _HasTagAndGet[None], _ -) -with_descriptors.float_not_none = cast( # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy - _HasTagAndGet[object], _ -) +with_descriptors.float_not_none = cast(_HasTagAndGet[None], _) # type: ignore +with_descriptors.float_not_none = cast(_HasTagAndGet[object], _) # type: ignore with_descriptors.float_none = 0 with_descriptors.float_none = 0.0 @@ -451,15 +443,11 @@ class WithDescriptorsStrict(Strict): with_descriptors.integer_not_none = 0.0 with_descriptors.integer_not_none = "0" with_descriptors.integer_not_none = b"0" -with_descriptors.integer_not_none = None # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy -with_descriptors.integer_not_none = object() # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy +with_descriptors.integer_not_none = None # type: ignore +with_descriptors.integer_not_none = object() # type: ignore with_descriptors.integer_not_none = cast(_HasTagAndGet[int], _) -with_descriptors.integer_not_none = cast( # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy - _HasTagAndGet[None], _ -) -with_descriptors.integer_not_none = cast( # pyright: ignore[reportAttributeAccessIssue] # false negative in mypy - _HasTagAndGet[object], _ -) +with_descriptors.integer_not_none = cast(_HasTagAndGet[None], _) # type: ignore +with_descriptors.integer_not_none = cast(_HasTagAndGet[object], _) # type: ignore with_descriptors.integer_none = 0 with_descriptors.integer_none = 0.0 diff --git a/stubs/passlib/@tests/stubtest_allowlist.txt b/stubs/passlib/@tests/stubtest_allowlist.txt index 5877bbebe95b..0faf0d50d983 100644 --- a/stubs/passlib/@tests/stubtest_allowlist.txt +++ b/stubs/passlib/@tests/stubtest_allowlist.txt @@ -38,10 +38,7 @@ passlib.utils.handlers.HasRounds.rounds # Errors in `__all__` at runtime: # TODO: change after https://github.com/python/mypy/pull/14217 is released passlib.handlers.oracle.__all__ -passlib.handlers.oracle.oracle11g -passlib.handlers.oracle.oracle10g passlib.handlers.mysql.__all__ -passlib.handlers.mysql.mysq41 # Compat tools are ignored: passlib.utils.compat.* diff --git a/stubs/python-xlib/@tests/stubtest_allowlist.txt b/stubs/python-xlib/@tests/stubtest_allowlist.txt index 2fec5b0c782c..731b14c8c3df 100644 --- a/stubs/python-xlib/@tests/stubtest_allowlist.txt +++ b/stubs/python-xlib/@tests/stubtest_allowlist.txt @@ -12,6 +12,9 @@ Xlib.protocol.rq.DictWrapper.__lt__ Xlib.protocol.rq.Event.__gt__ Xlib.protocol.rq.Event.__lt__ +# should allow setting any attribute +Xlib.protocol.rq.GetAttrData.__setattr__ + # Can be None or str once instantiated Xlib.protocol.rq.*.structcode # Should only ever be str once instantiated diff --git a/stubs/reportlab/@tests/stubtest_allowlist.txt b/stubs/reportlab/@tests/stubtest_allowlist.txt index 745bf361913c..859113c22aae 100644 --- a/stubs/reportlab/@tests/stubtest_allowlist.txt +++ b/stubs/reportlab/@tests/stubtest_allowlist.txt @@ -53,14 +53,6 @@ reportlab.lib.utils.CIDict.get reportlab.lib.utils.CIDict.pop reportlab.lib.utils.CIDict.setdefault -# these have a __module__ argument which confuses stubtest -reportlab.lib.testutils.rlSkip -reportlab.lib.testutils.rlSkipIf -reportlab.lib.testutils.rlSkipUnless - -# __map__ argument confuses stubtest -reportlab.lib.styles.str2alignment - # __new__ just forwards the arguments to the super class # it doesn't actually accept arbitrary arguments reportlab.platypus.doctemplate.PTCycle.__new__ @@ -83,6 +75,10 @@ reportlab.graphics.barcode.qrencoder.i reportlab.lib.fonts.k reportlab.lib.pdfencrypt.i +# should allow setting any attribute +reportlab.lib.abag.ABag.__setattr__ +reportlab.lib.styles.PropertySet.__setattr__ + # *-imports that cause a mess we don't want to propagate reportlab.graphics.charts.lineplots.pi reportlab\.graphics\.render(base|PDF|PM|PS|SVG)\.EVEN_ODD @@ -96,23 +92,7 @@ reportlab\.graphics\.render(base|PDF|PM|PS|SVG)\.shapeChecking reportlab\.graphics\.render(base|PDF|PM|PS|SVG)\.verbose # messed up __all__ which contains just a string -reportlab.graphics.barcode.qr.C -reportlab.graphics.barcode.qr.Q -reportlab.graphics.barcode.qr.W reportlab.graphics.barcode.qr.__all__ -reportlab.graphics.barcode.qr.d -reportlab.graphics.barcode.qr.e -reportlab.graphics.barcode.qr.g -reportlab.graphics.barcode.qr.i -reportlab.graphics.barcode.qr.o -reportlab.graphics.barcode.qr.r -reportlab.graphics.barcode.qr.t - -# spelling mistake in __all__ -reportlab.graphics.barcode.ecc200datamatrix.ECC200datamatrix - -# wasn't removed from __all__ by accident -reportlab.graphics.barcode.eanbc.isEanString # Error: is not present at runtime diff --git a/stubs/requests/@tests/stubtest_allowlist.txt b/stubs/requests/@tests/stubtest_allowlist.txt index 3bfd86463261..9f24211ef4d4 100644 --- a/stubs/requests/@tests/stubtest_allowlist.txt +++ b/stubs/requests/@tests/stubtest_allowlist.txt @@ -2,3 +2,6 @@ requests.packages.mod requests.packages.package requests.packages.target + +# Should allow setting any attribute: +requests.structures.LookupDict.__setattr__ diff --git a/stubs/workalendar/@tests/stubtest_allowlist.txt b/stubs/workalendar/@tests/stubtest_allowlist.txt index bd0a43b5b82a..5ba5b391d3d7 100644 --- a/stubs/workalendar/@tests/stubtest_allowlist.txt +++ b/stubs/workalendar/@tests/stubtest_allowlist.txt @@ -1,6 +1,5 @@ # VictoriaDayTuesdayAfterFirstMondayMay is not defined but used in __all__ runtime: workalendar.europe.scotland.mixins.__all__ -workalendar.europe.scotland.mixins.VictoriaDayTuesdayAfterFirstMondayMay workalendar.core.CoreCalendar.name workalendar.skyfield_astronomy