fix new rule - ban dynamic types #3765#3869
Conversation
|
Diff from mypy_primer, showing the effect of this PR on open source code: mkdocs (https://github.com/mkdocs/mkdocs)
+ ERROR mkdocs/config/config_options.py:101:28-31: Base class `type[Self@SubConfig]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR mkdocs/plugins.py:75:28-31: Base class `type[Self@BasePlugin]` in `type()` call is not a statically known class [unsupported-dynamic-base]
steam.py (https://github.com/Gobot1234/steam.py)
+ ERROR steam/_gc/client.py:74:32-46: Base classes in `type()` calls must be a tuple literal of statically known classes [unsupported-dynamic-base]
+ ERROR steam/enums.py:120:13-122:14: Base classes in `type()` calls must be a tuple literal of statically known classes [unsupported-dynamic-base]
spark (https://github.com/apache/spark)
+ ERROR python/pyspark/pandas/typedef/typehints.py:881:43-55: Base class `type[IndexNameTypeHolder | NameTypeHolder]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR python/pyspark/pandas/typedef/typehints.py:901:43-55: Base class `type[IndexNameTypeHolder | NameTypeHolder]` in `type()` call is not a statically known class [unsupported-dynamic-base]
scikit-build-core (https://github.com/scikit-build/scikit-build-core)
+ ERROR src/scikit_build_core/setuptools/wrapper.py:71:14-23: Base class `type[_DistributionT]` in `type()` call is not a statically known class [unsupported-dynamic-base]
bidict (https://github.com/jab/bidict)
+ ERROR bidict/_base.py:148:47-50: Base class `type[Self@BidictBase]` in `type()` call is not a statically known class [unsupported-dynamic-base]
psycopg (https://github.com/psycopg/psycopg)
+ ERROR psycopg/psycopg/types/array.py:339:52-56: Base class `type[ArrayLoader] | Any` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR psycopg/psycopg/types/json.py:120:26-30: Base class `type[Dumper]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR psycopg/psycopg/types/json.py:140:26-30: Base class `type[Loader]` in `type()` call is not a statically known class [unsupported-dynamic-base]
schemathesis (https://github.com/schemathesis/schemathesis)
+ ERROR src/schemathesis/core/deserialization.py:137:54-64: Base class `type[CSafeLoader] | type[SafeLoader]` in `type()` call is not a statically known class [unsupported-dynamic-base]
beartype (https://github.com/beartype/beartype)
+ ERROR beartype/_util/cls/utilclsmake.py:104:27-37: Base classes in `type()` calls must be a tuple literal of statically known classes [unsupported-dynamic-base]
pytest-autoprofile (https://gitlab.com/TTsangSC/pytest-autoprofile)
+ ERROR src/pytest_autoprofile/_doctest.py:361:38-48: Base class `type[DocTestRunner]` in `type()` call is not a statically known class [unsupported-dynamic-base]
pandera (https://github.com/pandera-dev/pandera)
+ ERROR pandera/api/dataframe/model.py:340:55-58: Base class `type[Self@DataFrameModel]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pandera/api/dataframe/model.py:507:32-42: Base class `type[BaseConfig]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pandera/api/pyspark/model.py:214:55-58: Base class `type[Self@DataFrameModel]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pandera/api/xarray/model.py:263:32-42: Base class `type[DataArrayConfig | DataTreeConfig | DatasetConfig]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pandera/api/xarray/model.py:469:42-52: Base class `type[DataArrayConfig]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pandera/api/xarray/model.py:571:42-52: Base class `type[DatasetConfig]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pandera/api/xarray/model.py:684:42-52: Base class `type[DataTreeConfig]` in `type()` call is not a statically known class [unsupported-dynamic-base]
ibis (https://github.com/ibis-project/ibis)
+ ERROR ibis/expr/operations/udf.py:155:51-60: Base class `[B: Value[Unknown]](self: Self@_UDF) -> type[B]` in `type()` call is not a statically known class [unsupported-dynamic-base]
strawberry (https://github.com/strawberry-graphql/strawberry)
+ ERROR strawberry/tools/merge_types.py:35:39-44: Base classes in `type()` calls must be a tuple literal of statically known classes [unsupported-dynamic-base]
+ ERROR strawberry/types/base.py:341:14-25: Base class `type[Any]` in `type()` call is not a statically known class [unsupported-dynamic-base]
pandas (https://github.com/pandas-dev/pandas)
+ ERROR pandas/tseries/holiday.py:656:34-44: Base class `type[AbstractHolidayCalendar] | Unknown` in `type()` call is not a statically known class [unsupported-dynamic-base]
hydpy (https://github.com/hydpy-dev/hydpy)
+ ERROR hydpy/core/modeltools.py:3244:61-74: Base class `type[Any]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR hydpy/core/testtools.py:1401:47-55: Base class `type[T_inv]` in `type()` call is not a statically known class [unsupported-dynamic-base]
dd-trace-py (https://github.com/DataDog/dd-trace-py)
+ ERROR ddtrace/vendor/debtcollector/moves.py:192:39-48: Base class `type[Any]` in `type()` call is not a statically known class [unsupported-dynamic-base]
werkzeug (https://github.com/pallets/werkzeug)
+ ERROR src/werkzeug/test.py:819:32-48: Base class `type[Response]` in `type()` call is not a statically known class [unsupported-dynamic-base]
core (https://github.com/home-assistant/core)
+ ERROR homeassistant/helpers/deprecation.py:110:14-23: Base class `type` in `type()` call is not a statically known class [unsupported-dynamic-base]
pydantic (https://github.com/pydantic/pydantic)
+ ERROR pydantic/v1/config.py:183:27-39: Base classes in `type()` calls must be a tuple literal of statically known classes [unsupported-dynamic-base]
+ ERROR pydantic/v1/schema.py:1094:50-55: Base class `type[SecretBytes | SecretStr]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pydantic/v1/schema.py:1101:54-59: Base class `type[str]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR pydantic/v1/schema.py:1110:54-59: Base class `type[bytes]` in `type()` call is not a statically known class [unsupported-dynamic-base]
artigraph (https://github.com/artigraph/artigraph)
+ ERROR src/arti/internal/mappings.py:111:49-52: Base class `type[Self@TypedBox]` in `type()` call is not a statically known class [unsupported-dynamic-base]
+ ERROR src/arti/types/__init__.py:341:18-21: Base class `type[Self@_ScalarClassTypeAdapter]` in `type()` call is not a statically known class [unsupported-dynamic-base]
|
Primer Diff Classification❌ 19 regression(s) | 19 project(s) total | +36 errors 19 regression(s) across mkdocs, steam.py, spark, scikit-build-core, bidict, psycopg, schemathesis, beartype, pytest-autoprofile, pandera, ibis, strawberry, pandas, hydpy, dd-trace-py, werkzeug, core, pydantic, artigraph. error kinds:
Detailed analysis❌ Regression (19)mkdocs (+2)
steam.py (+2)
The rule as implemented is strict — it bans ALL non-literal tuple expressions as bases in
spark (+2)
scikit-build-core (+1)
bidict (+1)
psycopg (+3)
schemathesis (+1)
beartype (+1)
pytest-autoprofile (+1)
While the PR's intent is to warn about patterns that pyrefly can't statically analyze, flagging well-established patterns in widely-used projects like pytest creates false positive noise. The check is arguably reasonable from a strict static analysis perspective:
pandera (+7)
Per-category reasoning:
ibis (+1)
In practice,
strawberry (+2)
Error 1 (merge_types.py:35): The function Error 2 (base.py:341): The new rule is overly strict for real-world code. Dynamic class creation with Per-category reasoning:
pandas (+1)
hydpy (+2)
dd-trace-py (+1)
Since This is a completely valid and common Python pattern for dynamic class creation. The three-argument The rule is intentionally strict — it requires bases in
werkzeug (+1)
core (+1)
However, this is a false positive. The pattern of using The rule is too strict — it rejects any non-literal class expression in
pydantic (+4)
artigraph (+2)
Suggested fixesSummary: The new check_dynamic_type_bases() function in call.rs is too strict: it only accepts Type::ClassDef(_) as valid bases in type() calls, but rejects type[X] values (including classmethod cls parameters, type[Self], and type[X] function parameters), unions of class types, and non-literal tuple variables — all of which are valid class objects at runtime. This causes 19 regressions across 19 projects, with the vast majority being pyrefly-only false positives. 1. In
2. In
Was this helpful? React with 👍 or 👎 Classification by primer-classifier (19 LLM) |
Summary
Fixes #3765
Added unsupported-dynamic-base error kind, added builtin type(name, bases, dict) checking, and documented the new error kind.
Test Plan
add test