Skip to content

Commit 676c3b4

Browse files
msullivanhugovk
andauthored
Apply suggestions from code review
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
1 parent 6f73b61 commit 676c3b4

File tree

2 files changed

+27
-40
lines changed

2 files changed

+27
-40
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ peps/pep-0821.rst @JelleZijlstra
700700
peps/pep-0822.rst @methane
701701
peps/pep-0825.rst @warsaw @dstufft
702702
peps/pep-0826.rst @savannahostrowski
703-
peps/pep-0827.rst @msullivan @dnwpark @1st1
703+
peps/pep-0827.rst @1st1
704704
# ...
705705
peps/pep-2026.rst @hugovk
706706
# ...

peps/pep-0827.rst

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ this gap by adding type manipulation facilities that
4646
are better able to keep up with dynamic Python code.
4747

4848
There is demand for this. In the analysis of the
49-
responses to Meta's 2025 Typed Python Survey [#survey]_, the first
49+
responses to Meta's `2025 Typed Python Survey <#survey_>`__, the first
5050
entry on the list of "Most Requested Features" was:
5151

5252
**Missing Features From TypeScript and Other Languages**: Many respondents
@@ -150,13 +150,13 @@ Even further, an IDE could offer code completion for
150150
all arguments of the ``db.select()`` call (matching the
151151
actual database column names), recursively.
152152

153-
(Example code for implementing this :ref:`below <qb-impl>`.)
153+
(Example code for implementing this :ref:`below <pep827-qb-impl>`.)
154154

155155

156156
Automatically deriving FastAPI CRUD models
157157
------------------------------------------
158158

159-
In the `FastAPI tutorial <#fastapi-tutorial_>`_, they show how to
159+
The `FastAPI tutorial <#fastapi-tutorial_>`_, shows how to
160160
build CRUD endpoints for a simple ``Hero`` type. At its heart is a
161161
series of class definitions used both to define the database interface
162162
and to perform validation and filtering of the data in the endpoint::
@@ -261,7 +261,7 @@ based on the attributes of an object. The most well-known example of
261261
this is generating ``__init__`` methods for dataclasses,
262262
which we present a simplified example of.
263263

264-
This kind of pattern is widespread enough that :pep:`PEP 681 <681>`
264+
This kind of pattern is widespread enough that :pep:`681`
265265
was created to represent a lowest-common denominator subset of what
266266
existing libraries do.
267267

@@ -279,7 +279,7 @@ typing. The situation was substantially improved by the introduction of
279279
``ParamSpec`` in :pep:`612`, but a number of patterns remain
280280
unsupported:
281281

282-
* Adding/removing/modifying a keyword parameter
282+
* Adding/removing/modifying a keyword parameter.
283283
* Adding/removing/modifying a variable number of parameters. (Though
284284
``TypeVarTuple`` is close to being able to support adding and
285285
removing, if multiple unpackings were to be allowed, and Pyre
@@ -312,7 +312,7 @@ Here ``BaseTypedDict`` is defined as::
312312
class BaseTypedDict(typing.TypedDict):
313313
pass
314314

315-
But any TypedDict would be allowed there.
315+
But any :class:`~typing.TypedDict` would be allowed there.
316316

317317
Then, if we had a call like::
318318

@@ -325,9 +325,9 @@ the type inferred for ``K`` would be something like::
325325
TypedDict({'x': int, 'y': list[str]})
326326

327327
This is basically a combination of
328-
"PEP 692Using TypedDict for more precise ``**kwargs`` typing"
328+
:pep:`692` "Using TypedDict for more precise ``**kwargs`` typing"
329329
and the behavior of ``Unpack`` for ``*args``
330-
from "PEP 646Variadic Generics".
330+
from :pep:`646` "Variadic Generics".
331331

332332
When inferring types here, the type checker should **infer literal
333333
types when possible**. This means inferring literal types for
@@ -340,7 +340,6 @@ have its type inferred as ``Never``, to indicate that it was not
340340
provided. (This can only be done for read-only items, since non
341341
read-only items are invariant.)
342342

343-
344343
This is potentially moderately useful on its own but is being done to
345344
support processing ``**kwargs`` with type level computation.
346345

@@ -563,8 +562,8 @@ Boolean operators
563562
* ``IsAssignable[T, S]``: Returns a boolean literal type indicating whether
564563
``T`` is assignable to ``S``.
565564

566-
That is, it is a "consistent subtype". This is subtyping extended
567-
to gradual types.
565+
That is, it is a "consistent subtype". This is subtyping extended
566+
to gradual types.
568567

569568
* ``IsEquivalent[T, S]``:
570569
Equivalent to ``IsAssignable[T, S] and IsAssignable[S, T]``.
@@ -595,24 +594,19 @@ Basic operators
595594
will be packed in a tuple, and a ``...`` will become
596595
``SpecialFormEllipsis``.
597596

598-
599597
* ``GetArgs[T, Base]``: returns a tuple containing all of the type
600598
arguments of ``T`` when interpreted as ``Base``, or ``Never`` if it
601599
cannot be.
602600

603-
604601
* ``GetMemberType[T, S: Literal[str]]``: Extract the type of the
605602
member named ``S`` from the class ``T``.
606603

607-
608604
* ``Length[T: tuple]`` - Gets the length of a tuple as an int literal
609605
(or ``Literal[None]`` if it is unbounded)
610606

611-
612607
* ``Slice[S: tuple, Start: Literal[int | None], End: Literal[int | None]]``:
613608
Slices a tuple type.
614609

615-
616610
* ``GetSpecialAttr[T, Attr: Literal[str]]``: Extracts the value
617611
of the special attribute named ``Attr`` from the class ``T``. Valid
618612
attributes are ``__name__``, ``__module__``, and ``__qualname__``.
@@ -670,7 +664,7 @@ Methods are returned as callables using the new ``Param`` based
670664
extended callables, and carrying the ``ClassVar``
671665
qualifier. ``staticmethod`` and ``classmethod`` will return
672666
``staticmethod`` and ``classmethod`` types, which are subscriptable as
673-
of 3.14.
667+
of Python 3.14.
674668

675669
All of the operators in this section are :ref:`lifted over union types
676670
<lifting>`.
@@ -694,7 +688,7 @@ InitField
694688
'''''''''
695689

696690
We want to be able to support transforming types based on
697-
dataclasses/attrs/pydantic style field descriptors. In order to do
691+
dataclasses/attrs/Pydantic-style field descriptors. In order to do
698692
that, we need to be able to consume operations like calls to ``Field``.
699693

700694
Our strategy for this is to introduce a new type
@@ -911,7 +905,7 @@ as a literal type--all of these mechanisms lean very heavily on literal types.
911905
]:
912906
raise NotImplementedError
913907

914-
ConvertField is our first type helper, and it is a conditional type
908+
``ConvertField`` is our first type helper, and it is a conditional type
915909
alias, which decides between two types based on a (limited)
916910
subtype-ish check.
917911

@@ -972,9 +966,7 @@ Automatically deriving FastAPI CRUD models
972966
------------------------------------------
973967

974968
We have a more `fully-worked example <#fastapi-test_>`_ in our test
975-
suite, but here is a possible implementation of just ``Public``
976-
977-
::
969+
suite, but here is a possible implementation of just ``Public``::
978970

979971
# Extract the default type from an Init field.
980972
# If it is a Field, then we try pulling out the "default" field,
@@ -1096,7 +1088,7 @@ arrays, such as::
10961088
The example in that PEP shows how ``TypeVarTuple`` can be used to
10971089
make sure that both sides of an arithmetic operation have matching
10981090
shapes. Most multi-dimensional array libraries, however, also support
1099-
broadcasting [#broadcasting]_, which allows the mixing of differently
1091+
`broadcasting <#broadcasting_>`__, which allows the mixing of differently
11001092
shaped data. With this PEP, we can define a ``Broadcast[A, B]`` type
11011093
alias, and then use it as a return type::
11021094

@@ -1207,13 +1199,13 @@ which wouldn't be any simpler.)
12071199

12081200
We are proposing a fully new extended callable syntax because:
12091201
1. The ``mypy_extensions`` functions are full no-ops, and we need
1210-
real runtime objects
1202+
real runtime objects.
12111203
2. They use parentheses and not brackets, which really goes against
12121204
the philosophy here.
12131205
3. We can make an API that more nicely matches what we are going to
12141206
do for inspecting members (we could introduce extended callables that
12151207
closely mimic the ``mypy_extensions`` version though, if something new
1216-
is a non-starter)
1208+
is a non-starter).
12171209

12181210
.. _generic-callable-rationale:
12191211

@@ -1250,7 +1242,6 @@ functions with explicit generic annotations. For old-style generics,
12501242
we'll probably have to try to evaluate it and then raise an error when
12511243
we encounter a variable.)
12521244

1253-
12541245
The reason we suggest restricting the use of ``GenericCallable`` to
12551246
the type argument of ``Member`` is because impredicative
12561247
polymorphism (where you can instantiate type variables with other
@@ -1259,7 +1250,6 @@ positions deep inside function types) are cans of worms when combined
12591250
with type inference [#undecidable]_. While it would be nice to support,
12601251
we don't want to open that can of worms now.
12611252

1262-
12631253
The unbound type variable tuple is so that bounds and defaults and
12641254
``TypeVarTuple``-ness can be specified, though maybe we want to come
12651255
up with a new approach.
@@ -1329,10 +1319,10 @@ and APIs they introduce.
13291319
Reference Implementation
13301320
========================
13311321

1332-
There is a demo of a runtime evaluator [#runtime]_, which is
1322+
There is a `demo of a runtime evaluator <#runtime_>`__, which is
13331323
also where this PEP draft currently lives.
13341324

1335-
There is an in-progress proof-of-concept implementation in mypy [#ref-impl]_.
1325+
There is an in-progress `proof-of-concept implementation <#ref-impl_>`__ in mypy.
13361326

13371327
It can type check the ORM, FastAPI-style model derivation, and
13381328
NumPy-style broadcasting examples.
@@ -1529,7 +1519,7 @@ behavior of lifting the conditional over unions.
15291519
Replace ``IsAssignable`` with something weaker than "assignable to" checking
15301520
----------------------------------------------------------------------------
15311521

1532-
Full python typing assignability checking is not fully implementable
1522+
Full Python typing assignability checking is not fully implementable
15331523
at runtime (in particular, even if all the typeshed types for the
15341524
stdlib were made available, checking against protocols will often not
15351525
be possible, because class attributes may be inferred and have no visible
@@ -1636,7 +1626,7 @@ It would require a well-defined and safe-to-run subset of the language
16361626
typecheckers. Subsets like this have been defined in other systems
16371627
(see `Starlark <#starlark_>`_, the configuration language for Bazel),
16381628
but it's still a lot of surface area, and programmers would need to
1639-
keep in mind the boundaries of it.
1629+
keep in mind its boundaries.
16401630

16411631
Additionally there would need to be a clear specification of how types
16421632
are represented in the "mini-plugin" functions, as well as defining
@@ -1674,7 +1664,7 @@ machinery.
16741664
treated as having some type like ``tuple[Member[KeyOf[T], object,
16751665
str, ..., ...], ...]``
16761666
* ``GetMemberType[T, S: KeyOf[T]]`` - but this isn't supported yet.
1677-
TS supports it.
1667+
TypeScript supports it.
16781668
* We would also need to do context sensitive type bound inference
16791669

16801670

@@ -1731,12 +1721,9 @@ for all unicode!).
17311721
It would definitely be possible to take just slicing and
17321722
concatenation, also.
17331723

1734-
17351724
* ``Slice[S: Literal[str], Start: Literal[int | None], End: Literal[int | None]]``:
17361725
Also support slicing string types. (Currently tuples are supported.)
1737-
17381726
* ``Concat[S1: Literal[str], S2: Literal[str]]``: concatenate two strings
1739-
17401727
* ``Uppercase[S: Literal[str]]``: uppercase a string literal
17411728
* ``Lowercase[S: Literal[str]]``: lowercase a string literal
17421729
* ``Capitalize[S: Literal[str]]``: capitalize a string literal
@@ -1824,20 +1811,20 @@ substantial influence on this proposal!
18241811
Footnotes
18251812
=========
18261813

1814+
.. _#broadcasting: https://numpy.org/doc/stable/user/basics.broadcasting.html
18271815
.. _#fastapi: https://fastapi.tiangolo.com/
18281816
.. _#pydantic: https://docs.pydantic.dev/latest/
18291817
.. _#fastapi-tutorial: https://fastapi.tiangolo.com/tutorial/sql-databases/#heroupdate-the-data-model-to-update-a-hero
18301818
.. _#fastapi-test: https://github.com/vercel/python-typemap/blob/main/tests/test_fastapilike_2.py
18311819
.. _#prisma: https://www.prisma.io/
18321820
.. _#prisma-example: https://github.com/prisma/prisma-examples/tree/latest/orm/express
18331821
.. _#qb-test: https://github.com/vercel/python-typemap/blob/main/tests/test_qblike_2.py
1822+
.. _#ref-impl: https://github.com/msullivan/mypy/tree/typemap
1823+
.. _#runtime: https://github.com/vercel/python-typemap
18341824
.. _#starlark: https://starlark-lang.org/
1825+
.. _#survey: https://engineering.fb.com/2025/12/22/developer-tools/python-typing-survey-2025-code-quality-flexibility-typing-adoption/
18351826
.. _#ast_format: https://imogenbits-peps.readthedocs.io/en/ast_format/pep-9999/
18361827

1837-
.. [#broadcasting] http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
1838-
.. [#ref-impl] https://github.com/msullivan/mypy/tree/typemap
1839-
.. [#runtime] https://github.com/vercel/python-typemap/
1840-
.. [#survey] https://engineering.fb.com/2025/12/22/developer-tools/python-typing-survey-2025-code-quality-flexibility-typing-adoption/
18411828
.. [#undecidable]
18421829
18431830
* "Partial polymorphic type inference is undecidable" by Hans Boehm: https://dl.acm.org/doi/10.1109/SFCS.1985.44

0 commit comments

Comments
 (0)