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

Support type annotations for @settings #377

Open
gschaffner opened this issue Aug 10, 2020 · 2 comments
Open

Support type annotations for @settings #377

gschaffner opened this issue Aug 10, 2020 · 2 comments

Comments

@gschaffner
Copy link
Member

@fanmingyu212 brought this up and it seems like a really nice idea. It also looks like it was briefly mentioned in #162 (comment).

One thing to consider is whether users are using static type checkers. If they are, hints should be of the format

from labrad.types import TInt, TStr
from typing import Generator
from twisted.internet.defer import returnValue

@setting(1)
async def foo(self, c, a: TInt) -> TStr:
    await something(a)
    b = "foo"
    return b

@setting(1)
def foo(self, c, a: TInt) -> Generator[Any, Any, None]:
    yield something(a)
    b = yield "foo"  # not a Deferred, but twisted is OK with this
    returnValue(b)  # technically, this generator returns None

@setting(1)
def foo(self, c, a: TInt) -> Generator[Any, Any, TStr]:
    yield something(a)
    b = yield "foo"  # not a Deferred, but twisted is OK with this
    return b

Technically speaking, the return type hint for twisted generators should be Generator[Any, Any, ???] in order for static type checkers to not become angry. I doubt many users are using static type checkers though, so we could probably just let users use coroutine-style hints and tell them to have their type checker ignore @setting functions. It's unlikely that users are type checking @setting functions anyway since twisted doesn't provide type annotations for inlineCallbacks or most of their library.

@maffoo
Copy link
Contributor

maffoo commented Aug 11, 2020

This is one of many reasons why we want async/await support, because the type annotations actually behave nicely :-) Also, I think if we did this we'd want to support standard python types like str, List[str], etc in the annotations, because then the code is compatible with static type checking.

@setting(1)
async def foo(self, c, a: int) -> str:
    b = await something(a)
    return f'b: {b}'

Putting your own object into the annotations is going against the grain, though 3.9 adds typing.Annotated which would allow including both; for labrad this could help disambiguate between, for example, signed and unsigned ints:

@setting(1)
async def foo(self, c, unsigned: Annotated[int, 'w'], signed: Annotated[int, 'i']) -> str:
    return f'{unsigned=}, {signed=}'

@gschaffner
Copy link
Member Author

That makes sense. typing.Annotated looks perfect for this too, but I think it would be extreme to require 3.9+ since nobody is using it with pylabrad yet. A quick search doesn't find a package similar to https://python-future.org but for bringing 3.x stdlib changes to lower 3.x versions.

For int (and similar cases), should we choose a default interpretation of the hint or just require users to clarify in @setting(...)? I think it would be handy to assume that arg: int means signed int, but there may be a downside to this that I'm not seeing.

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

No branches or pull requests

2 participants