Skip to content

Commit 8dcc559

Browse files
authored
Improve TypedDict documentation (#770)
* Improve `TypedDict` documentation * fix docs, add a CI job to check the docs, document how to build the docs
1 parent 224f8d5 commit 8dcc559

6 files changed

Lines changed: 70 additions & 22 deletions

File tree

.github/workflows/ci.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ concurrency:
2121
cancel-in-progress: true
2222

2323
jobs:
24+
docs:
25+
name: Build docs
26+
runs-on: ubuntu-latest
27+
28+
steps:
29+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
30+
with:
31+
persist-credentials: false
32+
33+
- name: Install the latest version of uv
34+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
35+
with:
36+
python-version: "3.14"
37+
38+
- name: Build docs in nitpicky mode
39+
run: uvx --from sphinx sphinx-build -n -W -b html doc doc/_build/html
40+
2441
tests:
2542
name: Run tests
2643

CONTRIBUTING.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ Running these commands in the `src/` directory ensures that the local file
5656
`typing_extensions.py` is used, instead of any other version of the library you
5757
may have installed.
5858

59+
# Building the documentation
60+
61+
To build the documentation in nitpicky mode and treat warnings as errors, run:
62+
63+
```
64+
uvx --from sphinx sphinx-build -n -W -b html doc doc/_build/html
65+
```
66+
67+
The generated HTML documentation is written to `doc/_build/html`.
68+
5969
# Linting
6070

6171
Linting is done via pre-commit. We recommend running pre-commit via a tool such

doc/conf.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
templates_path = ['_templates']
2828
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
2929

30-
# This should usually point to /3, unless there is a necessity to link to
31-
# features in future versions of Python.
32-
intersphinx_mapping = {'py': ('https://docs.python.org/3', None)}
30+
# Use Python 3.15 for new features and Python 3.14 as a fallback for APIs that
31+
# were removed in Python 3.15.
32+
intersphinx_mapping = {
33+
'py': ('https://docs.python.org/3.15', None),
34+
'py314': ('https://docs.python.org/3.14', None),
35+
}
3336

3437
add_module_names = False
3538

doc/index.rst

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -587,14 +587,26 @@ Special typing primitives
587587
``typing_extensions`` backports various bug fixes and improvements
588588
to ``TypedDict``.
589589

590-
:py:class:`TypedDict` does not store runtime information
591-
about which (if any) keys are non-required in Python 3.8, and does not
592-
honor the ``total`` keyword with old-style ``TypedDict()`` in Python
593-
3.9.0 and 3.9.1. :py:class:`typing.TypedDict` also does not support multiple inheritance
594-
with :py:class:`typing.Generic` on Python <3.11, and :py:class:`typing.TypedDict` classes do not
595-
consistently have the ``__orig_bases__`` attribute on Python <3.12. The
596-
``typing_extensions`` backport provides all of these features and bugfixes on
597-
all Python versions.
590+
Features backported by `typing_extensions` include:
591+
592+
* :py:class:`typing.TypedDict` does not store runtime information about which
593+
(if any) keys are non-required in Python 3.8, and does not honor the
594+
*total* keyword with old-style ``TypedDict()`` on Python 3.9.0 and 3.9.1.
595+
* :py:class:`typing.TypedDict` does not support multiple inheritance with
596+
:py:class:`typing.Generic` on Python <3.11
597+
* :py:class:`typing.TypedDict` classes do not consistently have the
598+
:attr:`!__orig_bases__` attribute on Python <3.12.
599+
* :py:class:`typing.TypedDict` does not expose the
600+
:py:attr:`~typing.TypedDict.__readonly_keys__` and
601+
:py:attr:`~typing.TypedDict.__mutable_keys__` attributes on Python <3.13.
602+
* :py:class:`typing.TypedDict` does not support the *extra_items* or *closed*
603+
keyword arguments on Python <3.15, and also does not expose the
604+
:py:attr:`~typing.TypedDict.__extra_items__` and
605+
:py:attr:`~typing.TypedDict.__closed__` attributes on Python <3.15.
606+
607+
``typing_extensions`` also currently includes experimental support for
608+
:pep:`764` (inline ``TypedDict``\ s), which is not yet supported in the
609+
standard library on any Python version.
598610

599611
Historically, ``TypedDict`` has supported an alternative creation syntax
600612
where the fields are supplied as keyword arguments (e.g.,
@@ -603,6 +615,9 @@ Special typing primitives
603615
raises a :py:exc:`DeprecationWarning` when this syntax is used in Python 3.12
604616
or lower and fails with a :py:exc:`TypeError` in Python 3.13 and higher.
605617

618+
Introspection attributes
619+
------------------------
620+
606621
``typing_extensions`` supports the :data:`ReadOnly` qualifier
607622
introduced by :pep:`705`. It is reflected in the following attributes:
608623

@@ -620,7 +635,7 @@ Special typing primitives
620635

621636
.. versionadded:: 4.9.0
622637

623-
The ``closed`` and ``extra_items`` keyword arguments introduced by
638+
The *closed* and *extra_items* keyword arguments introduced by
624639
:pep:`728` and supported in Python 3.15 and newer are supported.
625640

626641
For runtime introspection, two attributes can be looked at:
@@ -640,6 +655,9 @@ Special typing primitives
640655

641656
.. versionadded:: 4.10.0
642657

658+
History
659+
-------
660+
643661
.. versionchanged:: 4.3.0
644662

645663
Added support for generic ``TypedDict``\ s.
@@ -873,9 +891,7 @@ Protocols
873891
Decorators
874892
~~~~~~~~~~
875893

876-
.. decorator:: dataclass_transform(*, eq_default=False, order_default=False,
877-
kw_only_default=False, frozen_default=False,
878-
field_specifiers=(), **kwargs)
894+
.. decorator:: dataclass_transform(*, eq_default=False, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)
879895

880896
See :py:func:`typing.dataclass_transform` and :pep:`681`. In ``typing`` since 3.11.
881897

src/test_typing_extensions.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7175,7 +7175,10 @@ def test_all_names_in___all__(self):
71757175
self.assertLessEqual(exclude, actual_names)
71767176

71777177
def test_typing_extensions_defers_when_possible(self):
7178-
exclude = set()
7178+
# These two are currently always different to `typing.TypedDict`
7179+
# as PEP 764 has not yet been accepted/implemented upstream.
7180+
exclude = {'TypedDict', 'is_typeddict'}
7181+
71797182
if sys.version_info < (3, 10):
71807183
exclude |= {'get_args', 'get_origin'}
71817184
if sys.version_info < (3, 10, 1):
@@ -7202,8 +7205,6 @@ def test_typing_extensions_defers_when_possible(self):
72027205
exclude |= {
72037206
'TypeVarTuple'
72047207
}
7205-
if not typing_extensions._PEP_728_IMPLEMENTED:
7206-
exclude |= {'TypedDict', 'is_typeddict'}
72077208
for item in typing_extensions.__all__:
72087209
if item not in exclude and hasattr(typing, item):
72097210
self.assertIs(

src/typing_extensions.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,10 +1131,10 @@ def __reduce__(self):
11311131

11321132

11331133
# Update this to something like >=3.13.0b1 if and when
1134-
# PEP 728 is implemented in CPython
1135-
_PEP_728_IMPLEMENTED = False
1134+
# PEP 764 is implemented in CPython
1135+
_PEP_764_IMPLEMENTED = False
11361136

1137-
if _PEP_728_IMPLEMENTED:
1137+
if _PEP_764_IMPLEMENTED:
11381138
# The standard library TypedDict in Python 3.9.0/1 does not honour the "total"
11391139
# keyword with old-style TypedDict(). See https://bugs.python.org/issue42059
11401140
# The standard library TypedDict below Python 3.11 does not store runtime
@@ -1144,7 +1144,8 @@ def __reduce__(self):
11441144
# to enable better runtime introspection.
11451145
# On 3.13 we deprecate some odd ways of creating TypedDicts.
11461146
# Also on 3.13, PEP 705 adds the ReadOnly[] qualifier.
1147-
# PEP 728 (still pending) makes more changes.
1147+
# PEP 728 (Python 3.15+) adds the `extra_items` and `closed` keywords.
1148+
# PEP 764 (still pending) allows the `TypedDict` special form to be subscripted.
11481149
TypedDict = typing.TypedDict
11491150
_TypedDictMeta = typing._TypedDictMeta
11501151
is_typeddict = typing.is_typeddict

0 commit comments

Comments
 (0)