On 2/27/21 2:57 PM, Paul Bryan wrote:
Is there a useful reason to allow Required[] in other positions that I'm not thinking of?
My thought is admittedly pretty weak at this point: dynamically defining a as required prior to its use in TypeDict. Is the following valid?
TD = TypedDict("TD", {"a": Required[int] if some_condition else NotRequired[int], "b": str}, total=False)
It is not valid. Type checkers need to be able to determine the types of keys statically and those expressions are too complex.
Q2. Can the PEP explicitly address how Required[...] and NotRequired[...] will manifest in TypedDict state? Namely, its effect on __required_keys__ and __optional_keys__?
Sure.
Required[] applied to a key means it will definitely appear in __required_keys__ at runtime. Similarly NotRequired[] applied to a key means it will definitely appear in __optional_keys__.
Neither __required_keys__ nor __optional_keys__ are mentioned in PEP 589 (TypedDict) [1] or the "typing" module documentation [2] but I think an earlier post to the list suggested that was an oversight and that these runtime-available keys should be documented (presumably in one of those locations) as well.
[1]: https://www.python.org/dev/peps/pep-0589/ <https://www.python.org/dev/peps/pep-0589/> [2]: https://docs.python.org/3/library/typing.html#typing.TypedDict <https://docs.python.org/3/library/typing.html#typing.TypedDict>
I'll create a PR to update [2].
Cool. I'll probably see it this Thursday or this weekend. Pretty overloaded this week.
I wonder if it would be useful to ban confusing combinations of both Required[] and NotRequired[] at the same time, like:
class Movie(TypedDict): year: Required[NotRequired[...]] # um; error?; does Required[] win?
The options that make sense to me:
1. Combining them is an error. 2. Outer always wins.
I lean toward option 1, as I can't think of a good reason they might wrap each other.
Agreed.
Q3. How will get_type_hints(...), get_options(...) and get_args(...) behave with TypedDicts (and their __annotations__ values) where keys are explicitly marked Required[...] or NotRequired[...]?
Good question. Presumably they would became similarly to how they treat other type qualifiers like Final[] and Annotated[] (whatever that behavior is), but I'll do some further research/thinking here.
Suggestions:
TD = TypedDict("TD", {"a": Required[int]}, total=False)
get_type_hints(TD)
{'a': typing.Required[int]}
a = get_type_hints(TD)["a"]
get_origin(a)
typing.Required
get_args(a)
(<class 'int'>,)
Yes, that's the *preserve* approach. I could also see an argument that the hints be *erased*, leaving only the requireness information in the `__required_keys__` and `__optional_keys__` collections. Erased types are likely to be easier for user code to work with at runtime. Again, I'll do some more research RE the behavior of similar Final[] and Annotated[] here when I have some bandwidth. -- David Foster | Seattle, WA, USA Contributor to TypedDict support for mypy