Skip to content

Commit 48bd3af

Browse files
committed
Replace string-based ParamQuals with ParamKind IntEnum
Model parameter qualifiers on inspect._ParameterKind instead of using ad-hoc string literals. Drop the ParamQuals Literal type alias and bind Param's Q directly to the ParamKind enum.
1 parent c567406 commit 48bd3af

9 files changed

Lines changed: 169 additions & 105 deletions

pep.rst

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -393,18 +393,31 @@ Extended Callables, take 2
393393

394394
We introduce a ``Param`` type the contains all the information about a function param::
395395

396-
class Param[N: str | None, T, Q: ParamQuals = typing.Never]:
396+
class ParamKind(enum.IntEnum):
397+
"""Parameter kind qualifiers, modeled on inspect._ParameterKind."""
398+
POSITIONAL_ONLY = 0
399+
POSITIONAL_OR_KEYWORD = 1
400+
VAR_POSITIONAL = 2
401+
KEYWORD_ONLY = 3
402+
VAR_KEYWORD = 4
403+
HAS_DEFAULT = 5
404+
405+
class Param[N: str | None, T, Q: ParamKind = typing.Never]:
397406
pass
398407

399-
ParamQuals = typing.Literal["*", "**", "default", "keyword"]
400-
401-
type PosParam[N: str | None, T] = Param[N, T, Literal["positional"]]
402-
type PosDefaultParam[N: str | None, T] = Param[N, T, Literal["positional", "default"]]
403-
type DefaultParam[N: str, T] = Param[N, T, Literal["default"]]
404-
type NamedParam[N: str, T] = Param[N, T, Literal["keyword"]]
405-
type NamedDefaultParam[N: str, T] = Param[N, T, Literal["keyword", "default"]]
406-
type ArgsParam[T] = Param[Literal[None], T, Literal["*"]]
407-
type KwargsParam[T] = Param[Literal[None], T, Literal["**"]]
408+
type PosParam[N: str | None, T] = Param[
409+
N, T, Literal[ParamKind.POSITIONAL_ONLY]
410+
]
411+
type PosDefaultParam[N: str | None, T] = Param[
412+
N, T, Literal[ParamKind.POSITIONAL_ONLY, ParamKind.HAS_DEFAULT]
413+
]
414+
type DefaultParam[N: str, T] = Param[N, T, Literal[ParamKind.HAS_DEFAULT]]
415+
type NamedParam[N: str, T] = Param[N, T, Literal[ParamKind.KEYWORD_ONLY]]
416+
type NamedDefaultParam[N: str, T] = Param[
417+
N, T, Literal[ParamKind.KEYWORD_ONLY, ParamKind.HAS_DEFAULT]
418+
]
419+
type ArgsParam[T] = Param[Literal[None], T, Literal[ParamKind.VAR_POSITIONAL]]
420+
type KwargsParam[T] = Param[Literal[None], T, Literal[ParamKind.VAR_KEYWORD]]
408421

409422
And then, we can represent the type of a function like::
410423

@@ -424,13 +437,13 @@ as (we are omitting the ``Literal`` in places)::
424437

425438
Callable[
426439
[
427-
Param["a", int, "positional"],
440+
Param["a", int, ParamKind.POSITIONAL_ONLY],
428441
Param["b", int],
429-
Param["c", int, "default"],
430-
Param[None, int, "*"],
431-
Param["d", int, "keyword"],
432-
Param["e", int, Literal["default", "keyword"]],
433-
Param[None, int, "**"],
442+
Param["c", int, ParamKind.HAS_DEFAULT],
443+
Param[None, int, ParamKind.VAR_POSITIONAL],
444+
Param["d", int, ParamKind.KEYWORD_ONLY],
445+
Param["e", int, Literal[ParamKind.HAS_DEFAULT, ParamKind.KEYWORD_ONLY]],
446+
Param[None, int, ParamKind.VAR_KEYWORD],
434447
],
435448
int,
436449
]
@@ -1130,12 +1143,12 @@ dataclasses-style method generation
11301143
typing.GetType[p],
11311144
# All arguments are keyword-only
11321145
# It takes a default if a default is specified in the class
1133-
Literal["keyword"]
1146+
Literal[typing.ParamKind.KEYWORD_ONLY]
11341147
if typing.IsAssignable[
11351148
GetDefault[typing.GetInit[p]],
11361149
Never,
11371150
]
1138-
else Literal["keyword", "default"],
1151+
else Literal[typing.ParamKind.KEYWORD_ONLY, typing.ParamKind.HAS_DEFAULT],
11391152
]
11401153
for p in typing.Iter[typing.Attrs[T]]
11411154
],

tests/test_eval_call_with_types.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Iter,
1313
Members,
1414
Param,
15+
ParamKind,
1516
)
1617

1718

@@ -27,7 +28,10 @@ def test_eval_call_with_types_callable_02():
2728

2829
def test_eval_call_with_types_callable_03():
2930
res = eval_call_with_types(
30-
Callable[[Param[Literal["x"], int, Literal["keyword"]]], int], x=int
31+
Callable[
32+
[Param[Literal["x"], int, Literal[ParamKind.KEYWORD_ONLY]]], int
33+
],
34+
x=int,
3135
)
3236
assert res is int
3337

@@ -64,7 +68,7 @@ class C: ...
6468
Callable[
6569
[
6670
Param[Literal["self"], Self],
67-
Param[Literal["x"], int, Literal["keyword"]],
71+
Param[Literal["x"], int, Literal[ParamKind.KEYWORD_ONLY]],
6872
],
6973
int,
7074
],

tests/test_fastapilike_1.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
GetQuals,
1919
Member,
2020
Members,
21+
ParamKind,
2122
Param,
2223
)
2324

@@ -53,12 +54,12 @@ class _Default:
5354
Param[
5455
GetName[p],
5556
DropAnnotations[GetType[p]],
56-
Literal["keyword", "default"]
57+
Literal[ParamKind.KEYWORD_ONLY, ParamKind.HAS_DEFAULT]
5758
if IsAssignable[
5859
Literal[PropQuals.HAS_DEFAULT],
5960
GetAnnotations[GetType[p]],
6061
]
61-
else Literal["keyword"],
62+
else Literal[ParamKind.KEYWORD_ONLY],
6263
]
6364
for p in Iter[Attrs[T]]
6465
],

tests/test_fastapilike_2.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,15 @@ class Field[T: FieldArgs](typing.InitField[T]):
152152
typing.GetType[p],
153153
# All arguments are keyword-only
154154
# It takes a default if a default is specified in the class
155-
Literal["keyword"]
155+
Literal[typing.ParamKind.KEYWORD_ONLY]
156156
if typing.IsAssignable[
157157
GetDefault[typing.GetInit[p]],
158158
Never,
159159
]
160-
else Literal["keyword", "default"],
160+
else Literal[
161+
typing.ParamKind.KEYWORD_ONLY,
162+
typing.ParamKind.HAS_DEFAULT,
163+
],
161164
]
162165
for p in typing.Iter[typing.Attrs[T]]
163166
],

tests/test_schemalike.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Member,
1313
NamedParam,
1414
Param,
15+
ParamKind,
1516
StrConcat,
1617
)
1718

@@ -50,7 +51,11 @@ class Property:
5051
Callable[
5152
[
5253
Param[Literal["self"], Schemaify[T]],
53-
NamedParam[Literal["schema"], Schema, Literal["keyword"]],
54+
NamedParam[
55+
Literal["schema"],
56+
Schema,
57+
Literal[ParamKind.KEYWORD_ONLY],
58+
],
5459
],
5560
GetType[p],
5661
],

tests/test_type_dir.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,8 @@ def test_type_members_func_1():
379379
typing.Callable[[\
380380
typemap.typing.Param[typing.Literal['self'], tests.test_type_dir.Base[int], typing.Never], \
381381
typemap.typing.Param[typing.Literal['a'], int | None, typing.Never], \
382-
typemap.typing.Param[typing.Literal['b'], int, typing.Literal['keyword', \
383-
'default']]], \
382+
typemap.typing.Param[typing.Literal['b'], int, typing.Literal[\
383+
<ParamKind.KEYWORD_ONLY: 3>, <ParamKind.HAS_DEFAULT: 5>]]], \
384384
dict[str, int]]"
385385
)
386386

0 commit comments

Comments
 (0)