@@ -133,9 +133,16 @@ the database) like::
133133 id: Property[int]
134134
135135 name: Property[str]
136+ age: Property[int | None]
136137 email: Property[str]
137138 posts: Link[Post]
138139
140+
141+ (In the example, ``Property `` indicates a scalar type, ``Link ``
142+ indicates a reference to another table, and ``MultiLink `` indicates a
143+ potentially many-to-many reference to another table; all would be
144+ defined by the ORM library.)
145+
139146So, in Python code, a call like::
140147
141148 db.select(
@@ -509,7 +516,7 @@ Operators <pep827-boolean-ops>`, defined below, potentially combined with
509516``any ``, the argument is a comprehension of type booleans, evaluated
510517in the same way as the :ref: `unpacked comprehensions <pep827-unpacked >`.
511518
512- When evaluated in type annotation context, they will evaluate to
519+ When evaluated in type annotation context, they will be equivalent to
513520``Literal[True] `` or ``Literal[False] ``.
514521
515522We restrict what operators may be used in a conditional
@@ -556,6 +563,18 @@ and we want typechecking to match.
556563Type operators
557564--------------
558565
566+ Type operators are the core engine of type manipulation, and provide
567+ the primitives that are used to deconstruct types and construct new
568+ ones.
569+
570+ This section defines the operators being introduced, and explains how
571+ they are to be evaluated in a typechecking or type evaluation context.
572+ The actual runtime classes being introduced, though, are just regular classes,
573+ and subscripting them produces normal ``typing `` generic alias objects
574+ (with the partial exception of the boolean operators and ``Iter ``,
575+ which produce aliases that have some dunder methods overloaded for
576+ :ref: `runtime hooks <pep827-rt-support >`).
577+
559578Many of the operators specified have type bounds listed for some of
560579their operands. These should be interpreted more as documentation than
561580as exact type bounds. Trying to evaluate operators with invalid
@@ -600,22 +619,20 @@ Basic operators
600619
601620 Negative indexes work in the usual way.
602621
603- Note that runtime evaluation will only be able to support proper classes
604- as ``Base ``, * not * protocols . So, for example, ``GetArg[Ty,
605- Iterable, Literal[0]] `` to get the type of something iterable will
606- fail in the runtime evaluator.
622+ ( Note that runtime evaluators of type annotations are likely
623+ to struggle with using protocols as ``Base ``. So, for example, ``GetArg[Ty,
624+ Iterable, Literal[0]] `` to get the type of something iterable may
625+ fail in a runtime evaluator of types.)
607626
608- Special forms require special handling: the arguments list of a ``Callable ``
609- will be packed in a tuple, and a ``... `` will become
610- ``SpecialFormEllipsis ``.
627+ Special forms require special handling: the arguments list of a
628+ ``Callable `` will be packed in a tuple and a ``... `` will be treated
629+ as ``*args: Any `` and ``**kwargs: Any ``, represented with the new
630+ ``Param `` types.
611631
612632* ``GetArgs[T, Base] ``: returns a tuple containing all of the type
613633 arguments of ``T `` when interpreted as ``Base ``, or ``Never `` if it
614634 cannot be.
615635
616- * ``GetMemberType[T, S: Literal[str]] ``: Extract the type of the
617- member named ``S `` from the class ``T ``.
618-
619636* ``Length[T: tuple] `` - Gets the length of a tuple as an int literal
620637 (or ``Literal[None] `` if it is unbounded)
621638
@@ -627,6 +644,10 @@ Basic operators
627644 attributes are ``__name__ ``, ``__module__ ``, and ``__qualname__ ``.
628645 Returns the value as a ``Literal[str] ``.
629646
647+ For non-class types, the principal should be that if ``x `` has type
648+ ``T ``, we want the value of ``type(x).<attr> ``. So
649+ ``GetSpecialAttr[Literal[1], "__name__"] `` should produce ``Literal["int"] ``.
650+
630651All of the operators in this section are :ref: `lifted over union types
631652<pep827-lifting>`.
632653
@@ -643,17 +664,24 @@ Union processing
643664Object inspection
644665'''''''''''''''''
645666
667+ .. _pep827-members :
668+
646669* ``Members[T] ``: produces a ``tuple `` of ``Member `` types describing
647670 the members (attributes and methods) of class or typed dict ``T ``.
648671
649- In order to allow typechecking time and runtime evaluation to coincide
650- more closely, **only members with explicit type annotations are included **.
672+ In order to allow typechecking time and runtime evaluation to
673+ coincide more closely, **only members with explicit type annotations
674+ are included **. (This is intended to also exclude unannotated
675+ methods, though see Open Issues.)
651676
652677* ``Attrs[T] ``: like ``Members[T] `` but only returns attributes (not
653678 methods).
654679
655680* ``GetMember[T, S: Literal[str]] ``: Produces a ``Member `` type for the
656- member named ``S `` from the class ``T ``.
681+ member named ``S `` from the class ``T ``, or ``Never `` if it does not exist.
682+
683+ * ``GetMemberType[T, S: Literal[str]] ``: Extract the type of the
684+ member named ``S `` from the class ``T ``, or ``Never `` if it does not exist.
657685
658686* ``Member[N: Literal[str], T, Q: MemberQuals, Init, D] ``: ``Member ``,
659687 is a simple type, not an operator, that is used to describe members
@@ -662,9 +690,11 @@ Object inspection
662690
663691 * ``N `` is the name, as a literal string type. Accessible with ``.name ``.
664692 * ``T `` is the type. Accessible with ``.type ``.
665- * ``Q `` is a union of qualifiers (see ``MemberQuals `` below). Accessible with ``.quals ``.
693+ * ``Q `` is a union of qualifiers (see ``MemberQuals ``
694+ below). Accessible with ``.quals ``. ``Never `` if no qualifiers.
666695 * ``Init `` is the literal type of the attribute initializer in the
667- class (see :ref: `InitField <pep827-init-field >`). Accessible with ``.init ``.
696+ class (see :ref: `InitField <pep827-init-field >`). Accessible with
697+ ``.init ``. ``Never `` if no initializer.
668698 * ``D `` is the defining class of the member. (That is, which class
669699 the member is inherited from. Always ``Never ``, for a ``TypedDict ``).
670700 Accessible with ``.definer ``.
@@ -674,8 +704,10 @@ Object inspection
674704 member; currently ``ClassVar `` and ``Final `` apply to classes, and
675705 ``NotRequired `` and ``ReadOnly `` apply to typed dicts.
676706
707+ Methods are functions, staticmethods, and classmethods that are
708+ defined class body. Properties should be treated as attributes.
677709
678- Methods are returned as callables using the new ``Param `` based
710+ Methods are returned as callables that are introspectable as ``Param ``- based
679711extended callables, and carrying the ``ClassVar ``
680712qualifier. ``staticmethod `` and ``classmethod `` will return
681713``staticmethod `` and ``classmethod `` types, which are subscriptable as
@@ -787,7 +819,7 @@ Update class
787819
788820 When a class is declared, if one or more of its ancestors have an
789821 ``__init_subclass__ `` with an ``UpdateClass `` return type, they are
790- applied in reverse MRO order. N.B: If the ``cls `` param is
822+ applied in reverse MRO order. If the ``cls `` param is
791823 parameterized by ``type[T] ``, then the class type should be
792824 substituted in for ``T ``.
793825
@@ -1216,6 +1248,7 @@ We present implementations of a selection of them::
12161248
12171249 # Omit<T, Keys>
12181250 # Constructs a type by picking all properties from T and then removing Keys.
1251+ # Note that unlike in TS, our Omit does not depend on Exclude.
12191252 type Omit[T, Keys] = typing.NewProtocol[
12201253 *[
12211254 p
@@ -1224,6 +1257,27 @@ We present implementations of a selection of them::
12241257 ]
12251258 ]
12261259
1260+ # Exclude<T, U>
1261+ # Constructs a type by excluding from T all union members assignable to U.
1262+ type Exclude[T, U] = Union[
1263+ *[
1264+ x
1265+ for x in typing.Iter[typing.FromUnion[T]]
1266+ if not typing.IsAssignable[x, U]
1267+ ]
1268+ ]
1269+
1270+ # Extract<T, U>
1271+ # Constructs a type by extracting from T all union members assignable to U.
1272+ type Extract[T, U] = Union[
1273+ *[
1274+ x
1275+ for x in typing.Iter[typing.FromUnion[T]]
1276+ # Just the inverse of Exclude, really
1277+ if typing.IsAssignable[x, U]
1278+ ]
1279+ ]
1280+
12271281 # Partial<T>
12281282 # Constructs a type with all properties of T set to optional (T | None).
12291283 type Partial[T] = typing.NewProtocol[
@@ -1843,6 +1897,12 @@ Open Issues
18431897 there is a default, and have whether there is a default represented in
18441898 an ``init `` field, like we do for class member initializers with ``Member ``.
18451899
1900+ * :ref: `Members <pep827-members >`: Should ``Members `` return all
1901+ methods, even those without annotations? We excluded them out of the
1902+ desire for some consistency with attributes, but it would not be
1903+ technically difficult to include them in either static or runtime
1904+ evaluators.
1905+
18461906* :ref: `Generic Callable <pep827-generic-callable >`: Should we have any mechanisms
18471907 to inspect/destruct ``GenericCallable ``? Maybe can fetch the variable
18481908 information and maybe can apply it to concrete types?
@@ -1855,6 +1915,8 @@ Open Issues
18551915 rejected. This does actually exactly mirror a potential **runtime **
18561916 evaluation-order dependence, though.
18571917
1918+ * Should ``RaiseError `` support string templating when outputing the types?
1919+
18581920* Because of generic functions, there will be plenty of cases where we
18591921 can't evaluate a type operator (because it's applied to an unresolved
18601922 type variable), and exactly what the type evaluation rules should be
0 commit comments