From 0e49b067c3dc3d71f13a98a26eb388718f4d2402 Mon Sep 17 00:00:00 2001 From: anthony sottile Date: Mon, 22 Jul 2024 14:46:25 -0400 Subject: [PATCH] ref: upgrade mypy to 1.11.0 --- requirements-dev-frozen.txt | 2 +- requirements-dev.txt | 2 +- src/sentry/models/authenticator.py | 2 +- .../rules/conditions/event_frequency.py | 2 +- tests/tools/mypy_helpers/test_plugin.py | 75 ------------------- tools/mypy_helpers/plugin.py | 25 ------- 6 files changed, 4 insertions(+), 104 deletions(-) diff --git a/requirements-dev-frozen.txt b/requirements-dev-frozen.txt index 718cba50616e2c..6e0b1640b3d457 100644 --- a/requirements-dev-frozen.txt +++ b/requirements-dev-frozen.txt @@ -101,7 +101,7 @@ mmh3==4.0.0 more-itertools==8.13.0 msgpack==1.0.7 msgpack-types==0.2.0 -mypy==1.10.0 +mypy==1.11.0 mypy-extensions==1.0.0 nodeenv==1.8.0 oauthlib==3.1.0 diff --git a/requirements-dev.txt b/requirements-dev.txt index 63abb28fa5b73e..2d434ae8ae7694 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -39,7 +39,7 @@ sentry-forked-django-stubs>=5.0.2.post6 sentry-forked-djangorestframework-stubs>=3.15.0.post1 lxml-stubs msgpack-types>=0.2.0 -mypy>=1.10 +mypy>=1.11 types-beautifulsoup4 types-cachetools types-croniter diff --git a/src/sentry/models/authenticator.py b/src/sentry/models/authenticator.py index df0f03ff4cbcc8..15c95e6dbbe81c 100644 --- a/src/sentry/models/authenticator.py +++ b/src/sentry/models/authenticator.py @@ -191,7 +191,7 @@ def reset_fields(self, save=True): if save: self.save() - def __repr__(self): + def __repr__(self) -> str: # type: ignore[override] # python/mypy#17562 return f"" @classmethod diff --git a/src/sentry/rules/conditions/event_frequency.py b/src/sentry/rules/conditions/event_frequency.py index 0ec068db0fa249..3aaa5215170707 100644 --- a/src/sentry/rules/conditions/event_frequency.py +++ b/src/sentry/rules/conditions/event_frequency.py @@ -177,7 +177,7 @@ def passes(self, event: GroupEvent, state: EventState) -> bool: comparison_interval = COMPARISON_INTERVALS[comparison_interval_option][1] _, duration = self.intervals[interval] try: - current_value = self.get_rate(duration=duration, comparison_interval=comparison_interval, event=event, environment_id=self.rule.environment_id, comparison_type=comparison_type) # type: ignore[arg-type, union-attr] + current_value = self.get_rate(duration=duration, comparison_interval=comparison_interval, event=event, environment_id=self.rule.environment_id, comparison_type=comparison_type) # type: ignore[union-attr] # XXX(CEO): once inc-666 work is concluded, rm try/except except RateLimitExceeded: metrics.incr("rule.event_frequency.snuba_query_limit") diff --git a/tests/tools/mypy_helpers/test_plugin.py b/tests/tools/mypy_helpers/test_plugin.py index 42af5e0fb740a2..f7eaa93e045d93 100644 --- a/tests/tools/mypy_helpers/test_plugin.py +++ b/tests/tools/mypy_helpers/test_plugin.py @@ -234,78 +234,3 @@ def _mypy() -> tuple[int, str]: cfg.write_text('[tool.mypy]\nplugins = ["tools.mypy_helpers.plugin"]\n') ret, out = _mypy() assert ret == 0 - - -def test_resolution_of_objects_across_typevar(tmp_path: pathlib.Path) -> None: - src = """\ -from typing import assert_type, TypeVar - -from sentry.db.models.base import Model - -M = TypeVar("M", bound=Model, covariant=True) - -def f(m: type[M]) -> M: - return m.objects.get() - -class C(Model): pass - -assert_type(f(C), C) -""" - expected = """\ -:8: error: Incompatible return value type (got "Model", expected "M") [return-value] -Found 1 error in 1 file (checked 1 source file) -""" - - # tools tests aren't allowed to import from `sentry` so we fixture - # the particular source file we are testing - models_dir = tmp_path.joinpath("sentry/db/models") - models_dir.mkdir(parents=True) - - models_base_src = """\ -from typing import ClassVar, Self - -from .manager.base import BaseManager - -class Model: - objects: ClassVar[BaseManager[Self]] -""" - models_dir.joinpath("base.pyi").write_text(models_base_src) - - manager_dir = models_dir.joinpath("manager") - manager_dir.mkdir(parents=True) - - manager_base_src = """\ -from typing import Generic, TypeVar - -M = TypeVar("M") - -class BaseManager(Generic[M]): - def get(self) -> M: ... - """ - manager_dir.joinpath("base.pyi").write_text(manager_base_src) - - cfg = tmp_path.joinpath("mypy.toml") - cfg.write_text("[tool.mypy]\nplugins = []\n") - - # can't use our helper above because we're fixturing sentry src, so mimic it here - def _mypy() -> tuple[int, str]: - ret = subprocess.run( - ( - *(sys.executable, "-m", "mypy"), - *("--config", cfg), - *("-c", src), - ), - env={**os.environ, "MYPYPATH": str(tmp_path)}, - capture_output=True, - encoding="UTF-8", - ) - assert not ret.stderr - return ret.returncode, ret.stdout - - ret, out = _mypy() - assert ret - assert out == expected - - cfg.write_text('[tool.mypy]\nplugins = ["tools.mypy_helpers.plugin"]\n') - ret, out = _mypy() - assert ret == 0 diff --git a/tools/mypy_helpers/plugin.py b/tools/mypy_helpers/plugin.py index 8bd4214e3ce82e..9ee797a4541770 100644 --- a/tools/mypy_helpers/plugin.py +++ b/tools/mypy_helpers/plugin.py @@ -17,8 +17,6 @@ NoneType, Type, TypeOfAny, - TypeType, - TypeVarType, UnionType, ) @@ -116,23 +114,6 @@ def _lazy_service_wrapper_attribute(ctx: AttributeContext, *, attr: str) -> Type return member -def _resolve_objects_for_typevars(ctx: AttributeContext) -> Type: - # XXX: hack around python/mypy#17395 - - # self: type[] - # default_attr_type: BaseManager[ConcreteTypeVarBound] - if ( - isinstance(ctx.type, TypeType) - and isinstance(ctx.type.item, TypeVarType) - and isinstance(ctx.default_attr_type, Instance) - and ctx.default_attr_type.type.fullname == "sentry.db.models.manager.base.BaseManager" - ): - tvar = ctx.type.item - return ctx.default_attr_type.copy_modified(args=(tvar,)) - else: - return ctx.default_attr_type - - class SentryMypyPlugin(Plugin): def get_function_signature_hook( self, fullname: str @@ -146,12 +127,6 @@ def get_base_class_hook(self, fullname: str) -> Callable[[ClassDefContext], None else: return None - def get_class_attribute_hook(self, fullname: str) -> Callable[[AttributeContext], Type] | None: - if fullname.startswith("sentry.") and fullname.endswith(".objects"): - return _resolve_objects_for_typevars - else: - return None - def get_attribute_hook(self, fullname: str) -> Callable[[AttributeContext], Type] | None: if fullname.startswith("sentry.utils.lazy_service_wrapper.LazyServiceWrapper."): _, attr = fullname.rsplit(".", 1)