Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions pep-0655.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ different value for ``total``:
Having to declare two different TypedDict types for this purpose is
cumbersome.

This PEP introduces two new type qualifiers, ``typing.Required`` and
``typing.NotRequired``, which allow defining a *single* TypedDict with
a mix of both required and potentially-missing keys:

::

class Movie(TypedDict):
title: str
year: NotRequired[int]


Rationale
=========
Expand Down Expand Up @@ -138,6 +148,35 @@ for TypedDict also supports
Movie = TypedDict('Movie', {'name': str, 'year': NotRequired[int]})


Interaction with ``total=False``
--------------------------------

Any :pep:`589`-style TypedDict declared with ``total=False`` is equivalent
to a TypedDict with an implicit ``total=True`` definition with all of its
keys marked as ``NotRequired[]``.

Therefore:

::
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
::
.. code-block: python

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

According to Sphinx documentation, .. code-block:: python is equivalent to just :: in regular RST documents. And indeed using the former form appears to have no effect.

Strangely, neither form actually syntax-highlights Python code in color, at least in PEPs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Coloured syntax highlighting is planned via PEP 676, you can see a preview:

So a TypeScript code block would be useful for that particular snippet.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seconding Hugo -- the default for literal blocks is Python, but explicitness is always better, and it allows highlighting different languages, such as the TypeScript code in this PEP.

A

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seconding Hugo and Adam as well. Furthermore, as that page also mentions, that default is fully configurable on a per-project and per-file basis, and we have discussed doing so in the past.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll make a separate PR that marks the language for non-Python blocks

Presumably the PEP repo will be configured to use Python as the default syntax-highlighting language, so I won't bother to explicitly set the default language to Python in this specific PEP.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Its still a good idea to explicitly specify the language in new PEPs, as it is more clear and consistent and we've discussed using a different default (though I think our current thinking, at least between @AA-Turner and myself, is to stick with python and modify any others accordingly), but it isn't critical.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Explicit isn't always better than implicit :)

Because virtually all code is Python, and there are a lot of Python code blocks, I think we should allow the default :: for Python (and specify the language for other code blocks).

RST isn't easy. Just yesterday I read of someone ditching it for MyST: https://twitter.com/hynek/status/1493509644228173830

We should make writing documents fluent for PEP authors and not require them to stop and look up the syntax (at least I can't always remember the syntax off the top of my head) when the double colon shortcut is so easy.

(If there's a PEP with a lot of C, I think it would be fine switching the default for that PEP to C and then using ::.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think there's harm in encouraging users to be explicit, but now that it seems we've at least informally settled on an approach going forward (use python as the default and update any non-python code blocks at least on active, process, etc PEPs), I agree with the sentiment that its overstepping to require all new PEP authors to explicitly annotate every code block (its what I would do myself in my own PEPs, but I can get a bit too carried away with purity at the expense of practicality sometimes).

Using .. language at the top of the file for PEPs like PEP 7 makes sense as well (particularly on old PEPs, to allow fixing their syntax highlighting in as little as one line rather than modifying every code block, reducing noise and churn), so long as PEP authors and editors are cognizant of it.


class _MovieBase(TypedDict): # implicitly total=True
title: str

class Movie(_MovieBase, total=False):
year: int


is equivalent to:

::

class _MovieBase(TypedDict):
title: str

class Movie(_MovieBase):
year: NotRequired[int]


Interaction with ``Annotated[]``
-----------------------------------

Expand All @@ -162,8 +201,12 @@ annotations, which may always want ``Annotated[]`` as the outermost annotation.
[3]_


Runtime behavior
----------------


Interaction with ``get_type_hints()``
-------------------------------------
'''''''''''''''''''''''''''''''''''''

``typing.get_type_hints(...)`` applied to a TypedDict will by default
strip out any ``Required[]`` or ``NotRequired[]`` type qualifiers,
Expand All @@ -188,7 +231,7 @@ wishes to preserve *all* annotations in the original source:


Interaction with ``get_origin()`` and ``get_args()``
----------------------------------------------------
''''''''''''''''''''''''''''''''''''''''''''''''''''

``typing.get_origin()`` and ``typing.get_args()`` will be updated to
recognize ``Required[]`` and ``NotRequired[]``:
Expand All @@ -203,7 +246,7 @@ recognize ``Required[]`` and ``NotRequired[]``:


Interaction with ``__required_keys__`` and ``__optional_keys__``
----------------------------------------------------------------
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

An item marked with ``Required[]`` will always appear
in the ``__required_keys__`` for its enclosing TypedDict. Similarly an item
Expand All @@ -226,6 +269,7 @@ How to Teach This

To define a TypedDict where most keys are required and some are
potentially-missing, define a single TypedDict as normal
(without the ``total`` keyword)
and mark those few keys that are potentially-missing with ``NotRequired[]``.

To define a TypedDict where most keys are potentially-missing and a few are
Expand Down