Skip to content

[ty] Enum literal types#19328

Merged
sharkdp merged 28 commits intomainfrom
david/enum-literals
Jul 15, 2025
Merged

[ty] Enum literal types#19328
sharkdp merged 28 commits intomainfrom
david/enum-literals

Conversation

@sharkdp
Copy link
Contributor

@sharkdp sharkdp commented Jul 14, 2025

Summary

Add a new Type::EnumLiteral(…) variant and infer this type for member accesses on enums.

Example: No more @Todo types here:

from enum import Enum

class Answer(Enum):
    YES = 1
    NO = 2

    def is_yes(self) -> bool:
        return self == Answer.YES

reveal_type(Answer.YES)  # revealed: Literal[Answer.YES]
reveal_type(Answer.YES == Answer.NO)  # revealed: Literal[False]
reveal_type(Answer.YES.is_yes())  # revealed: bool

Test Plan

  • Many new Markdown tests for the new type variant
  • Added enum literal types to property tests, ran property tests

Ecosystem analysis

Lots of false positives removed. All of the new diagnostics are either new true positives (the majority) or known problems. Click for detailed analysis
AutoSplit (https://github.com/Toufool/AutoSplit)
+ error[call-non-callable] src/capture_method/__init__.py:137:9: Method `__getitem__` of type `bound method CaptureMethodDict.__getitem__(key: Never, /) -> type[CaptureMethodBase]` is not callable on object of type `CaptureMethodDict`
+ error[call-non-callable] src/capture_method/__init__.py:147:9: Method `__getitem__` of type `bound method CaptureMethodDict.__getitem__(key: Never, /) -> type[CaptureMethodBase]` is not callable on object of type `CaptureMethodDict`
+ error[call-non-callable] src/capture_method/__init__.py:148:1: Method `__getitem__` of type `bound method CaptureMethodDict.__getitem__(key: Never, /) -> type[CaptureMethodBase]` is not callable on object of type `CaptureMethodDict`

New true positives. That __getitem__ method is apparently annotated with Never to prevent developers from using it.

dd-trace-py (https://github.com/DataDog/dd-trace-py)
+ error[invalid-assignment] ddtrace/vendor/psutil/_common.py:29:5: Object of type `None` is not assignable to `Literal[AddressFamily.AF_INET6]`
+ error[invalid-assignment] ddtrace/vendor/psutil/_common.py:33:5: Object of type `None` is not assignable to `Literal[AddressFamily.AF_UNIX]`

Arguably true positives: https://github.com/DataDog/dd-trace-py/blob/e0a772c28bc3897a4b5df73125274999e0f58f30/ddtrace/vendor/psutil/_common.py#L29

ignite (https://github.com/pytorch/ignite)
+ error[invalid-argument-type] tests/ignite/engine/test_custom_events.py:190:34: Argument to bound method `__call__` is incorrect: Expected `((...) -> Unknown) | None`, found `Literal["123"]`
+ error[invalid-argument-type] tests/ignite/engine/test_custom_events.py:220:37: Argument to function `default_event_filter` is incorrect: Expected `Engine`, found `None`
+ error[invalid-argument-type] tests/ignite/engine/test_custom_events.py:220:43: Argument to function `default_event_filter` is incorrect: Expected `int`, found `None`
+ error[call-non-callable] tests/ignite/engine/test_custom_events.py:561:9: Object of type `CustomEvents` is not callable
+ error[invalid-argument-type] tests/ignite/metrics/test_frequency.py:50:38: Argument to bound method `attach` is incorrect: Expected `Events`, found `CallableEventWithFilter`

All true positives. Some of them are inside pytest.raises(TypeError, …) blocks 🙃

meson (https://github.com/mesonbuild/meson)
+ error[invalid-argument-type] unittests/internaltests.py:243:51: Argument to bound method `__init__` is incorrect: Expected `bool`, found `Literal[MachineChoice.HOST]`
+ error[invalid-argument-type] unittests/internaltests.py:271:51: Argument to bound method `__init__` is incorrect: Expected `bool`, found `Literal[MachineChoice.HOST]`

New true positives. Enum literals can not be assigned to bool, even if their value types are 0 and 1.

poetry (https://github.com/python-poetry/poetry)
+ error[invalid-assignment] src/poetry/console/exceptions.py:101:5: Object of type `Literal[""]` is not assignable to `InitVar[str]`

New false positive, missing support for InitVar.

prefect (https://github.com/PrefectHQ/prefect)
+ error[invalid-argument-type] src/integrations/prefect-dask/tests/test_task_runners.py:193:17: Argument is incorrect: Expected `StateType`, found `Literal[StateType.COMPLETED]`

This is confusing. There are two definitions (one, two) of the StateType enum. Here, we're trying to assign one to the other. I don't think that should be allowed, so this is a true positive (?).

python-htmlgen (https://github.com/srittau/python-htmlgen)
+ error[invalid-assignment] test_htmlgen/form.py:51:9: Object of type `str` is not assignable to attribute `autocomplete` of type `Autocomplete | None`
+ error[invalid-assignment] test_htmlgen/video.py:38:9: Object of type `str` is not assignable to attribute `preload` of type `Preload | None`

True positives. The stubs are wrong. These should not contain type annotations, but rather just OFF = ....

rotki (https://github.com/rotki/rotki)
+ error[invalid-argument-type] rotkehlchen/tests/unit/test_serialization.py:62:30: Argument to bound method `deserialize` is incorrect: Expected `str`, found `Literal[15]`

New true positive.

vision (https://github.com/pytorch/vision)
+ error[unresolved-attribute] test/test_extended_models.py:302:17: Type `type[WeightsEnum]` has no attribute `DEFAULT`
+ error[unresolved-attribute] test/test_extended_models.py:302:58: Type `type[WeightsEnum]` has no attribute `DEFAULT`

Also new true positives. No DEFAULT member exists on WeightsEnum.

@sharkdp sharkdp added ty Multi-file analysis & type inference ecosystem-analyzer labels Jul 14, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Jul 14, 2025

mypy_primer results

Changes were detected when running on open source projects
python-htmlgen (https://github.com/srittau/python-htmlgen)
+ error[invalid-assignment] test_htmlgen/form.py:51:9: Object of type `str` is not assignable to attribute `autocomplete` of type `Autocomplete | None`
+ error[invalid-assignment] test_htmlgen/video.py:38:9: Object of type `str` is not assignable to attribute `preload` of type `Preload | None`
- Found 26 diagnostics
+ Found 28 diagnostics

hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- warning[unused-ignore-comment] src/hydra_zen/structured_configs/_implementations.py:492:89: Unused blanket `type: ignore` directive
- Found 572 diagnostics
+ Found 571 diagnostics

trio (https://github.com/python-trio/trio)
- error[unresolved-attribute] src/trio/_abc.py:223:17: Type `def socket(self, family: Unknown | int = @Todo(Attribute access on enum classes), type: Unknown | int = @Todo(Attribute access on enum classes), proto: int = Literal[0]) -> SocketType` has no attribute `AddressFamily`
- error[unresolved-attribute] src/trio/_abc.py:224:15: Type `def socket(self, family: Unknown | int = @Todo(Attribute access on enum classes), type: Unknown | int = @Todo(Attribute access on enum classes), proto: int = Literal[0]) -> SocketType` has no attribute `SocketKind`
+ error[unresolved-attribute] src/trio/_abc.py:223:17: Type `def socket(self, family: Unknown | int = Literal[AddressFamily.AF_INET], type: Unknown | int = Literal[SocketKind.SOCK_STREAM], proto: int = Literal[0]) -> SocketType` has no attribute `AddressFamily`
+ error[unresolved-attribute] src/trio/_abc.py:224:15: Type `def socket(self, family: Unknown | int = Literal[AddressFamily.AF_INET], type: Unknown | int = Literal[SocketKind.SOCK_STREAM], proto: int = Literal[0]) -> SocketType` has no attribute `SocketKind`

jinja (https://github.com/pallets/jinja)
- warning[unused-ignore-comment] src/jinja2/nodes.py:758:45: Unused blanket `type: ignore` directive
- Found 197 diagnostics
+ Found 196 diagnostics

ignite (https://github.com/pytorch/ignite)
- warning[unused-ignore-comment] ignite/contrib/engines/common.py:194:96: Unused blanket `type: ignore` directive
+ error[invalid-argument-type] tests/ignite/engine/test_custom_events.py:190:34: Argument to bound method `__call__` is incorrect: Expected `((...) -> Unknown) | None`, found `Literal["123"]`
+ error[invalid-argument-type] tests/ignite/engine/test_custom_events.py:220:37: Argument to function `default_event_filter` is incorrect: Expected `Engine`, found `None`
+ error[invalid-argument-type] tests/ignite/engine/test_custom_events.py:220:43: Argument to function `default_event_filter` is incorrect: Expected `int`, found `None`
+ error[call-non-callable] tests/ignite/engine/test_custom_events.py:561:9: Object of type `CustomEvents` is not callable
+ error[invalid-argument-type] tests/ignite/metrics/test_frequency.py:50:38: Argument to bound method `attach` is incorrect: Expected `Events`, found `CallableEventWithFilter`
- Found 2125 diagnostics
+ Found 2129 diagnostics

poetry (https://github.com/python-poetry/poetry)
+ error[invalid-assignment] src/poetry/console/exceptions.py:101:5: Object of type `Literal[""]` is not assignable to `InitVar[str]`
- Found 936 diagnostics
+ Found 937 diagnostics

vision (https://github.com/pytorch/vision)
+ error[unresolved-attribute] test/test_extended_models.py:302:17: Type `type[WeightsEnum]` has no attribute `DEFAULT`
+ error[unresolved-attribute] test/test_extended_models.py:302:58: Type `type[WeightsEnum]` has no attribute `DEFAULT`
- Found 1472 diagnostics
+ Found 1474 diagnostics

yarl (https://github.com/aio-libs/yarl)
- error[invalid-return-type] yarl/_url.py:360:20: Return type does not match returned value: expected `URL`, found `str | SplitResult | URL | UndefinedType | @Todo(Attribute access on enum classes)`
+ error[invalid-return-type] yarl/_url.py:360:20: Return type does not match returned value: expected `URL`, found `str | SplitResult | URL | UndefinedType`

urllib3 (https://github.com/urllib3/urllib3)
- error[invalid-return-type] src/urllib3/_collections.py:386:20: Return type does not match returned value: expected `list[str] | _DT`, found `_Sentinel | _DT | @Todo(Attribute access on enum classes)`
+ error[invalid-return-type] src/urllib3/_collections.py:386:20: Return type does not match returned value: expected `list[str] | _DT`, found `(_Sentinel & ~Literal[_Sentinel.not_passed]) | (_DT & ~Literal[_Sentinel.not_passed])`

AutoSplit (https://github.com/Toufool/AutoSplit)
+ error[call-non-callable] src/capture_method/__init__.py:137:9: Method `__getitem__` of type `bound method CaptureMethodDict.__getitem__(key: Never, /) -> type[CaptureMethodBase]` is not callable on object of type `CaptureMethodDict`
+ error[call-non-callable] src/capture_method/__init__.py:147:9: Method `__getitem__` of type `bound method CaptureMethodDict.__getitem__(key: Never, /) -> type[CaptureMethodBase]` is not callable on object of type `CaptureMethodDict`
+ error[call-non-callable] src/capture_method/__init__.py:148:1: Method `__getitem__` of type `bound method CaptureMethodDict.__getitem__(key: Never, /) -> type[CaptureMethodBase]` is not callable on object of type `CaptureMethodDict`
- Found 38 diagnostics
+ Found 41 diagnostics

pytest (https://github.com/pytest-dev/pytest)
- error[invalid-argument-type] src/_pytest/fixtures.py:157:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Scope`
- error[invalid-argument-type] src/_pytest/fixtures.py:218:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Scope`
+ error[invalid-argument-type] src/_pytest/fixtures.py:157:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Scope & ~Literal[Scope.Function] & ~Literal[Scope.Class] & ~Literal[Scope.Module] & ~Literal[Scope.Package] & ~Literal[Scope.Session]`
+ error[invalid-argument-type] src/_pytest/fixtures.py:218:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Scope & ~Literal[Scope.Function] & ~Literal[Scope.Session] & ~Literal[Scope.Package] & ~Literal[Scope.Module] & ~Literal[Scope.Class]`
- error[invalid-argument-type] src/_pytest/pathlib.py:585:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `ImportMode`
+ error[invalid-argument-type] src/_pytest/pathlib.py:585:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `ImportMode & ~Literal[ImportMode.importlib] & ~Literal[ImportMode.append] & ~Literal[ImportMode.prepend]`
- error[invalid-argument-type] testing/test_cacheprovider.py:1303:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Action`
+ error[invalid-argument-type] testing/test_cacheprovider.py:1303:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Action & ~Literal[Action.MKDIR] & ~Literal[Action.SET]`
- error[invalid-argument-type] testing/test_cacheprovider.py:1315:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Action`
+ error[invalid-argument-type] testing/test_cacheprovider.py:1315:22: Argument to function `assert_never` is incorrect: Expected `Never`, found `Action & ~Literal[Action.MKDIR] & ~Literal[Action.SET]`

django-stubs (https://github.com/typeddjango/django-stubs)
- error[type-assertion-failure] tests/assert_type/db/models/_enums.py:15:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/_enums.py:17:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/_enums.py:23:1: Argument does not have asserted type `Literal[True]`
+ error[subclass-of-final-class] tests/assert_type/db/models/test_enums.py:90:19: Class `VoidChoices` cannot inherit from final class `BaseEmptyChoices`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:139:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:140:1: Argument does not have asserted type `list[@Todo(Support for `typing.TypeAlias`)]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:141:1: Argument does not have asserted type `list[int]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:142:1: Argument does not have asserted type `list[tuple[int, @Todo(Support for `typing.TypeAlias`)]]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:147:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:150:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:151:1: Argument does not have asserted type `list[@Todo(Support for `typing.TypeAlias`)]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:152:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:153:1: Argument does not have asserted type `list[tuple[str, @Todo(Support for `typing.TypeAlias`)]]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:158:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:162:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:163:1: Argument does not have asserted type `list[@Todo(Support for `typing.TypeAlias`)]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:170:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:176:1: Argument does not have asserted type `list[str]`
+ error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:171:1: Argument does not have asserted type `@Todo(Support for `typing.TypeAlias`)`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:184:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:189:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:191:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:197:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:202:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:210:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:216:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:224:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:230:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:238:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:243:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:245:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:251:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:255:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:257:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:263:1: Argument does not have asserted type `Literal[True]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:267:1: Argument does not have asserted type `list[str]`
- error[type-assertion-failure] tests/assert_type/db/models/test_enums.py:269:1: Argument does not have asserted type `list[str]`
- Found 464 diagnostics
+ Found 431 diagnostics

meson (https://github.com/mesonbuild/meson)
+ error[invalid-argument-type] unittests/internaltests.py:243:51: Argument to bound method `__init__` is incorrect: Expected `bool`, found `Literal[MachineChoice.HOST]`
+ error[invalid-argument-type] unittests/internaltests.py:271:51: Argument to bound method `__init__` is incorrect: Expected `bool`, found `Literal[MachineChoice.HOST]`
- Found 901 diagnostics
+ Found 903 diagnostics

zulip (https://github.com/zulip/zulip)
+ error[invalid-assignment] zerver/actions/message_send.py:1834:5: Invalid assignment to data descriptor attribute `type` on type `Message` with custom `__set__` method
- Found 7265 diagnostics
+ Found 7266 diagnostics

dd-trace-py (https://github.com/DataDog/dd-trace-py)
+ error[invalid-assignment] ddtrace/vendor/psutil/_common.py:29:5: Object of type `None` is not assignable to `Literal[AddressFamily.AF_INET6]`
+ error[invalid-assignment] ddtrace/vendor/psutil/_common.py:33:5: Object of type `None` is not assignable to `Literal[AddressFamily.AF_UNIX]`
- Found 6822 diagnostics
+ Found 6824 diagnostics

prefect (https://github.com/PrefectHQ/prefect)
+ error[invalid-argument-type] src/integrations/prefect-dask/tests/test_task_runners.py:193:17: Argument is incorrect: Expected `StateType`, found `Literal[StateType.COMPLETED]`
- Found 3728 diagnostics
+ Found 3729 diagnostics

rotki (https://github.com/rotki/rotki)
+ error[invalid-assignment] rotkehlchen/assets/asset.py:77:5: Object of type `Literal[False]` is not assignable to `InitVar[bool]`
- warning[unused-ignore-comment] rotkehlchen/chain/aggregator.py:582:83: Unused blanket `type: ignore` directive
- warning[unused-ignore-comment] rotkehlchen/exchanges/kraken.py:953:57: Unused blanket `type: ignore` directive
- error[invalid-argument-type] rotkehlchen/tests/api/test_exchanges.py:524:52: Argument to function `patch_poloniex_balances_query` is incorrect: Expected `Poloniex`, found `Binance`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:673:12: Type `Binance` has no attribute `account_type`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:713:12: Type `Binance` has no attribute `account_type`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:788:12: Type `Binance` has no attribute `api_passphrase`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:801:12: Type `Binance` has no attribute `api_passphrase`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:823:12: Type `Binance` has no attribute `account_type`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:824:12: Type `Binance` has no attribute `call_limit`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:825:12: Type `Binance` has no attribute `reduction_every_secs`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:834:12: Type `Binance` has no attribute `account_type`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:835:12: Type `Binance` has no attribute `call_limit`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:836:12: Type `Binance` has no attribute `reduction_every_secs`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:846:12: Type `Binance` has no attribute `account_type`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:847:12: Type `Binance` has no attribute `call_limit`
- error[unresolved-attribute] rotkehlchen/tests/api/test_exchanges.py:848:12: Type `Binance` has no attribute `reduction_every_secs`
- warning[unused-ignore-comment] rotkehlchen/tests/api/test_exchanges.py:869:78: Unused blanket `type: ignore` directive
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:872:21: Attribute `name` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:874:31: Attribute `name` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:886:20: Attribute `api_key` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:888:24: Attribute `secret` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:893:54: Attribute `session` on type `Binance | None` is possibly unbound
- warning[unused-ignore-comment] rotkehlchen/tests/api/test_exchanges.py:897:78: Unused blanket `type: ignore` directive
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:900:21: Attribute `name` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:902:31: Attribute `name` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:914:20: Attribute `api_key` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:916:24: Attribute `secret` on type `Binance | None` is possibly unbound
- warning[possibly-unbound-attribute] rotkehlchen/tests/api/test_exchanges.py:921:54: Attribute `session` on type `Binance | None` is possibly unbound
- error[invalid-assignment] rotkehlchen/tests/exchanges/test_kraken.py:933:5: Object of type `Literal[False]` is not assignable to attribute `random_ledgers_data` on type `Binance | None`
+ error[invalid-assignment] rotkehlchen/tests/exchanges/test_kraken.py:933:5: Object of type `Literal[False]` is not assignable to attribute `random_ledgers_data` on type `Kraken | None`
- warning[possibly-unbound-attribute] rotkehlchen/tests/exchanges/test_kraken.py:935:9: Attribute `query_history_events` on type `Binance | None` is possibly unbound
+ warning[possibly-unbound-attribute] rotkehlchen/tests/exchanges/test_kraken.py:935:9: Attribute `query_history_events` on type `Kraken | None` is possibly unbound
+ error[invalid-argument-type] rotkehlchen/tests/unit/test_serialization.py:62:30: Argument to bound method `deserialize` is incorrect: Expected `str`, found `Literal[15]`
- error[invalid-argument-type] rotkehlchen/tests/utils/rotkehlchen.py:181:52: Argument to function `patch_poloniex_balances_query` is incorrect: Expected `Poloniex`, found `Binance & ~AlwaysFalsy`
- Found 1606 diagnostics
+ Found 1579 diagnostics
Memory usage changes were detected when running on open source projects
trio (https://github.com/python-trio/trio)
-     memo metadata = ~20MB
+     memo metadata = ~21MB

@github-actions
Copy link
Contributor

github-actions bot commented Jul 14, 2025

ecosystem-analyzer results

Lint rule Added Removed Changed
type-assertion-failure 1 35 0
unresolved-attribute 2 13 2
invalid-argument-type 8 2 5
possibly-unbound-attribute 0 10 1
invalid-assignment 7 0 1
unused-ignore-comment 0 7 0
call-non-callable 4 0 0
invalid-return-type 0 0 2
subclass-of-final-class 1 0 0
Total 23 67 11

Full report with detailed diff

Comment on lines +403 to +405
# TODO: This should not be an error. The return type should be `A | B | C` once enums are expanded
# error: [no-matching-overload]
reveal_type(f(x)) # revealed: Unknown
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not implemented expansion of enums yet. I didn't see any ecosystem impact (no new no-matching-overload diagnostics or similar), so I guess this change is fine. Returning Unknown instead of A seems better anyway.

@github-actions

This comment was marked as off-topic.

@sharkdp sharkdp force-pushed the david/enum-literals branch from 2fa37d4 to cfae2bc Compare July 15, 2025 08:46
@sharkdp sharkdp marked this pull request as ready for review July 15, 2025 09:57
Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!!

@codspeed-hq
Copy link

codspeed-hq bot commented Jul 15, 2025

CodSpeed Instrumentation Performance Report

Merging #19328 will degrade performances by 5.69%

Comparing david/enum-literals (d0060c2) with main (a0d4e1f)

Summary

⚡ 1 improvements
❌ 2 (👁 2) regressions
✅ 37 untouched benchmarks
🆕 1 new benchmarks

Benchmarks breakdown

Benchmark BASE HEAD Change
👁 ty_micro[complex_constrained_attributes_1] 58 ms 61.5 ms -5.69%
👁 ty_micro[complex_constrained_attributes_2] 57.7 ms 60.8 ms -5.12%
🆕 ty_micro[many_enum_members] N/A 112.4 ms N/A
ty_micro[many_string_assignments] 78 ms 74.8 ms +4.28%

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

@AlexWaygood
Copy link
Member

hmm, could the codspeed complaints be due to the changes to try_bool? IIRC that's a very hot funciton

@sharkdp
Copy link
Contributor Author

sharkdp commented Jul 15, 2025

hmm, could the codspeed complaints be due to the changes to try_bool? IIRC that's a very hot funciton

No, I'm afraid it might be due to the new is_final changes? Looking into it.

@sharkdp sharkdp force-pushed the david/enum-literals branch 2 times, most recently from ef50d99 to 9ee7fe9 Compare July 15, 2025 18:45
@sharkdp sharkdp force-pushed the david/enum-literals branch from 9ee7fe9 to d0060c2 Compare July 15, 2025 18:54
@sharkdp
Copy link
Contributor Author

sharkdp commented Jul 15, 2025

Benchmark BASE HEAD Change
ty_micro[complex_constrained_attributes_1] 58 ms 61.5 ms -5.69%
ty_micro[complex_constrained_attributes_2] 57.7 ms 60.8 ms -5.12%
🆕 ty_micro[many_enum_members] N/A 112.4 ms N/A
ty_micro[many_string_assignments] 78 ms 74.8 ms +4.28%

I did find a way to reduce the regression from -8% to -5% in the complex_constrained_attributes_* benchmarks. In the process, many_string_assignments is now suddenly a +4.28% improvement — I do not understand why. All of these benchmarks are extremely short (they are regression tests for cases where we initially took a long time). And we do need to perform some more work on this branch, because whenever we check if a type is final, we now also check if it's an enum — which requires a MRO traversal.

I don't think that small regressions on these benchmarks are a huge deal, and all other benchmarks are below -2%, so I'm not going to investigate much further. Not because I'm out of ideas, but because it starts to feel like there are more important things to do. If someone disagrees, please let me know. Happy to take another look.

@sharkdp sharkdp merged commit a1edb69 into main Jul 15, 2025
37 checks passed
@sharkdp sharkdp deleted the david/enum-literals branch July 15, 2025 19:31
UnboundVariable pushed a commit to UnboundVariable/ruff that referenced this pull request Jul 15, 2025
* main:
  [ty] Enum literal types (astral-sh#19328)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants