Skip to content

[ty] Treat custom enum __new__ values as dynamic#25136

Merged
charliermarsh merged 3 commits into
mainfrom
charlie/enum-new
May 13, 2026
Merged

[ty] Treat custom enum __new__ values as dynamic#25136
charliermarsh merged 3 commits into
mainfrom
charlie/enum-new

Conversation

@charliermarsh
Copy link
Copy Markdown
Member

Summary

For enums with a custom __new__, the member RHS is input to the constructor, but __new__ can assign _value_ independently. We now treat such values as dynamically typed, unless _value_ is explicitly annotated.

To quote @JelleZijlstra: "Looks right and fairly simple, behavior matches pyright and mypy."

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label May 13, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented May 13, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 89.36%. The percentage of expected errors that received a diagnostic held steady at 85.49%. The number of fully passing files held steady at 88/134.

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented May 13, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 682.62MB 682.67MB +0.01% (48.97kB)
trio 115.56MB 115.58MB +0.02% (17.96kB)
sphinx 256.21MB 256.23MB +0.01% (15.71kB)
flake8 47.42MB 47.43MB +0.01% (2.84kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
enum_metadata 2.77MB 2.82MB +1.64% (46.63kB)
infer_definition_types 81.05MB 81.05MB +0.00% (1.36kB)
FunctionType 9.48MB 9.48MB +0.01% (672.00B)
OverloadLiteral 3.78MB 3.78MB +0.01% (336.00B)

trio

Name Old New Diff Outcome
Type<'db>::apply_specialization_::interned_arguments 625.08kB 630.31kB +0.84% (5.23kB)
enum_metadata 231.18kB 235.32kB +1.79% (4.15kB)
Type<'db>::apply_specialization_ 616.17kB 619.84kB +0.59% (3.66kB)
infer_scope_types_impl 4.02MB 4.02MB +0.05% (2.09kB)
infer_deferred_types 2.10MB 2.10MB +0.03% (676.00B)
infer_definition_types 7.24MB 7.24MB +0.01% (464.00B)
FunctionType<'db>::signature_ 1.11MB 1.11MB +0.03% (396.00B)
InferableTypeVarsInner 75.81kB 76.15kB +0.44% (344.00B)
FunctionType 1.53MB 1.53MB +0.01% (224.00B)
Specialization 457.11kB 457.33kB +0.05% (224.00B)
GenericContext 124.71kB 124.85kB +0.11% (140.00B)
inferable_typevars_inner 28.96kB 29.10kB +0.46% (136.00B)
bound_typevar_default_type 14.11kB 14.22kB +0.78% (112.00B)
OverloadLiteral 439.33kB 439.44kB +0.02% (112.00B)
BoundTypeVarInstance 162.63kB 162.70kB +0.04% (72.00B)

sphinx

Name Old New Diff Outcome
enum_metadata 704.03kB 715.90kB +1.69% (11.87kB)
infer_deferred_types 4.73MB 4.73MB +0.01% (676.00B)
Type<'db>::apply_specialization_::interned_arguments 1.44MB 1.44MB +0.04% (640.00B)
infer_definition_types 21.99MB 21.99MB +0.00% (464.00B)
Type<'db>::apply_specialization_ 1.41MB 1.41MB +0.03% (448.00B)
FunctionType<'db>::signature_ 2.38MB 2.38MB +0.02% (396.00B)
infer_scope_types_impl 12.97MB 12.97MB +0.00% (252.00B)
FunctionType 3.18MB 3.18MB +0.01% (224.00B)
InferableTypeVarsInner 84.40kB 84.57kB +0.20% (172.00B)
GenericContext 134.89kB 135.02kB +0.10% (140.00B)
Specialization 1018.34kB 1018.45kB +0.01% (112.00B)
OverloadLiteral 1019.27kB 1019.38kB +0.01% (112.00B)
TypeVarInstance 173.44kB 173.53kB +0.05% (96.00B)
BoundTypeVarInstance 624.73kB 624.80kB +0.01% (72.00B)
inferable_typevars_inner 34.97kB 35.04kB +0.19% (68.00B)
... 1 more

flake8

Name Old New Diff Outcome
enum_metadata 64.89kB 66.12kB +1.88% (1.22kB)
infer_definition_types 1.72MB 1.72MB +0.05% (928.00B)
FunctionType 451.45kB 451.89kB +0.10% (448.00B)
OverloadLiteral 120.94kB 121.16kB +0.18% (224.00B)
use_def_map 19.86kB 19.92kB +0.29% (60.00B)

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented May 13, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-assignment 3 0 0
Total 3 0 0

Raw diff:

mypy (https://github.com/python/mypy)
+ mypy/typeshed/stdlib/ssl.pyi:268:5 error[invalid-assignment] Enum member `SERVER_AUTH` is incompatible with `__new__`
+ mypy/typeshed/stdlib/ssl.pyi:269:5 error[invalid-assignment] Enum member `CLIENT_AUTH` is incompatible with `__new__`

typeshed-stats (https://github.com/AlexWaygood/typeshed-stats)
+ tests/test_gather.py:114:13 error[invalid-assignment] Enum member `NOT_A_STRING` is incompatible with `__new__`

Full report with detailed diff (timing results)

@charliermarsh charliermarsh marked this pull request as ready for review May 13, 2026 03:08
reveal_type(Planet2.MERCURY._value_) # revealed: Any
```

### `__new__` without `_value_` annotation
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we test for __new__ coming from a parent class? The code makes explicit allowance for inherited __new__.

class Base(Enum):
def __new__(cls, value: str, connector_id: int = 0) -> "Base":
obj = object.__new__(cls)
obj._value_ = value
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we give any errors if this is set to a different type instead? Probably not essential but would be nice to note.

I tried this sample in multiplay, just changing the annotation on the __new__ to value: int, and only pyright detects the issue.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It appears not today, but I can fix that in a follow-up.

@charliermarsh charliermarsh enabled auto-merge (squash) May 13, 2026 23:14
@charliermarsh charliermarsh disabled auto-merge May 13, 2026 23:16
@charliermarsh charliermarsh merged commit ed819f9 into main May 13, 2026
58 checks passed
@charliermarsh charliermarsh deleted the charlie/enum-new branch May 13, 2026 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants