Skip to content

Commit e9712cf

Browse files
committed
Wrapping up
1 parent 2857d69 commit e9712cf

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

.github/CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ peps/pep-0759.rst @warsaw
640640
peps/pep-0760.rst @pablogsal @brettcannon
641641
peps/pep-0761.rst @sethmlarson @hugovk
642642
peps/pep-0762.rst @pablogsal @ambv @lysnikolaou @emilyemorehouse
643+
peps/pep-0764.rst @Viicos @erictraut
643644
# ...
644645
peps/pep-0777.rst @warsaw
645646
# ...

peps/pep-0764.rst

+47-14
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ Abstract
1717
:pep:`589` defines a :ref:`class-based <typing:typeddict-class-based-syntax>`
1818
and a :ref:`functional syntax <typing:typeddict-functional-syntax>` to create
1919
typed dictionaries. In both scenarios, it requires defining a class or
20-
assigning to a value. In some situations, this can add unnecessary boilerplate,
21-
especially if the typed dictionary is only used once.
20+
assigning to a value. In some situations, this can add unnecessary
21+
boilerplate, especially if the typed dictionary is only used once.
2222

2323
This PEP proposes the addition of a new inlined syntax, by subscripting the
2424
:class:`~typing.TypedDict` type::
@@ -93,11 +93,15 @@ The :class:`~typing.TypedDict` class is made subscriptable, and accepts a
9393
single type argument which must be a :class:`dict`, following the same
9494
semantics as the :ref:`functional syntax <typing:typeddict-functional-syntax>`
9595
(the dictionary keys are strings representing the field names, and values are
96-
valid :ref:`annotation expressions <typing:annotation-expression>`).
96+
valid :ref:`annotation expressions <typing:annotation-expression>`). Only the
97+
comma-separated list of ``key: value`` pairs within braces constructor
98+
(``{k: <type>}``) is allowed, and should be specified directly as the type
99+
argument (i.e. it is not allowed to use a variable which was previously
100+
assigned a :class:`dict` instance).
97101

98102
Inlined typed dictionaries can be referred to as *anonymous*, meaning they
99-
don't have a name. For this reason, their :attr:`~type.__name__` attribute
100-
will be set to an empty string.
103+
don't have a name (see the `runtime behavior <Runtime behavior>`_
104+
section).
101105

102106
It is possible to define a nested inlined dictionary::
103107

@@ -135,8 +139,6 @@ are bound to some outer scope::
135139

136140
InlinedTD = TypedDict[{'name': T}] # Not OK, `T` refers to a type variable that is not bound to any scope.
137141

138-
**TODO** closed
139-
140142
Typing specification changes
141143
----------------------------
142144

@@ -158,19 +160,20 @@ implemented as a function at runtime. To be made subscriptable, it will be
158160
changed to be a class.
159161

160162
Creating an inlined typed dictionary results in a new class, so ``T1`` and
161-
``T2`` are the same type (apart from the different :attr:`~type.__name__`)::
163+
``T2`` are of the same type::
162164

163165
from typing import TypedDict
164166

165167
T1 = TypedDict('T1', {'a': int})
166168
T2 = TypedDict[{'a': int}]
167169

170+
As inlined typed dictionaries are are meant to be *anonymous*, their
171+
:attr:`~type.__name__` attribute will be set to an empty string.
168172

169173
Backwards Compatibility
170174
=======================
171175

172-
Apart from the :class:`~typing.TypedDict` internal implementation change, this
173-
PEP does not bring any backwards incompatible changes.
176+
This PEP does not bring any backwards incompatible changes.
174177

175178

176179
Security Implications
@@ -236,7 +239,7 @@ While this would avoid having to import :class:`~typing.TypedDict` from
236239
* For type checkers, :class:`dict` is a regular class with two type variables.
237240
Allowing :class:`dict` to be parametrized with a single type argument would
238241
require special casing from type checkers, as there is no way to express
239-
parametrization overloads. On ther other hand, :class:`~typing.TypedDict` is
242+
parametrization overloads. On the other hand, :class:`~typing.TypedDict` is
240243
already a :term:`special form <typing:special form>`.
241244

242245
* If future work extends what inlined typed dictionaries can do, we don't have
@@ -277,6 +280,13 @@ Should we allow the following?::
277280
class SubTD(InlinedTD):
278281
pass
279282

283+
What about defining an inlined typed dictionay extending another typed
284+
dictionary?::
285+
286+
InlinedBase = TypedDict[{'a': int}]
287+
288+
Inlined = TypedDict[InlinedBase, {'b': int}]
289+
280290
Using ``typing.Dict`` with a single argument
281291
--------------------------------------------
282292

@@ -285,16 +295,39 @@ While using :class:`dict` isn't ideal, we could make use of
285295

286296
def get_movie() -> Dict[{'title': str}]: ...
287297

288-
It is less verbose, doesn't have the baggage of :class:`dict`,
289-
and is defined as some kind of special form (an alias to the built-in
290-
``dict``).
298+
It is less verbose, doesn't have the baggage of :class:`dict`, and is
299+
already defined as some kind of special form.
291300

292301
However, it is currently marked as deprecated (although not scheduled for
293302
removal), so it might be confusing to undeprecate it.
294303

295304
This would also set a precedent on typing constructs being parametrizable
296305
with a different number of type arguments.
297306

307+
Should inlined typed dictionaries be proper classes?
308+
----------------------------------------------------
309+
310+
The PEP currently defines inlined typed dictionaries as type objects, to be in
311+
line with the existing syntaxes. To work around the fact that they don't have
312+
a name, their :attr:`~type.__name__` attribute is set to an empty string.
313+
314+
This is somewhat arbitrary, and an alternative name could be used as well
315+
(e.g. ``'<TypedDict>'``).
316+
317+
Alternatively, inlined typed dictionaries could be defined as instances of a
318+
new (internal) typing class, e.g. :class:`!typing._InlinedTypedDict`. While
319+
this solves the naming issue, it requires extra logic in the runtime
320+
implementation to provide the introspection attributes (such as
321+
:attr:`~typing.TypedDict.__total__`), and tools relying on runtime
322+
introspection would have to add proper support for this new type.
323+
324+
Inlined typed dictionaries and extra items
325+
------------------------------------------
326+
327+
:pep:`728` introduces the concept of *closed* type dictionaries. Inlined
328+
typed dictionaries should probably be implicitly *closed*, but it may be
329+
better to wait for :pep:`728` to be accepted first.
330+
298331

299332
Copyright
300333
=========

0 commit comments

Comments
 (0)