JelleZijlstra / typeshed_client

Retrieve information from typeshed and other typing stubs
MIT License
20 stars 2 forks source link

Is it possible to use this to access typeshed annotations for builtin functions? #56

Open EdwardChamberlain opened 2 years ago

EdwardChamberlain commented 2 years ago

This project could benefit from some example code.

Is it possible to use this to access type annotation for built in functions such as time.sleep?

I would like to access the annotations def sleep(secs: float) -> None: ... within my python script so that I can work with them such that it can be analysed at runtime much in the way that you can use .__annotations__ on other functions.

JelleZijlstra commented 2 years ago

Yes, it can be, and you're right that the docs could be better! I'll work on that.

There isn't a builtin sleep function; assuming you mean time.sleep, you could do resolver = typeshed_client.Resolver() and then resolver.get_fully_qualified_name("time.sleep").

EdwardChamberlain commented 2 years ago

You're absolutely right - I mean the time.sleep function.

I delved a bit further into the ast library and managed to put together a basic example to get a function name, args, types, return. It is essentially exactly what you have written above, but with a bit of the structure of the ast shown. I personally find this type of example much easier to follow.

import typeshed_client

x = "time.sleep"

resolver = typeshed_client.Resolver()
fully_qualified_name = resolver.get_fully_qualified_name(x)
func_ast = fully_qualified_name.ast

print(func_ast.name)
for arg in func_ast.args.args:
    print(f'   {arg.arg}: {arg.annotation.id}')
print("   Return: ", func_ast.returns.value)

The ast lib adds a massive amount of boilerplate. For example to print just the type of one argument is:

print(fully_qualified_name.ast.args.args[0].annotation.id)

And that boilerplate is not intuitively named or structured.... to get the annotation type from an arg is .id but for the return type it's .value. To get the args you need to call .args but then that returns an args object, from there you can get a list of the arg objects with .args again... x.args.args

Based on that it may be a nice addition to this lib to add a helper function so that annotations can be accessed in the same way as other functions. Perhaps adding a property of .annotations to the fully qualified name that returns a dict in the same structure you see using .__annotations__ on non-type shed functions would be a handy shorthand?