@@ -720,7 +720,12 @@ Object creation
720720 specified by ``Member `` arguments
721721
722722* ``NewProtocolWithBases[Bases: tuple[type], *Ms: Member] `` - A variant that
723- allows specifying bases too. TODO: Is this something we actually want?
723+ allows specifying bases too. The idea is that a type would satisfy
724+ this protocol if it extends all of the given bases and has the
725+ specified members. (TODO: Is this something we actually
726+ want? It would would be a potentially powerful feature for dealing
727+ with things like Pydantic models, but protocol-with-bases would be
728+ something of a new concept.)
724729
725730* ``NewTypedDict[*Ps: Member] `` - Creates a new ``TypedDict `` with
726731 items specified by the ``Member `` arguments. TODO: Do we want a way
@@ -933,13 +938,14 @@ Runtime evaluation support
933938--------------------------
934939
935940An important goal is supporting runtime evaluation of these computed
936- types. We do not propose to add an official evaluator to the standard
941+ types. We ** do not ** propose to add an official evaluator to the standard
937942library, but intend to release a third-party evaluator library.
938943
939944While most of the extensions to the type system are "inert" type
940- operator applications, the syntax also includes list iteration and
941- conditionals, which will be automatically evaluated when the
942- ``__annotate__ `` method of a class, alias, or function is called.
945+ operator applications, the syntax also includes list iteration,
946+ conditionals, and attribute access, which will be automatically
947+ evaluated when the ``__annotate__ `` method of a class, alias, or
948+ function is called.
943949
944950In order to allow an evaluator library to trigger type evaluation in
945951those cases, we add a new hook to ``typing ``:
@@ -1236,6 +1242,10 @@ I am proposing a fully new extended callable syntax because:
12361242 closely mimic the ``mypy_extensions `` version though, if something new
12371243 is a non starter)
12381244
1245+ TODO: Currently I made the qualifiers be short strings, for code brevity
1246+ when using them, but an alternate approach would be to mirror
1247+ ``inspect.Signature `` more directly, and have an enum with names like
1248+ ``ParamKind.POSITIONAL_OR_KEYWORD ``.
12391249
12401250.. _generic-callable-rationale :
12411251
@@ -1313,6 +1323,9 @@ like mapped types are unmentioned in current documentation
13131323Reference Implementation
13141324========================
13151325
1326+ There is a demo of a runtime evaluator [#runtime ]_, which is
1327+ also where this PEP draft currently lives.
1328+
13161329There is an in-progress proof-of-concept implementation in mypy [#ref-impl ]_.
13171330
13181331It can type check the ORM, FastAPI-style model derivation, and
@@ -1321,8 +1334,6 @@ NumPy-style broadcasting examples.
13211334It is missing support for callables, ``UpdateClass ``, annotation
13221335processing, and various smaller things.
13231336
1324- There is a demo of a runtime evaluator as well [#runtime ]_.
1325-
13261337Alternate syntax ideas
13271338======================
13281339
@@ -1461,15 +1472,48 @@ Rejected Ideas
14611472Renounce all cares of runtime evaluation
14621473----------------------------------------
14631474
1464- This would have a lot of simplifying features.
1475+ This would give us more flexibility to experiment with syntactic
1476+ forms, and would allow us to dispense with some ugliness such as
1477+ requiring ``typing.Iter `` in unpacked comprehension types and having a
1478+ limited set of ``<type-bool> `` expressions that can appear in
1479+ conditional types.
14651480
1466- TODO: Expand
1481+ For better or worse, though, runtime use of type annotations is
1482+ widespread, and one of our motivating examples (automatically deriving
1483+ FastAPI CRUD models) depends on it.
14671484
14681485Support TypeScript style pattern matching in subtype checking
14691486-------------------------------------------------------------
14701487
1471- This would almost certainly only be possible if we also decide not to
1472- care about runtime evaluation, as above.
1488+ In TypeScript, conditional types are formed like::
1489+
1490+ SomeType extends OtherType ? TrueType : FalseType
1491+
1492+ What's more, the right hand side of the check allows binding type
1493+ variables based on pattern matching, using the ``infer `` keyword, like
1494+ this example that extracts the element type of an array::
1495+
1496+ type ArrayArg<T> = T extends [infer El] ? El : never;
1497+
1498+ This is a very elegant mechanism, especially in the way that it
1499+ eliminates the need for ``typing.GetArg `` and its subtle ``Base ``
1500+ parameter.
1501+
1502+ Unfortunately it seems very difficult to shoehorn into Python's
1503+ existing syntax in any sort of satisfactory way, especially because of
1504+ the subtle binding structure.
1505+
1506+ Perhaps the most plausible variant would be something like::
1507+
1508+ type ArrayArg[T] = El if IsAssignable[T, list[Infer[El]]] else Never
1509+
1510+ Then, if we wanted to evaluate it at runtime, we'd need to do
1511+ something gnarly involving a custom ``globals `` environment that
1512+ catches the unbound ``Infer `` arguments.
1513+
1514+ Additionally, without major syntactic changes (using type operators
1515+ instead of ternary), we wouldn't be able to match TypeScript's
1516+ behavior of lifting the conditional over unions.
14731517
14741518
14751519Replace ``IsAssignable `` with something weaker than "assignable to" checking
@@ -1497,6 +1541,34 @@ that is similar to but not the same as subtyping, and that would need
14971541to either have a long and weird name like ``IsAssignableSimilar `` or a
14981542misleading short one like ``IsAssignable ``.
14991543
1544+
1545+ Don't use dot notation to access ``Member `` components
1546+ ------------------------------------------------------
1547+
1548+ Earlier versions of this PEP draft omitted the ability to write
1549+ ``m.name `` and similar on ``Member `` and ``Param `` components, and
1550+ instead relied on helper operators such as ``typing.GetName `` (that
1551+ could be implemented under the hood using ``typing.GetArg `` or
1552+ ``typing.GetMemberType ``).
1553+
1554+ The potential advantage here is reducing the number of new constructs
1555+ being added to the type language, and avoiding needing to either
1556+ introduce a new general mechanism for associated types or having a
1557+ special-case for ``Member ``.
1558+
1559+ ``PropsOnly `` (from :ref: `the query builder example <qb-impl >`) would
1560+ look like::
1561+
1562+ type PropsOnly[T] = typing.NewProtocol[
1563+ *[
1564+ typing.Member[typing.GetName[p], PointerArg[typing.GetType[p]]]
1565+ for p in typing.Iter[typing.Attrs[T]]
1566+ if typing.IsAssignable[typing.GetType[p], Property]
1567+ ]
1568+ ]
1569+
1570+ Everyone hated how this looked a lot.
1571+
15001572.. _less_syntax :
15011573
15021574
@@ -1517,8 +1589,9 @@ Boolean operations would likewise become operators (``Not``, ``And``,
15171589etc).
15181590
15191591The advantage of this is that constructing a type annotation never
1520- needs to do non-trivial computation, and thus we don't need
1521- :ref: `runtime hooks <rt-support >` to support evaluating them.
1592+ needs to do non-trivial computation (assuming we also get rid of dot
1593+ notation), and thus we don't need :ref: `runtime hooks <rt-support >` to
1594+ support evaluating them.
15221595
15231596It would also mean that it would be much easier to extract the raw
15241597type annotation. (The lambda form would still be somewhat fiddly.
@@ -1535,35 +1608,6 @@ worse. Supporting filtering while mapping would make it even more bad
15351608
15361609We can explore other options too if needed.
15371610
1538-
1539- Don't use dot notation to access ``Member `` components
1540- ------------------------------------------------------
1541-
1542- Earlier versions of this PEP draft omitted the ability to write
1543- ``m.name `` and similar on ``Member `` and ``Param `` components, and
1544- instead relied on helper operators such as ``typing.GetName `` (that
1545- could be implemented under the hood using ``typing.GetArg `` or
1546- ``typing.GetMemberType ``).
1547-
1548- The potential advantage here is reducing the number of new constructs
1549- being added to the type language, and avoiding needing to either
1550- introduce a new general mechanism for associated types or having a
1551- special-case for ``Member ``.
1552-
1553- ``PropsOnly `` (from :ref: `the query builder example <qb-impl >`) would
1554- look like::
1555-
1556- type PropsOnly[T] = typing.NewProtocol[
1557- *[
1558- typing.Member[typing.GetName[p], PointerArg[typing.GetType[p]]]
1559- for p in typing.Iter[typing.Attrs[T]]
1560- if typing.IsAssignable[typing.GetType[p], Property]
1561- ]
1562- ]
1563-
1564- Everyone hated how this looked a lot.
1565-
1566-
15671611Perform type manipulations with normal Python functions
15681612-------------------------------------------------------
15691613
@@ -1646,7 +1690,7 @@ arguments invariantly.
16461690Acknowledgements
16471691================
16481692
1649- Jukka Lehtosalo
1693+ Jukka Lehtosalo, etc
16501694
16511695[Thank anyone who has helped with the PEP.]
16521696
0 commit comments