Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc6f518b

Browse files
committed
Keep mypy from thinking Git has arbitrary class attributes
The existence of __getattr__ or __getattribute__ on a class causesstatic type checkers like mypy to stop inferring that reads ofunrecognized instance attributes are static type errors. When theclass is a metaclass, this causes static type checkers to stopinferring that reads of unrecognized class attributes, on classesthat use (i.e., that have as their type) the metaclass, are statictype errors.The Git class itself defines __getattr__ and __getattribute__, butGit objects' instance attributes really are dynamically synthesized(in __getattr__). However, class attributes of Git are not dynamic,even though _GitMeta defines __getattribute__. Therefore, somethingspecial is needed so mypy infers nothing about Git class attributesfrom the existence of _GitMeta.__getattribute__.This takes the same approach as taken to the analogous problem with__getattr__ at module level, defining __getattribute__ with adifferent name first and then assigning that to __getattribute__under an `if not TYPE_CHECKING:`. (Allowing static type checkers tosee the original definition allows them to find some kinds of typeerrors in the body of the method, which is why the method isn'tjust defined in the `if not TYPE_CHECKING`.)Although it may not currently be necessary to hide __setattr__ too,the same is done with it in _GitMeta as well. The reason is thatthe intent may otherwise be subtly amgiguous to human readers andmaybe future tools: when __setattr__ exists, the effect of settinga class attribute that did not previously exist is in principleunclear, and might not make the attribute readble. (I am unsure ifthis is the right choice; either approach seems reasonable.)
1 parent04eb09c commitc6f518b

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

‎git/cmd.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,16 +335,23 @@ class _GitMeta(type):
335335
This helps issue :class:`DeprecationWarning` if :attr:`Git.USE_SHELL` is used.
336336
"""
337337

338-
def__getattribute__(cls,name:str)->Any:
338+
def__getattribute(cls,name:str)->Any:
339339
ifname=="USE_SHELL":
340340
_warn_use_shell(False)
341341
returnsuper().__getattribute__(name)
342342

343-
def__setattr__(cls,name:str,value:Any)->Any:
343+
def__setattr(cls,name:str,value:Any)->Any:
344344
ifname=="USE_SHELL":
345345
_warn_use_shell(value)
346346
super().__setattr__(name,value)
347347

348+
ifnotTYPE_CHECKING:
349+
# To preserve static checking for undefined/misspelled attributes while letting
350+
# the methods' bodies be type-checked, these are defined as non-special methods,
351+
# then bound to special names out of view of static type checkers.
352+
__getattribute__=__getattribute
353+
__setattr__=__setattr
354+
348355

349356
classGit(metaclass=_GitMeta):
350357
"""The Git class manages communication with the Git binary.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp