Skip to content

Commit 48d0722

Browse files
authored
Use typing. in the examples to make it more clear what are builtins (#66)
1 parent e747f7b commit 48d0722

4 files changed

Lines changed: 140 additions & 114 deletions

File tree

pep.rst

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -908,18 +908,18 @@ as a literal type--all of these mechanisms lean very heavily on literal types.
908908

909909
::
910910

911-
def select[ModelT, K: BaseTypedDict](
911+
def select[ModelT, K: typing.BaseTypedDict](
912912
typ: type[ModelT],
913913
/,
914914
**kwargs: Unpack[K],
915915
) -> list[
916-
NewProtocol[
916+
typing.NewProtocol[
917917
*[
918-
Member[
919-
GetName[c],
920-
ConvertField[GetMemberType[ModelT, GetName[c]]],
918+
typing.Member[
919+
typing.GetName[c],
920+
ConvertField[typing.GetMemberType[ModelT, typing.GetName[c]]],
921921
]
922-
for c in Iter[Attrs[K]]
922+
for c in typing.Iter[typing.Attrs[K]]
923923
]
924924
]
925925
]: ...
@@ -936,7 +936,9 @@ producing a new target type containing only properties and wrapping
936936
::
937937

938938
type ConvertField[T] = (
939-
AdjustLink[PropsOnly[PointerArg[T]], T] if IsSub[T, Link] else PointerArg[T]
939+
AdjustLink[PropsOnly[PointerArg[T]], T]
940+
if typing.IsSub[T, Link]
941+
else PointerArg[T]
940942
)
941943

942944
``PointerArg`` gets the type argument to ``Pointer`` or a subclass.
@@ -950,26 +952,28 @@ grabs the argument to a ``Pointer``).
950952

951953
::
952954

953-
type PointerArg[T: Pointer] = GetArg[T, Pointer, Literal[0]]
955+
type PointerArg[T: Pointer] = typing.GetArg[T, Pointer, Literal[0]]
954956

955957
``AdjustLink`` sticks a ``list`` around ``MultiLink``, using features
956958
we've discussed already.
957959

958960
::
959961

960-
type AdjustLink[Tgt, LinkTy] = list[Tgt] if IsSub[LinkTy, MultiLink] else Tgt
962+
type AdjustLink[Tgt, LinkTy] = (
963+
list[Tgt] if typing.IsSub[LinkTy, MultiLink] else Tgt
964+
)
961965

962966
And the final helper, ``PropsOnly[T]``, generates a new type that
963967
contains all the ``Property`` attributes of ``T``.
964968

965969
::
966970

967971
type PropsOnly[T] = list[
968-
NewProtocol[
972+
typing.NewProtocol[
969973
*[
970-
Member[GetName[p], PointerArg[GetType[p]]]
971-
for p in Iter[Attrs[T]]
972-
if IsSub[GetType[p], Property]
974+
typing.Member[typing.GetName[p], PointerArg[typing.GetType[p]]]
975+
for p in typing.Iter[typing.Attrs[T]]
976+
if typing.IsSub[typing.GetType[p], Property]
973977
]
974978
]
975979
]
@@ -983,22 +987,32 @@ Automatically deriving FastAPI CRUD models
983987
------------------------------------------
984988

985989
We have a more `fully-worked example <#fastapi-test_>`_ in our test
986-
suite, but here is a possible implementation of just ``Public``::
990+
suite, but here is a possible implementation of just ``Public``
991+
992+
::
987993

988994
# Extract the default type from an Init field.
989995
# If it is a Field, then we try pulling out the "default" field,
990996
# otherwise we return the type itself.
991997
type GetDefault[Init] = (
992-
GetFieldItem[Init, Literal["default"]] if IsSub[Init, Field] else Init
998+
GetFieldItem[Init, Literal["default"]]
999+
if typing.IsSub[Init, Field]
1000+
else Init
9931001
)
9941002

9951003
# Create takes everything but the primary key and preserves defaults
996-
type Create[T] = NewProtocol[
1004+
type Create[T] = typing.NewProtocol[
9971005
*[
998-
Member[GetName[p], GetType[p], GetQuals[p], GetDefault[GetInit[p]]]
999-
for p in Iter[Attrs[T]]
1000-
if not IsSub[
1001-
Literal[True], GetFieldItem[GetInit[p], Literal["primary_key"]]
1006+
typing.Member[
1007+
typing.GetName[p],
1008+
typing.GetType[p],
1009+
typing.GetQuals[p],
1010+
GetDefault[typing.GetInit[p]],
1011+
]
1012+
for p in typing.Iter[typing.Attrs[T]]
1013+
if not typing.IsSub[
1014+
Literal[True],
1015+
GetFieldItem[typing.GetInit[p], Literal["primary_key"]],
10021016
]
10031017
]
10041018
]
@@ -1023,34 +1037,34 @@ dataclasses-style method generation
10231037
::
10241038

10251039
# Generate the Member field for __init__ for a class
1026-
type InitFnType[T] = Member[
1040+
type InitFnType[T] = typing.Member[
10271041
Literal["__init__"],
10281042
Callable[
10291043
[
1030-
Param[Literal["self"], Self],
1044+
typing.Param[Literal["self"], Self],
10311045
*[
1032-
Param[
1033-
GetName[p],
1034-
GetType[p],
1046+
typing.Param[
1047+
typing.GetName[p],
1048+
typing.GetType[p],
10351049
# All arguments are keyword-only
10361050
# It takes a default if a default is specified in the class
10371051
Literal["keyword"]
1038-
if IsSub[
1039-
GetDefault[GetInit[p]],
1052+
if typing.IsSub[
1053+
GetDefault[typing.GetInit[p]],
10401054
Never,
10411055
]
10421056
else Literal["keyword", "default"],
10431057
]
1044-
for p in Iter[Attrs[T]]
1058+
for p in typing.Iter[typing.Attrs[T]]
10451059
],
10461060
],
10471061
None,
10481062
],
10491063
Literal["ClassVar"],
10501064
]
1051-
type AddInit[T] = NewProtocol[
1065+
type AddInit[T] = typing.NewProtocol[
10521066
InitFnType[T],
1053-
*[x for x in Iter[Members[T]]],
1067+
*[x for x in typing.Iter[typing.Members[T]]],
10541068
]
10551069

10561070

@@ -1121,11 +1135,7 @@ Renounce all cares of runtime evaluation
11211135

11221136
This would have a lot of simplifying features.
11231137

1124-
We wouldn't need to worry about making ``IsSub`` be checkable at
1125-
runtime,
1126-
1127-
XXX
1128-
1138+
TODO: Expand
11291139

11301140
Support TypeScript style pattern matching in subtype checking
11311141
-------------------------------------------------------------

scripts/update-examples.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ scripts/py2rst.py tests/test_qblike_2.py --start "Begin PEP section" --end "End
44
| scripts/rst_replace_section.py pep.rst qb-impl -i
55

66

7-
scripts/py2rst.py tests/test_fastapilike_2.py --start "Begin PEP section" --end "End PEP section" \
7+
scripts/py2rst.py tests/test_fastapilike_2.py --start "Begin PEP section: dataclass like" --end "End PEP section: __init__" \
88
| scripts/rst_replace_section.py pep.rst init-impl -i
9+
10+
scripts/py2rst.py tests/test_fastapilike_2.py --start "Begin PEP section: Automatically deriving FastAPI CRUD models" --end "End PEP section: CRUD" \
11+
| scripts/rst_replace_section.py pep.rst fastapi-impl -i

tests/test_fastapilike_2.py

Lines changed: 72 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,7 @@
1111
)
1212

1313
from typemap.type_eval import eval_typing
14-
from typemap.typing import (
15-
NewProtocol,
16-
Iter,
17-
Attrs,
18-
IsSub,
19-
FromUnion,
20-
GetArg,
21-
GetMemberType,
22-
GetType,
23-
GetName,
24-
GetQuals,
25-
GetInit,
26-
InitField,
27-
Member,
28-
Members,
29-
Param,
30-
)
14+
from typemap import typing
3115

3216
from . import format_helper
3317

@@ -39,15 +23,15 @@ class FieldArgs(TypedDict, total=False):
3923
default: ReadOnly[object]
4024

4125

42-
class Field[T: FieldArgs](InitField[T]):
26+
class Field[T: FieldArgs](typing.InitField[T]):
4327
pass
4428

4529

4630
####
4731

4832
# TODO: Should this go into the stdlib?
49-
type GetFieldItem[T: InitField, K] = GetMemberType[
50-
GetArg[T, InitField, Literal[0]], K
33+
type GetFieldItem[T: typing.InitField, K] = typing.GetMemberType[
34+
typing.GetArg[T, typing.InitField, Literal[0]], K
5135
]
5236

5337

@@ -56,59 +40,96 @@ class Field[T: FieldArgs](InitField[T]):
5640
# Strip `| None` from a type by iterating over its union components
5741
# and filtering
5842
type NotOptional[T] = Union[
59-
*[x for x in Iter[FromUnion[T]] if not IsSub[x, None]]
43+
*[x for x in typing.Iter[typing.FromUnion[T]] if not typing.IsSub[x, None]]
6044
]
6145

6246
# Adjust an attribute type for use in Public below by dropping | None for
6347
# primary keys and stripping all annotations.
6448
type FixPublicType[T, Init] = (
6549
NotOptional[T]
66-
if IsSub[Literal[True], GetFieldItem[Init, Literal["primary_key"]]]
50+
if typing.IsSub[Literal[True], GetFieldItem[Init, Literal["primary_key"]]]
6751
else T
6852
)
6953

7054
# Strip out everything that is Hidden and also make the primary key required
7155
# Drop all the annotations, since this is for data getting returned to users
7256
# from the DB, so we don't need default values.
73-
type Public[T] = NewProtocol[
57+
type Public[T] = typing.NewProtocol[
7458
*[
75-
Member[GetName[p], FixPublicType[GetType[p], GetInit[p]], GetQuals[p]]
76-
for p in Iter[Attrs[T]]
77-
if not IsSub[Literal[True], GetFieldItem[GetInit[p], Literal["hidden"]]]
59+
typing.Member[
60+
typing.GetName[p],
61+
FixPublicType[typing.GetType[p], typing.GetInit[p]],
62+
typing.GetQuals[p],
63+
]
64+
for p in typing.Iter[typing.Attrs[T]]
65+
if not typing.IsSub[
66+
Literal[True], GetFieldItem[typing.GetInit[p], Literal["hidden"]]
67+
]
7868
]
7969
]
8070

71+
# Begin PEP section: Automatically deriving FastAPI CRUD models
72+
"""
73+
We have a more `fully-worked example <#fastapi-test_>`_ in our test
74+
suite, but here is a possible implementation of just ``Public``
75+
"""
76+
8177
# Extract the default type from an Init field.
8278
# If it is a Field, then we try pulling out the "default" field,
8379
# otherwise we return the type itself.
8480
type GetDefault[Init] = (
85-
GetFieldItem[Init, Literal["default"]] if IsSub[Init, Field] else Init
81+
GetFieldItem[Init, Literal["default"]]
82+
if typing.IsSub[Init, Field]
83+
else Init
8684
)
8785

8886
# Create takes everything but the primary key and preserves defaults
89-
type Create[T] = NewProtocol[
87+
type Create[T] = typing.NewProtocol[
9088
*[
91-
Member[GetName[p], GetType[p], GetQuals[p], GetDefault[GetInit[p]]]
92-
for p in Iter[Attrs[T]]
93-
if not IsSub[
94-
Literal[True], GetFieldItem[GetInit[p], Literal["primary_key"]]
89+
typing.Member[
90+
typing.GetName[p],
91+
typing.GetType[p],
92+
typing.GetQuals[p],
93+
GetDefault[typing.GetInit[p]],
94+
]
95+
for p in typing.Iter[typing.Attrs[T]]
96+
if not typing.IsSub[
97+
Literal[True],
98+
GetFieldItem[typing.GetInit[p], Literal["primary_key"]],
9599
]
96100
]
97101
]
98102

103+
"""
104+
The ``Create`` type alias creates a new type (via ``NewProtocol``) by
105+
iterating over the attributes of the original type. It has access to
106+
names, types, qualifiers, and the literal types of initializers (in
107+
part through new facilities to handle the extremely common
108+
``= Field(...)`` like pattern used here.
109+
110+
Here, we filter out attributes that have ``primary_key=True`` in their
111+
``Field`` as well as extracting default arguments (which may be either
112+
from a ``default`` argument to a field or specified directly as an
113+
initializer).
114+
"""
115+
116+
# End PEP section: CRUD
117+
118+
99119
# Update takes everything but the primary key, but makes them all have
100120
# None defaults
101-
type Update[T] = NewProtocol[
121+
type Update[T] = typing.NewProtocol[
102122
*[
103-
Member[
104-
GetName[p],
105-
GetType[p] | None,
106-
GetQuals[p],
123+
typing.Member[
124+
typing.GetName[p],
125+
typing.GetType[p] | None,
126+
typing.GetQuals[p],
107127
Literal[None],
108128
]
109-
for p in Iter[Attrs[T]]
110-
if not IsSub[
111-
Literal[True], GetFieldItem[GetInit[p], Literal["primary_key"]]
129+
for p in typing.Iter[typing.Attrs[T]]
130+
if not typing.IsSub[
131+
Literal[True],
132+
GetFieldItem[typing.GetInit[p], Literal["primary_key"]],
112133
]
113134
]
114135
]
@@ -117,40 +138,39 @@ class Field[T: FieldArgs](InitField[T]):
117138

118139
# Begin PEP section: dataclass like __init__
119140

120-
121141
# Generate the Member field for __init__ for a class
122-
type InitFnType[T] = Member[
142+
type InitFnType[T] = typing.Member[
123143
Literal["__init__"],
124144
Callable[
125145
[
126-
Param[Literal["self"], Self],
146+
typing.Param[Literal["self"], Self],
127147
*[
128-
Param[
129-
GetName[p],
130-
GetType[p],
148+
typing.Param[
149+
typing.GetName[p],
150+
typing.GetType[p],
131151
# All arguments are keyword-only
132152
# It takes a default if a default is specified in the class
133153
Literal["keyword"]
134-
if IsSub[
135-
GetDefault[GetInit[p]],
154+
if typing.IsSub[
155+
GetDefault[typing.GetInit[p]],
136156
Never,
137157
]
138158
else Literal["keyword", "default"],
139159
]
140-
for p in Iter[Attrs[T]]
160+
for p in typing.Iter[typing.Attrs[T]]
141161
],
142162
],
143163
None,
144164
],
145165
Literal["ClassVar"],
146166
]
147-
type AddInit[T] = NewProtocol[
167+
type AddInit[T] = typing.NewProtocol[
148168
InitFnType[T],
149-
*[x for x in Iter[Members[T]]],
169+
*[x for x in typing.Iter[typing.Members[T]]],
150170
]
151171

152172

153-
# End PEP section
173+
# End PEP section: __init__
154174

155175

156176
####

0 commit comments

Comments
 (0)