Skip to content

add stub for contextvars.pyi #1968

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

Merged
merged 2 commits into from
Mar 21, 2018
Merged

Conversation

JelleZijlstra
Copy link
Member

@gvanrossum
Copy link
Member

@1st1 Can you have a quick look here?

_T = TypeVar('_T')

class ContextVar(Generic[_T]):
def __init__(self, name: str, *, default: _T) -> None: ...
Copy link
Member

@1st1 1st1 Mar 21, 2018

Choose a reason for hiding this comment

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

default is not a required parameter. It's not typing.Optional either, as it is either of type _T or not passed at all (None is not a valid value).

A couple of examples:

# valid:
int_var: ContextVar[int] = ContextVar(default=1)
int_var: ContextVar[int] = ContextVar()

# invalid:
int_var: ContextVar[int] = ContextVar(default=None)

and

# valid:
int_var: ContextVar[Optional[int]] = ContextVar(default=1)
int_var: ContextVar[Optional[int]] = ContextVar(default=None)
int_var: ContextVar[Optional[int]] = ContextVar()

Here's a pure Python implementaion of PEP 567 / ContextVar: https://github.com/MagicStack/contextvars/blob/master/contextvars/__init__.py#L111

I'm not sure how to express this in terms of typing. Maybe

class ContextVar(Generic[_T]):
    def __init__(self, name: str, *, default: _T=...) -> None: ...

?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can write *, default: _T = .... Sorry for missing this.

Copy link
Member

Choose a reason for hiding this comment

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

Jelle: If = ... doesn't work, you can use an overload (once without, once with default).

Copy link
Member

Choose a reason for hiding this comment

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

NP!

@1st1
Copy link
Member

1st1 commented Mar 21, 2018

LGTM.

I wish there was a way to express Token.old_value more clearly, but since Token.MISSING is not a type we can't use a union type there, right?

@JelleZijlstra
Copy link
Member Author

Yes, I couldn't think of a clean way. An approach I thought of was to define a fake type like class _Missing: ... and then define MISSING as being of type _Missing, and have old_value return Union[_T, _Missing]. However, I assume the idiomatic way of using old_value would be something like:

val = token.old_value()
if val is token.MISSING:
     # do something
else:
     # do something else

and with the proposed type annotations I don't think mypy would be able to infer that val is not MISSING in the else branch.

So unless Guido can think of something better, we should probably go with Any.

@1st1
Copy link
Member

1st1 commented Mar 21, 2018

However, I assume the idiomatic way of using old_value would be something like:

FWIW I think that the primary use-case for Token.old_value will be debugging.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

Go ahead and merge!

@JelleZijlstra JelleZijlstra merged commit bfe0b06 into python:master Mar 21, 2018
@JelleZijlstra JelleZijlstra deleted the contextvars branch March 21, 2018 22:16
yedpodtrzitko pushed a commit to yedpodtrzitko/typeshed that referenced this pull request Jan 23, 2019
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.

3 participants