From 9c9cd917d8c397e42d8e1d29a77b1370d00988d6 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Fri, 16 Jan 2026 16:38:45 -0800 Subject: [PATCH] Rename Sub -> IsSub Yury says Guido would complain about `Sub`. --- tests/test_fastapilike_1.py | 16 +++++++++------- tests/test_fastapilike_2.py | 16 ++++++++-------- tests/test_qblike.py | 8 +++++--- tests/test_qblike_2.py | 8 ++++---- tests/test_type_dir.py | 18 +++++++++--------- tests/test_type_eval.py | 10 +++++----- typemap/typing.py | 2 +- 7 files changed, 41 insertions(+), 37 deletions(-) diff --git a/tests/test_fastapilike_1.py b/tests/test_fastapilike_1.py index 5e35071..3b79a7f 100644 --- a/tests/test_fastapilike_1.py +++ b/tests/test_fastapilike_1.py @@ -9,7 +9,7 @@ NewProtocol, Iter, Attrs, - Sub, + IsSub, GetAnnotations, DropAnnotations, FromUnion, @@ -54,7 +54,7 @@ class _Default: GetName[p], DropAnnotations[GetType[p]], Literal["keyword", "default"] - if Sub[ + if IsSub[ Literal[PropQuals.HAS_DEFAULT], GetAnnotations[GetType[p]], ] @@ -104,13 +104,15 @@ class _Default: # Strip `| None` from a type by iterating over its union components # and filtering type NotOptional[T] = Union[ - *[x for x in Iter[FromUnion[T]] if not Sub[x, None]] + *[x for x in Iter[FromUnion[T]] if not IsSub[x, None]] ] # Adjust an attribute type for use in Public below by dropping | None for # primary keys and stripping all annotations. type FixPublicType[T] = DropAnnotations[ - NotOptional[T] if Sub[Literal[PropQuals.PRIMARY], GetAnnotations[T]] else T + NotOptional[T] + if IsSub[Literal[PropQuals.PRIMARY], GetAnnotations[T]] + else T ] # Strip out everything that is Hidden and also make the primary key required @@ -120,7 +122,7 @@ class _Default: *[ Member[GetName[p], FixPublicType[GetType[p]], GetQuals[p]] for p in Iter[Attrs[T]] - if not Sub[Literal[PropQuals.HIDDEN], GetAnnotations[GetType[p]]] + if not IsSub[Literal[PropQuals.HIDDEN], GetAnnotations[GetType[p]]] ] ] @@ -129,7 +131,7 @@ class _Default: *[ Member[GetName[p], GetType[p], GetQuals[p]] for p in Iter[Attrs[T]] - if not Sub[Literal[PropQuals.PRIMARY], GetAnnotations[GetType[p]]] + if not IsSub[Literal[PropQuals.PRIMARY], GetAnnotations[GetType[p]]] ] ] @@ -144,7 +146,7 @@ class _Default: GetQuals[p], ] for p in Iter[Attrs[T]] - if not Sub[Literal[PropQuals.PRIMARY], GetAnnotations[GetType[p]]] + if not IsSub[Literal[PropQuals.PRIMARY], GetAnnotations[GetType[p]]] ] ] diff --git a/tests/test_fastapilike_2.py b/tests/test_fastapilike_2.py index c21e46f..7a33109 100644 --- a/tests/test_fastapilike_2.py +++ b/tests/test_fastapilike_2.py @@ -15,7 +15,7 @@ NewProtocol, Iter, Attrs, - Sub, + IsSub, FromUnion, GetArg, GetAttr, @@ -54,14 +54,14 @@ class Field[T: FieldArgs](InitField[T]): # Strip `| None` from a type by iterating over its union components # and filtering type NotOptional[T] = Union[ - *[x for x in Iter[FromUnion[T]] if not Sub[x, None]] + *[x for x in Iter[FromUnion[T]] if not IsSub[x, None]] ] # Adjust an attribute type for use in Public below by dropping | None for # primary keys and stripping all annotations. type FixPublicType[T, Init] = ( NotOptional[T] - if Sub[Literal[True], GetFieldItem[Init, Literal["primary_key"]]] + if IsSub[Literal[True], GetFieldItem[Init, Literal["primary_key"]]] else T ) @@ -72,7 +72,7 @@ class Field[T: FieldArgs](InitField[T]): *[ Member[GetName[p], FixPublicType[GetType[p], GetInit[p]], GetQuals[p]] for p in Iter[Attrs[T]] - if not Sub[Literal[True], GetFieldItem[GetInit[p], Literal["hidden"]]] + if not IsSub[Literal[True], GetFieldItem[GetInit[p], Literal["hidden"]]] ] ] @@ -80,7 +80,7 @@ class Field[T: FieldArgs](InitField[T]): # If it is a Field, then we try pulling out the "default" field, # otherwise we return the type itself. type GetDefault[Init] = ( - GetFieldItem[Init, Literal["default"]] if Sub[Init, Field] else Init + GetFieldItem[Init, Literal["default"]] if IsSub[Init, Field] else Init ) # Create takes everything but the primary key and preserves defaults @@ -88,7 +88,7 @@ class Field[T: FieldArgs](InitField[T]): *[ Member[GetName[p], GetType[p], GetQuals[p], GetDefault[GetInit[p]]] for p in Iter[Attrs[T]] - if not Sub[ + if not IsSub[ Literal[True], GetFieldItem[GetInit[p], Literal["primary_key"]] ] ] @@ -105,7 +105,7 @@ class Field[T: FieldArgs](InitField[T]): Literal[None], ] for p in Iter[Attrs[T]] - if not Sub[ + if not IsSub[ Literal[True], GetFieldItem[GetInit[p], Literal["primary_key"]] ] ] @@ -129,7 +129,7 @@ class Field[T: FieldArgs](InitField[T]): # All arguments are keyword-only # It takes a default if a default is specified in the class Literal["keyword"] - if Sub[ + if IsSub[ GetDefault[GetInit[p]], Never, ] diff --git a/tests/test_qblike.py b/tests/test_qblike.py index 7216f0e..13b9ffb 100644 --- a/tests/test_qblike.py +++ b/tests/test_qblike.py @@ -8,7 +8,7 @@ NewProtocol, Iter, Attrs, - Sub, + IsSub, GetType, Member, GetName, @@ -28,11 +28,13 @@ class Link[T]: type PropsOnly[T] = NewProtocol[ - *[p for p in Iter[Attrs[T]] if Sub[GetType[p], Property]] + *[p for p in Iter[Attrs[T]] if IsSub[GetType[p], Property]] ] # Conditional type alias! -type FilterLinks[T] = Link[PropsOnly[GetArg[T, Link, 0]]] if Sub[T, Link] else T +type FilterLinks[T] = ( + Link[PropsOnly[GetArg[T, Link, 0]]] if IsSub[T, Link] else T +) def select[K: BaseTypedDict]( diff --git a/tests/test_qblike_2.py b/tests/test_qblike_2.py index de493f7..21ddb4d 100644 --- a/tests/test_qblike_2.py +++ b/tests/test_qblike_2.py @@ -8,7 +8,7 @@ NewProtocol, Iter, Attrs, - Sub, + IsSub, GetType, Member, GetName, @@ -95,7 +95,7 @@ def select[ModelT, K: BaseTypedDict]( """ type ConvertField[T] = ( - AdjustLink[PropsOnly[PointerArg[T]], T] if Sub[T, Link] else PointerArg[T] + AdjustLink[PropsOnly[PointerArg[T]], T] if IsSub[T, Link] else PointerArg[T] ) """``PointerArg`` gets the type argument to ``Pointer`` or a subclass. @@ -115,7 +115,7 @@ def select[ModelT, K: BaseTypedDict]( we've discussed already. """ -type AdjustLink[Tgt, LinkTy] = list[Tgt] if Sub[LinkTy, MultiLink] else Tgt +type AdjustLink[Tgt, LinkTy] = list[Tgt] if IsSub[LinkTy, MultiLink] else Tgt """And the final helper, ``PropsOnly[T]``, generates a new type that contains all the ``Property`` attributes of ``T``. @@ -126,7 +126,7 @@ def select[ModelT, K: BaseTypedDict]( *[ Member[GetName[p], PointerArg[GetType[p]]] for p in Iter[Attrs[T]] - if Sub[GetType[p], Property] + if IsSub[GetType[p], Property] ] ] ] diff --git a/tests/test_type_dir.py b/tests/test_type_dir.py index 8fffd26..bf4e32d 100644 --- a/tests/test_type_dir.py +++ b/tests/test_type_dir.py @@ -11,7 +11,7 @@ GetQuals, GetType, InitField, - Sub, + IsSub, Iter, Member, Members, @@ -80,7 +80,7 @@ class Final(Mine, Ordinary, Wrapper[float], AnotherBase[float], Last[int]): pass -type BaseArg[T] = GetArg[T, Base, 0] if Sub[T, Base] else Never +type BaseArg[T] = GetArg[T, Base, 0] if IsSub[T, Base] else Never type AllOptional[T] = NewProtocol[ @@ -101,7 +101,7 @@ class Final(Mine, Ordinary, Wrapper[float], AnotherBase[float], Last[int]): ] type Prims[T] = NewProtocol[ - *[p for p in Iter[Attrs[T]] if Sub[GetType[p], int | str]] + *[p for p in Iter[Attrs[T]] if IsSub[GetType[p], int | str]] ] type NoLiterals1[T] = NewProtocol[ @@ -114,7 +114,7 @@ class Final(Mine, Ordinary, Wrapper[float], AnotherBase[float], Last[int]): for t in Iter[FromUnion[GetType[p]]] # XXX: 'typing.Literal' is not *really* a type... # Maybe we can't do this, which maybe is fine. - if not Sub[t, Literal] + if not IsSub[t, Literal] ] ], GetQuals[p], @@ -130,10 +130,10 @@ class Final(Mine, Ordinary, Wrapper[float], AnotherBase[float], Last[int]): type IsLiteral[T] = ( Literal[True] if ( - (Sub[T, str] and not Sub[str, T]) - or (Sub[T, bytes] and not Sub[bytes, T]) - or (Sub[T, bool] and not Sub[bool, T]) - or (Sub[T, int] and not Sub[int, T]) + (IsSub[T, str] and not IsSub[str, T]) + or (IsSub[T, bytes] and not IsSub[bytes, T]) + or (IsSub[T, bool] and not IsSub[bool, T]) + or (IsSub[T, int] and not IsSub[int, T]) # XXX: enum, None ) else Literal[False] @@ -150,7 +150,7 @@ class Final(Mine, Ordinary, Wrapper[float], AnotherBase[float], Last[int]): # XXX: 'typing.Literal' is not *really* a type... # Maybe we can't do this, which maybe is fine. # if not IsSubtype[t, Literal] - if not Sub[IsLiteral[t], Literal[True]] + if not IsSub[IsLiteral[t], Literal[True]] ] ], GetQuals[p], diff --git a/tests/test_type_eval.py b/tests/test_type_eval.py index aef7093..9f16d38 100644 --- a/tests/test_type_eval.py +++ b/tests/test_type_eval.py @@ -26,7 +26,7 @@ GetName, GetType, GetAnnotations, - Sub, + IsSub, Iter, Length, Member, @@ -63,7 +63,7 @@ class F_int(F[int]): *[ ( Member[GetName[p], OrGotcha[GetType[p]]] - if not Sub[GetType[p], A] + if not IsSub[GetType[p], A] else Member[GetName[p], OrGotcha[MapRecursive[A]]] ) # XXX: This next line *ought* to work, but we haven't @@ -709,7 +709,7 @@ def test_uppercase_never(): def test_never_is(): - d = eval_typing(Sub[Never, Never]) + d = eval_typing(IsSub[Never, Never]) assert d is True @@ -769,7 +769,7 @@ def test_eval_literal_idempotent_01(): def test_is_literal_true_vs_one(): - assert eval_typing(Sub[Literal[True], Literal[1]]) is False + assert eval_typing(IsSub[Literal[True], Literal[1]]) is False def test_callable_to_signature(): @@ -832,7 +832,7 @@ class AnnoTest: def test_type_eval_annotated_02(): - res = eval_typing(Sub[GetAttr[AnnoTest, Literal["a"]], int]) + res = eval_typing(IsSub[GetAttr[AnnoTest, Literal["a"]], int]) assert res is True diff --git a/typemap/typing.py b/typemap/typing.py index 45d9bc5..e7e7dd8 100644 --- a/typemap/typing.py +++ b/typemap/typing.py @@ -214,4 +214,4 @@ def IsSubSimilar(self, tps): return _IsGenericAlias(self, tps) -Sub = IsSubSimilar +IsSub = IsSubSimilar