diff --git a/setup.cfg b/setup.cfg index 009dd13..4c54795 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ packages = zope-stubs package_dir = =src install_requires = - mypy==0.981 + mypy==1.0.0 zope.interface zope.schema include_package_data = True diff --git a/src/mypy_zope/plugin.py b/src/mypy_zope/plugin.py index 46bdc1b..02ab413 100644 --- a/src/mypy_zope/plugin.py +++ b/src/mypy_zope/plugin.py @@ -96,6 +96,9 @@ def make_simple_type( } +HACK_IS_ABSTRACT_NON_PROPAGATING = -12345678 + + class ZopeInterfacePlugin(Plugin): def __init__(self, options: Options): super().__init__(options) @@ -520,6 +523,27 @@ def _adjust_interface_function( func_def.arg_kinds.insert(0, ARG_POS) func_def.arguments.insert(0, selfarg) + # 1: We want mypy to consider this method abstract, so that it allows the + # method to have an empty body without causing a warning. + # 2: We want mypy to consider the interface class NOT abstract, so we can use the + # "adaption" pattern. + # Unfortunately whenever mypy sees (1) it will mark the class as abstract, + # forcing (2) to be false. This seems to be a change in mypy 0.990, namely + # https://github.com/python/mypy/pull/13729 + # + # Mypy 1.0.0: + # - allows empty bodies for abstract methods in mypy/checker.py:1240 + # by testing if + # abstract_status != NOT_ABSTRACT. + # - marks classes as abstract based on their methods in + # mypy/semanal_classprop.py:79 by testing if + # abstract_status in (IS_ABSTRACT, IMPLICITLY_ABSTRACT) + # + # Thus we can make (1) and (2) true by setting abstract_status to some value + # distinct from these three NOT_ABSTRACT, IS_ABSTRACT and IMPLICITLY_ABSTRACT. + # These are presently the integers 0, 1, and 2 defined in mypy/nodes.py:738-743. + func_def.abstract_status = HACK_IS_ABSTRACT_NON_PROPAGATING + return func_def def _adjust_interface_overload( diff --git a/tests/samples/contextmanager.py b/tests/samples/contextmanager.py index ec6af36..cc6183b 100644 --- a/tests/samples/contextmanager.py +++ b/tests/samples/contextmanager.py @@ -9,7 +9,7 @@ class A(Generic[_T]): @contextmanager def m(x: _T) -> Iterator[A[_T]]: - ... + return iter([A()]) with m(7) as x: diff --git a/tests/samples/interface_meta.py b/tests/samples/interface_meta.py index 2e04617..2f02c1f 100644 --- a/tests/samples/interface_meta.py +++ b/tests/samples/interface_meta.py @@ -5,9 +5,7 @@ class IBookmark(zope.interface.Interface): - @staticmethod - def create(url: str) -> 'IBookmark': - pass + pass def createOb(iface: Type[T]) -> T: if zope.interface.interfaces.IInterface.providedBy(iface): @@ -20,6 +18,6 @@ def main(self) -> None: """ -interface_meta.py:19: note: Revealed type is "__main__.IBookmark" +interface_meta.py:17: note: Revealed type is "__main__.IBookmark" -""" \ No newline at end of file +""" diff --git a/tests/samples/interface_unknown_inherit.py b/tests/samples/interface_unknown_inherit.py index 8cc0768..2e13e6c 100644 --- a/tests/samples/interface_unknown_inherit.py +++ b/tests/samples/interface_unknown_inherit.py @@ -20,7 +20,7 @@ class Bookmark(object): interface_unknown_inherit.py:8: error: Cannot find implementation or library stub for module named "unknown.interfaces" interface_unknown_inherit.py:8: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports -interface_unknown_inherit.py:11: error: Method must have at least one argument +interface_unknown_inherit.py:11: error: Method must have at least one argument. Did you forget the "self" argument? interface_unknown_inherit.py:14: error: zope.interface.implementer accepts interface, not __main__.IKnownInterface. interface_unknown_inherit.py:14: error: Make sure you have stubs for all packages that provide interfaces for __main__.IKnownInterface class hierarchy. diff --git a/tests/samples/overload_readme.py b/tests/samples/overload_readme.py index acc0834..bcf8939 100644 --- a/tests/samples/overload_readme.py +++ b/tests/samples/overload_readme.py @@ -14,7 +14,7 @@ def say() -> str: def say(count: int) -> List[str]: ... - def say(count: int = None) -> Union[str, List[str]]: + def say(count: Optional[int] = None) -> Union[str, List[str]]: pass @@ -28,7 +28,7 @@ def say(self) -> str: def say(self, count: int) -> List[str]: ... - def say(self, count: int = None) -> Union[str, List[str]]: + def say(self, count: Optional[int] = None) -> Union[str, List[str]]: if count is None: return "Mooo" return ["Mooo"] * count diff --git a/tests/test_samples.py b/tests/test_samples.py index b929ce0..f853009 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -25,6 +25,7 @@ def test_samples(samplefile, mypy_cache_dir): opts.cache_dir = mypy_cache_dir opts.show_traceback = True opts.namespace_packages = True + opts.hide_error_codes = True opts.plugins = ['mypy_zope:plugin'] # Config file is needed to load plugins, it doesn't not exist and is not # supposed to.