-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Add a class attribute hook to the plugin system #9881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
23aeeb0
f1852e1
bbac561
379aa60
987207a
a976739
af49c12
1816cf6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -902,3 +902,92 @@ reveal_type(f()) # N: Revealed type is "builtins.str" | |||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/method_in_decorator.py | ||||||
|
||||||
[case testClassAttrPluginClassVar] | ||||||
# flags: --config-file tmp/mypy.ini | ||||||
|
||||||
from typing import Type | ||||||
|
||||||
class Cls: | ||||||
attr = 'test' | ||||||
unchanged = 'test' | ||||||
|
||||||
reveal_type(Cls().attr) # N: Revealed type is "builtins.str" | ||||||
reveal_type(Cls.attr) # N: Revealed type is "builtins.int" | ||||||
reveal_type(Cls.unchanged) # N: Revealed type is "builtins.str" | ||||||
x: Type[Cls] | ||||||
reveal_type(x.attr) # N: Revealed type is "builtins.int" | ||||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/class_attr_hook.py | ||||||
|
||||||
[case testClassAttrPluginMethod] | ||||||
# flags: --config-file tmp/mypy.ini | ||||||
|
||||||
class Cls: | ||||||
def attr(self) -> None: | ||||||
pass | ||||||
|
||||||
reveal_type(Cls.attr) # N: Revealed type is "builtins.int" | ||||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/class_attr_hook.py | ||||||
|
||||||
[case testClassAttrPluginEnum] | ||||||
# flags: --config-file tmp/mypy.ini | ||||||
|
||||||
import enum | ||||||
|
||||||
class Cls(enum.Enum): | ||||||
attr = 'test' | ||||||
|
||||||
reveal_type(Cls.attr) # N: Revealed type is "builtins.int" | ||||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/class_attr_hook.py | ||||||
|
||||||
[case testClassAttrPluginMetaclassAnyBase] | ||||||
# flags: --config-file tmp/mypy.ini | ||||||
|
||||||
from typing import Any, Type | ||||||
class M(type): | ||||||
attr = 'test' | ||||||
|
||||||
B: Any | ||||||
class Cls(B, metaclass=M): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to use one more test example with real There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added! |
||||||
pass | ||||||
|
||||||
reveal_type(Cls.attr) # N: Revealed type is "builtins.int" | ||||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/class_attr_hook.py | ||||||
|
||||||
[case testClassAttrPluginMetaclassRegularBase] | ||||||
# flags: --config-file tmp/mypy.ini | ||||||
|
||||||
from typing import Any, Type | ||||||
class M(type): | ||||||
attr = 'test' | ||||||
|
||||||
class B: | ||||||
attr = None | ||||||
|
||||||
class Cls(B, metaclass=M): | ||||||
pass | ||||||
|
||||||
reveal_type(Cls.attr) # N: Revealed type is "builtins.int" | ||||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/class_attr_hook.py | ||||||
|
||||||
[case testClassAttrPluginPartialType] | ||||||
# flags: --config-file tmp/mypy.ini | ||||||
|
||||||
class Cls: | ||||||
attr = None | ||||||
def f(self) -> int: | ||||||
return Cls.attr + 1 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about I think we can also check that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, so it looks like adding a test for The way this is done in other tests is via The other one is already tested above: mypy/test-data/unit/check-custom-plugin.test Lines 918 to 919 in af49c12
|
||||||
|
||||||
[file mypy.ini] | ||||||
\[mypy] | ||||||
plugins=<ROOT>/test-data/unit/plugins/class_attr_hook.py |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from typing import Callable, Optional | ||
|
||
from mypy.plugin import AttributeContext, Plugin | ||
from mypy.types import Type as MypyType | ||
|
||
|
||
class ClassAttrPlugin(Plugin): | ||
def get_class_attribute_hook(self, fullname: str | ||
) -> Optional[Callable[[AttributeContext], MypyType]]: | ||
if fullname == '__main__.Cls.attr': | ||
return my_hook | ||
return None | ||
|
||
|
||
def my_hook(ctx: AttributeContext) -> MypyType: | ||
return ctx.api.named_generic_type('builtins.int', []) | ||
|
||
|
||
def plugin(_version: str): | ||
return ClassAttrPlugin |
Uh oh!
There was an error while loading. Please reload this page.