-
Notifications
You must be signed in to change notification settings - Fork 170
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
Python 3.9 AttributeError: __args__ #231
Comments
Version 21.5.0 for MonkeyType |
@carljm This is becoming quite an issue for me as it chooses seemingly random files that I am completely unable to stub with monkeytype. Can you offer any advice? |
this seems quite similar to #122. The main difference is the error is deterministic. |
@GameDungeon There is some kind of type present in your annotations that passes the It would be useful to know what type this is; probably once we know it won't be hard to add support for it. If you are able to temporarily add a |
The error comes up when trying to stub camera.py and mobject.py both are untyped as of now. I'll try the except. |
Ok, I think I found it: |
Also if you see this later, quick question. Does MonkeyType allow for custom generics? |
@GameDungeon The If you want me to repro I'll need more detailed instructions; in particular the key missing step is how you are collecting the traces in the first place. MonkeyType doesn't record generic arg types for custom generics; it has no way to know how to introspect an instance of an arbitrary generic type to find the right types for its type args. |
I'm currently calling monkeytype run on this. from collections import Counter
import importlib
import warnings
from manim.utils.color import Colors
import manim
import os
import sys
import inspect
from manim import *
import re
from typing import List, Callable, Dict, Any, Tuple
config.verbosity = "ERROR"
warnings.filterwarnings("ignore")
errors = 0
all_errors: List[Any] = list()
class arg_generator:
def __init__(self) -> None:
func = lambda *args : args[0]
self.end_args: Dict[str, Any] = dict()
self.checks = {
"mobject": Mobject,
"vmobject": VMobject(),
"t": 0,
"animation": Animation(Mobject()),
"text": "Hello",
"angle": 100,
"function": func,
"func": func,
"name": "Fred",
"vmob": VMobject(),
"color": Colors.black.value,
"matrix": Matrix([[2, 2], [2, 2]]),
"n": 0,
"obj": "obj",
"line1": Line(),
"line2": Line(),
"method": Line().add_tip(),
"points": [(1, 1), (2, 2)],
"camera": Camera(),
"a": 1.0,
"b": 1.0,
"start": (1, 1),
"end": (2, 2),
}
def arg_check(self, sig: List[Any], check: str, final: Any) -> None:
if check in sig:
self.end_args[check] = final
def generate_args(self, sig: List[Any]) -> Dict[str, Any]:
self.end_args = dict()
for key in self.checks.keys():
self.arg_check(sig, key, self.checks[key])
return self.end_args
def run_function(obj, end_args: Dict[str, Any], kill: bool = False) -> bool:
global errors
global all_errors
try:
obj(**end_args)
except TypeError as e:
sig = inspect.signature(obj)
need_sig = list({k: v.default for k, v in sig.parameters.items()}.keys())
arg_gen = arg_generator()
x = tuple(re.findall(r"\'([^\']*)\'", str(e)))
if x == ():
print(f"{obj.__name__}, Error: {e}")
return False
if kill:
# print(f"{obj.__name__}, Failed: {x}")
all_errors.append(x)
errors += 1
return False
if need_sig == [
"mobject",
"args",
"use_override",
"kwargs",
]: # Needed due to strange bug. Might effect animation typings.
return False
run_function(obj, arg_gen.generate_args(need_sig), True)
except Exception as e:
# print(f"Error: {e} from {obj.__name__}")
return False
return True
def all_tests(start: str = "tests") -> None:
sys.path.append(start)
for file in os.listdir(start):
if file.startswith("test_"):
try:
importlib.import_module(file[:-3])
except ImportError as e:
struct = f"{start}//{file}"
if os.path.isdir(struct):
all_tests(struct)
except Exception as e:
print("Can't run this test: " + file)
print(e)
def all_classes() -> None:
for name, obj in inspect.getmembers(manim):
if callable(obj):
run_function(obj, dict())
all_tests()
all_classes() The above is designed to give monkeytype as much info as possible for its typings as everything else barely touches anything. (are tests are at 50% coverage) Download the manim git, pop that file at the git's root and the monkey type run it. After that try to call monkeytype stub on camera. |
I think this error might be the missing piece in the puzzle:
I get a ton of those when running MonkeyType run on the above. Need anything else @carljm? |
I have to believe the above error is directly causing:
Still see no clear connection between that and the original error. |
I'm having trouble even getting types collected. After a bunch of work to install all the manim dependencies, I'm now getting this error:
|
That is strange. It seems you got the github version too. I'll see if I can replicate the error. |
FWIW I'm on OS X and installed latex via |
Is running every function with the right parameters a healthy way to use monkeytype? |
It's not an approach I've seen before. It should work, but the types you get out will be only as good as what you put in. Typically you'd run MonkeyType with a more realistic workload (test suite and/or some kind of "production" workload), and for stuff you can't get covered that way, you'd add types a different way. E.g. if you can reliably predict the types of args based on their name, then you could write a LibCST transform (even based on MonkeyType's) to just add those types to args with those names if not already annotated, without going through MonkeyType for it. |
"but the types you get out will be only as good as what you put in" If I put in a bad type and it errors will monkey type still log it? |
Yeah if a function raises an exception, MonkeyType will still log the argument types, just no return type for that particular execution. |
While I believe that any function that raises an exception shouldn't be logged, I'll keep that in mind. I went this route as the test suite for manim is lacking. |
There are plenty of cases where functions raise exceptions that are not related to a bad type of argument being passed in. There could even be cases where a certain type of argument always results in an exception in practice, but this is part of the contract of the function and that type should still be annotated as valid for that argument! MonkeyType's job is to record what happens at runtime and tell you about the types it saw, not to make judgements (which will inevitably not be right for all cases) about which executions were valid or invalid. |
Ok I see your point, I'll just have to be careful then. |
@carljm Soon I'm just going to move on from this issue, as it has taken a lot of time, but let me know if you need my help. |
Now I'm getting this lovely error: AttributeError: '_SpecialForm' object has no attribute '__name__'. This has been a fun time. |
I reproduced the # monkeymodule/file1.py
def to_str(func):
def wrapper(*args):
newArgs = tuple(map(str, args))
return func(*newArgs)
return wrapper
@to_str
def add(a, b):
return a + b # monkeymodule/file2.py
from monkeymodule.file1 import add
add(1,2) Terminal script: monkeytype.exe run .\monkeymodule\file2.py
monkeytype.exe stub monkeymodule.file1 Trace:
|
ok, it seems to break on decorators? still wondering on the "AttributeError: '_SpecialForm' object has no attribute 'name'" |
Thanks @ntjess for the simple repro! It looks like in Python 3.9 unbound |
Sorry for the unpleasant experience. MonkeyType uses internal API of the If you want to file a separate issue with a full traceback for the |
Fixed with merge of #237. |
I honestly cannot parse this error message.
I'm trying to run monkeytype on manim's mobject.py
The text was updated successfully, but these errors were encountered: