Skip to content
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

Add __attrs_attrs__ and fields to attrs #10467

Closed
wants to merge 4 commits into from

Conversation

Tinche
Copy link
Contributor

@Tinche Tinche commented May 13, 2021

My first contribution, so sorry if it's not super well-coded.

This improved the attrs plugin in two ways.

Firstly, it makes Mypy aware of the __attrs_attrs__ class variable which attrs generates, and populates it with the proper attr.Attributes. This is not generally used much by attrs users, but is useful for our version of attr.fields, and can be used to write attrs protocols.

Secondly, it modified the return value of attr.fields to return properly instantiated attr.Attributes (which are generic). So now, this type checks:

from typing import TypeVar
from attr import define, Attribute, fields as f

@define
class A:
    a: int

C = TypeVar("C")
T1 = TypeVar("T1")

def test_projection(model: Type[C], field: Attribute[T1]) -> T1:
    pass

reveal_type(test_projection(A, f(A).a))
t.py:28: note: Revealed type is "builtins.int*"

This makes it possible to create ORM/ODM frameworks based on attrs that support statically checked projections, for one.

This would be just the initial implementation for soliciting early feedback, with docs and tests to follow.

@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

mypy (https://github.com/python/mypy.git)
+ /tmp/mypy_primer/projects/_mypy_venv/lib/python3.8/site-packages/_pytest/_code/code.py:666: error: INTERNAL ERROR -- Please try using mypy master on Github:
+ https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
+ Please report a bug at https://github.com/python/mypy/issues
+ version: 0.820+dev.8d8e63a0e381f2271f62ab06cdeefdf5e50ddbac
- mypy/semanal_shared.py:7: error: Library stubs not installed for "mypy_extensions" (or incompatible with Python 3.6)  [import]
+ mypy/build.py:27: error: Library stubs not installed for "mypy_extensions" (or incompatible with Python 3.6)  [import]
- mypy/modulefinder.py:429: error: Library stubs not installed for "toml" (or incompatible with Python 3.6)  [import]
- mypy/plugin.py:124: error: Library stubs not installed for "mypy_extensions" (or incompatible with Python 3.6)  [import]
- mypy/fastparse.py:100: error: Return type becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:109: error: unused 'type: ignore' comment
- mypy/fastparse.py:282: error: Argument 1 to "is_no_type_check_decorator" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:307: error: Type of variable becomes "Dict[type, Callable[[Optional[Any]], Any]]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:320: error: Argument 2 to "visit" becomes "Optional[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:331: error: Argument 3 to "set_line" becomes "Union[Any, Any, Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:337: error: Argument 2 to "translate_opt_expr_list" becomes "Sequence[Optional[Any]]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:344: error: Argument 2 to "translate_expr_list" becomes "Sequence[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:347: error: Argument 2 to "get_lineno" becomes "Union[Any, Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:353: error: Argument 2 to "translate_stmt_list" becomes "Sequence[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:372: error: Argument 2 to "translate_type_comment" becomes "Union[Any, Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:387: error: Type of variable becomes "Dict[Type[Any], str]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:403: error: Argument 2 to "from_operator" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:410: error: Type of variable becomes "Dict[Type[Any], str]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:423: error: Argument 2 to "from_comp_operator" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:430: error: Argument 2 to "as_block" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:437: error: Argument 2 to "as_required_block" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:488: error: Argument 2 to "visit_Module" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:491: error: unused 'type: ignore' comment
- mypy/fastparse.py:508: error: Argument 2 to "visit_FunctionDef" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:513: error: Argument 2 to "visit_AsyncFunctionDef" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:516: error: Argument 2 to "do_func_def" becomes "Union[Any, Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:656: error: Argument 2 to "transform_args" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:662: error: Type of variable becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:699: error: Argument 2 to "make_argument" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:699: error: Argument 3 to "make_argument" becomes "Optional[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:715: error: Argument 3 to "fail_arg" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:723: error: Argument 2 to "visit_ClassDef" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:748: error: Argument 2 to "visit_Return" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:753: error: Argument 2 to "visit_Delete" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:763: error: Argument 2 to "visit_Assign" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:771: error: Argument 2 to "visit_AnnAssign" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:786: error: Argument 2 to "visit_AugAssign" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:793: error: Argument 2 to "visit_For" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:803: error: Argument 2 to "visit_AsyncFor" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:814: error: Argument 2 to "visit_While" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:821: error: Argument 2 to "visit_If" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:829: error: Argument 2 to "visit_With" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:838: error: Argument 2 to "visit_AsyncWith" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:848: error: Argument 2 to "visit_Raise" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:853: error: Argument 2 to "visit_Try" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:869: error: Argument 2 to "visit_Assert" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:874: error: Argument 2 to "visit_Import" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:890: error: Argument 2 to "visit_ImportFrom" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:903: error: Argument 2 to "visit_Global" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:908: error: Argument 2 to "visit_Nonlocal" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:913: error: Argument 2 to "visit_Expr" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:919: error: Argument 2 to "visit_Pass" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:924: error: Argument 2 to "visit_Break" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:929: error: Argument 2 to "visit_Continue" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:940: error: Argument 2 to "visit_BoolOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:954: error: Argument 4 to "group" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:962: error: Argument 2 to "visit_BinOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:972: error: Argument 2 to "visit_UnaryOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:990: error: Argument 2 to "visit_Lambda" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1001: error: Argument 2 to "visit_IfExp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1008: error: Argument 2 to "visit_Dict" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1014: error: Argument 2 to "visit_Set" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1019: error: Argument 2 to "visit_ListComp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1020: error: Target type of cast becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1024: error: Argument 2 to "visit_SetComp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1025: error: Target type of cast becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1029: error: Argument 2 to "visit_DictComp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1043: error: Argument 2 to "visit_GeneratorExp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1056: error: Argument 2 to "visit_Await" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1062: error: Argument 2 to "visit_Yield" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1067: error: Argument 2 to "visit_YieldFrom" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1072: error: Argument 2 to "visit_Compare" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1080: error: Argument 2 to "visit_Call" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1120: error: Argument 2 to "visit_Num" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1137: error: Argument 2 to "visit_Str" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1148: error: Argument 2 to "visit_JoinedStr" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1167: error: Argument 2 to "visit_FormattedValue" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1187: error: Argument 2 to "visit_Bytes" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1192: error: Argument 2 to "visit_NameConstant" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1197: error: Argument 2 to "visit_Ellipsis" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1202: error: Argument 2 to "visit_Attribute" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1215: error: Argument 2 to "visit_Subscript" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1233: error: Argument 2 to "visit_Starred" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1238: error: Argument 2 to "visit_Name" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1243: error: Argument 2 to "visit_List" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1253: error: Argument 2 to "visit_Tuple" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1260: error: Argument 2 to "visit_Slice" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1266: error: Argument 2 to "visit_ExtSlice" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1271: error: Argument 2 to "visit_Index" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1287: error: Type of variable becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1302: error: Argument 2 to "invalid_type" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1321: error: Argument 2 to "visit" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1324: error: Argument 2 to "visit" becomes "Optional[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1324: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader  [misc]
- mypy/fastparse.py:1326: error: Argument 2 to "visit" becomes "Optional[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1341: error: Return type becomes "Optional[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1355: error: Argument 2 to "translate_expr_list" becomes "Sequence[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1369: error: Argument 2 to "visit_Call" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1415: error: Argument 2 to "translate_argument_list" becomes "Sequence[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1418: error: Argument 2 to "_extract_argument_name" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1427: error: Argument 2 to "visit_Name" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1430: error: Argument 2 to "visit_BinOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1442: error: Argument 2 to "visit_NameConstant" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1477: error: Argument 2 to "visit_UnaryOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1487: error: Argument 3 to "numeric_type" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1513: error: Argument 2 to "visit_Num" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1517: error: Argument 2 to "visit_Str" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1538: error: Argument 2 to "visit_Bytes" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1544: error: Argument 2 to "visit_Subscript" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1574: error: Argument 2 to "visit_Tuple" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1579: error: Argument 2 to "visit_Attribute" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1588: error: Argument 2 to "visit_Ellipsis" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1592: error: Argument 2 to "visit_List" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse.py:1597: error: Argument 1 to "stringify_name" becomes "Any" due to an unfollowed import  [no-any-unimported]
+ mypy/modulefinder.py:429: error: Library stubs not installed for "toml" (or incompatible with Python 3.6)  [import]
+ mypy/plugin.py:124: error: Library stubs not installed for "mypy_extensions" (or incompatible with Python 3.6)  [import]
+ mypy/semanal_shared.py:7: error: Library stubs not installed for "mypy_extensions" (or incompatible with Python 3.6)  [import]
- mypy/fastparse2.py:68: error: unused 'type: ignore' comment
- mypy/fastparse2.py:133: error: Argument 1 to "is_no_type_check_decorator" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:173: error: Type of variable becomes "Dict[type, Callable[[Optional[Any]], Any]]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:181: error: Argument 2 to "visit" becomes "Optional[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:192: error: Argument 3 to "set_line" becomes "Union[Any, Any, Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:197: error: Argument 2 to "translate_expr_list" becomes "Sequence[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:205: error: Argument 2 to "get_lineno" becomes "Union[Any, Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:210: error: Argument 2 to "translate_stmt_list" becomes "Sequence[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:229: error: Argument 2 to "translate_type_comment" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:244: error: Type of variable becomes "Dict[Type[Any], str]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:259: error: Argument 2 to "from_operator" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:268: error: Type of variable becomes "Dict[Type[Any], str]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:281: error: Argument 2 to "from_comp_operator" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:288: error: Argument 2 to "as_block" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:295: error: Argument 2 to "as_required_block" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:346: error: Argument 2 to "visit_Module" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:349: error: unused 'type: ignore' comment
- mypy/fastparse2.py:366: error: Argument 2 to "visit_FunctionDef" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:479: error: Argument 2 to "transform_args" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:528: error: Argument 2 to "extract_names" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:536: error: Argument 3 to "convert_arg" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:570: error: Argument 2 to "stringify_name" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:583: error: Argument 2 to "visit_ClassDef" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:599: error: Argument 2 to "visit_Return" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:604: error: Argument 2 to "visit_Delete" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:614: error: Argument 2 to "visit_Assign" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:622: error: Argument 2 to "visit_AugAssign" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:629: error: Argument 2 to "visit_For" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:639: error: Argument 2 to "visit_While" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:646: error: Argument 2 to "visit_If" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:653: error: Argument 2 to "visit_With" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:661: error: Argument 2 to "visit_Raise" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:677: error: Argument 2 to "visit_TryExcept" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:681: error: Argument 2 to "visit_TryFinally" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:688: error: Argument 2 to "try_handler" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:688: error: Argument 3 to "try_handler" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:688: error: Argument 4 to "try_handler" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:688: error: Argument 5 to "try_handler" becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:714: error: Argument 2 to "visit_Print" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:718: error: Argument 2 to "visit_Exec" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:724: error: Argument 2 to "visit_Repr" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:729: error: Argument 2 to "visit_Assert" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:734: error: Argument 2 to "visit_Import" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:750: error: Argument 2 to "visit_ImportFrom" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:766: error: Argument 2 to "visit_Global" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:771: error: Argument 2 to "visit_Expr" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:777: error: Argument 2 to "visit_Pass" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:782: error: Argument 2 to "visit_Break" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:787: error: Argument 2 to "visit_Continue" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:794: error: Argument 2 to "visit_BoolOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:815: error: Argument 2 to "visit_BinOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:825: error: Argument 2 to "visit_UnaryOp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:843: error: Argument 2 to "visit_Lambda" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:858: error: Argument 2 to "visit_IfExp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:865: error: Argument 2 to "visit_Dict" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:871: error: Argument 2 to "visit_Set" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:876: error: Argument 2 to "visit_ListComp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:877: error: Target type of cast becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:881: error: Argument 2 to "visit_SetComp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:882: error: Target type of cast becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:886: error: Argument 2 to "visit_DictComp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:899: error: Argument 2 to "visit_GeneratorExp" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:911: error: Argument 2 to "visit_Yield" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:916: error: Argument 2 to "visit_Compare" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:924: error: Argument 2 to "visit_Call" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:925: error: Type of variable becomes "List[Any]" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:956: error: Argument 2 to "visit_Num" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:982: error: Argument 2 to "visit_Str" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1000: error: Argument 2 to "visit_Ellipsis" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1004: error: Argument 2 to "visit_Attribute" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1020: error: Argument 2 to "visit_Subscript" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1030: error: Argument 2 to "visit_Name" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1035: error: Argument 2 to "visit_List" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1045: error: Argument 2 to "visit_Tuple" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1052: error: Argument 2 to "visit_Slice" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1058: error: Argument 2 to "visit_ExtSlice" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/fastparse2.py:1062: error: Argument 2 to "visit_Index" becomes "Any" due to an unfollowed import  [no-any-unimported]
- mypy/typeanal.py:1012: error: Invalid argument constructor "mypy.typeanal.DefaultNamedArg"  [misc]
- mypy/build.py:27: error: Library stubs not installed for "mypy_extensions" (or incompatible with Python 3.6)  [import]
- mypy/build.py:597: error: Variable "mypy.build.FgDepMeta" is not valid as a type  [valid-type]
- mypy/build.py:597: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
- mypy/build.py:805: error: Value of type FgDepMeta? is not indexable  [index]
- mypy/build.py:1038: error: Variable "mypy.build.FgDepMeta" is not valid as a type  [valid-type]
- mypy/build.py:1038: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
+ Traceback (most recent call last):
+   File "/tmp/mypy_primer/new_mypy/venv/bin/mypy", line 8, in <module>
+     sys.exit(console_entry())
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/__main__.py", line 11, in console_entry
+     main(None, sys.stdout, sys.stderr)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/main.py", line 98, in main
+     res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/build.py", line 179, in build
+     result = _build(
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/build.py", line 253, in _build
+     graph = dispatch(sources, manager, stdout)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/build.py", line 2688, in dispatch
+     process_graph(graph, manager)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/build.py", line 3012, in process_graph
+     process_stale_scc(graph, scc, manager)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/build.py", line 3104, in process_stale_scc
+     mypy.semanal_main.semantic_analysis_for_scc(graph, scc, manager.errors)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal_main.py", line 78, in semantic_analysis_for_scc
+     process_top_levels(graph, scc, patches)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal_main.py", line 199, in process_top_levels
+     deferred, incomplete, progress = semantic_analyze_target(next_id, state,
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal_main.py", line 326, in semantic_analyze_target
+     analyzer.refresh_partial(refresh_node,
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 394, in refresh_partial
+     self.refresh_top_level(node)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 405, in refresh_top_level
+     self.accept(d)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 4853, in accept
+     node.accept(self)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/nodes.py", line 950, in accept
+     return visitor.visit_class_def(self)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 1051, in visit_class_def
+     self.analyze_class(defn)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 1128, in analyze_class
+     self.analyze_class_body_common(defn)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 1137, in analyze_class_body_common
+     self.apply_class_plugin_hooks(defn)
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/semanal.py", line 1183, in apply_class_plugin_hooks
+     hook(ClassDefContext(defn, decorator, self))
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/plugins/attrs.py", line 340, in attr_class_maker_callback
+     {
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/plugins/attrs.py", line 349, in <dictcomp>
+     [a.argument(ctx).type_annotation]),
+   File "/tmp/mypy_primer/new_mypy/venv/lib/python3.8/site-packages/mypy/plugins/attrs.py", line 89, in argument
+     assert self.init
+ AssertionError: 



pytest (https://github.com/pytest-dev/pytest.git)
+ testing/conftest.py:197: error: INTERNAL ERROR -- Please try using mypy master on Github:
+ https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
+ If this issue continues with mypy master, please report a bug at https://github.com/python/mypy/issues
+ version: 0.820+dev.8d8e63a0e381f2271f62ab06cdeefdf5e50ddbac
+ testing/conftest.py:197: : note: please use --show-traceback to print a traceback when reporting a bug
+ src/_pytest/skipping.py:12: error: Library stubs not installed for "attr" (or incompatible with Python 3.8)  [import]
+ testing/python/metafunc.py:15: error: Library stubs not installed for "attr" (or incompatible with Python 3.8)  [import]
+ testing/acceptance_test.py:5: error: Library stubs not installed for "attr" (or incompatible with Python 3.8)  [import]
- testing/acceptance_test.py:5: error: Library stubs not installed for "attr" (or incompatible with Python 3.8)  [import]
- testing/acceptance_test.py:131: error: Too many arguments for "DummyEntryPoint"  [call-arg]
- testing/acceptance_test.py:132: error: Too many arguments for "DummyEntryPoint"  [call-arg]
- testing/acceptance_test.py:133: error: Too many arguments for "DummyEntryPoint"  [call-arg]
- testing/acceptance_test.py:142: error: Too many arguments for "DummyDist"  [call-arg]
- testing/python/metafunc.py:15: error: Library stubs not installed for "attr" (or incompatible with Python 3.8)  [import]
- testing/python/metafunc.py:150: error: Too many arguments for "DummyFixtureDef"  [call-arg]
- testing/python/metafunc.py:151: error: Too many arguments for "DummyFixtureDef"  [call-arg]
- testing/python/metafunc.py:152: error: Too many arguments for "DummyFixtureDef"  [call-arg]
- testing/python/metafunc.py:153: error: Too many arguments for "DummyFixtureDef"  [call-arg]
- testing/python/metafunc.py:154: error: Too many arguments for "DummyFixtureDef"  [call-arg]
- testing/code/test_excinfo.py:535: error: Unexpected keyword argument "showlocals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:550: error: Unexpected keyword argument "showlocals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:550: error: Unexpected keyword argument "truncate_locals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:569: error: Unexpected keyword argument "showlocals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:569: error: Unexpected keyword argument "truncate_locals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:579: error: Unexpected keyword argument "showlocals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:585: error: Unexpected keyword argument "showlocals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:585: error: Unexpected keyword argument "truncate_locals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:609: error: Unexpected keyword argument "showlocals" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:634: error: Unexpected keyword argument "funcargs" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:642: error: Unexpected keyword argument "funcargs" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:661: error: Unexpected keyword argument "funcargs" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:668: error: Unexpected keyword argument "funcargs" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:685: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:695: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:714: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:717: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:733: error: Unexpected keyword argument "tbfilter" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:736: error: Unexpected keyword argument "tbfilter" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:753: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:756: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:778: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:804: error: Unexpected keyword argument "abspath" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:887: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_excinfo.py:1378: error: Unexpected keyword argument "style" for "FormattedExcinfo"  [call-arg]
- testing/code/test_code.py:189: error: Too many arguments for "ReprFuncArgs"  [call-arg]
- src/_pytest/skipping.py:12: error: Library stubs not installed for "attr" (or incompatible with Python 3.8)  [import]
- src/_pytest/skipping.py:178: error: Too many arguments for "Skip"  [call-arg]
- src/_pytest/skipping.py:184: error: Too many arguments for "Skip"  [call-arg]
- src/_pytest/skipping.py:188: error: Too many arguments for "Skip"  [call-arg]
- src/_pytest/skipping.py:219: error: Too many arguments for "Xfail"  [call-arg]
- src/_pytest/skipping.py:225: error: Too many arguments for "Xfail"  [call-arg]
- src/_pytest/doctest.py:339: error: Too many arguments for "ReprFileLocation"  [call-arg]

@euresti
Copy link
Contributor

euresti commented May 14, 2021

This looks like a reasonable approach. As you can tell from all the errors there are some issues. I'm guessing there needs to be a lot of isinstance checks and lots of error handlings (e.g. I think lookup_fully_qualified("attr.Attribute",...) fails if you don't have the right stubs.

Oh and lots of comments because the code is definitely not self explanatory. :)

@@ -257,6 +258,14 @@ def _get_decorator_optional_bool_argument(
return default


def _make_var(n: str, i: Type, fullname: Optional[str] = None, is_classvar: bool = False) -> Var:
Copy link
Member

Choose a reason for hiding this comment

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

Maybe using name and instance as var names would be better?

},
)
cd = ClassDef(f"{info.name}Attributes", Block([]))
cd.fullname = f"{info.name}Attributes"
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't it be f"{info.fullname}Attributes"? https://github.com/python/mypy/blob/master/mypy/nodes.py#L2471

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looking at the runtime behavior, looks like the inner class is actually just called {name}Attributes, and the __module__ is 'builtins', always.

>>> import a
>>> a.A
<class 'a.A'>
>>> a.A.__attrs_attrs__
(Attribute(name='x', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=<class 'str'>, converter=<function converter at 0x7fcd03db2040>, kw_only=False, inherited=False, on_setattr=None),)
>>> a.A.__attrs_attrs__.__class__
<class 'AAttributes'>
>>> a.A.__attrs_attrs__.__module__
'builtins'
>>>

@Tinche
Copy link
Contributor Author

Tinche commented May 19, 2021

I tried running the plugin when attrs itself was not installed:

t.py:1: error: Library stubs not installed for "attr" (or incompatible with Python 3.9)
t.py:1: note: Hint: "python3 -m pip install types-attrs"
t.py:1: note: (or run "mypy --install-types" to install all missing stub packages)
t.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
t.py:28: note: Revealed type is "<nothing>"
Found 1 error in 1 file (checked 1 source file)

It doesn't crash Mypy and basically tells you what to do, so I think this case is fine.

Next, I tried deleting the stubs; attr.Attribute ceases to be generic but again, no crashes. (lookup_fully_qualified works, but returns the non-stub version.)

I'm going to add a check anyway, to future-proof just in case.

@Tinche
Copy link
Contributor Author

Tinche commented May 19, 2021

@euresti I have fixed almost all of the tests by changing the fixtures a little (they need dict now, for example).

I couldn't fix the incremental tests though. As part of creating the __attrs_attrs__ attribute, I create a namedtuple subclass in the plugin (just like attrs does at runtime). The incremental tests cannot find this class, for some reason. Now I need to figure out why. Does it have to do with de/serialization?

@Tinche
Copy link
Contributor Author

Tinche commented Dec 16, 2021

Fixed by #8578

@Tinche Tinche closed this Dec 16, 2021
@Tinche Tinche deleted the tin/attrs-fields branch December 16, 2021 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants