@@ -807,7 +807,7 @@ def output_templates(self, f):
807
807
default_return_converter = (not f .return_converter or
808
808
f .return_converter .type == 'PyObject *' )
809
809
810
- new_or_init = f .kind in ( METHOD_NEW , METHOD_INIT )
810
+ new_or_init = f .kind . new_or_init
811
811
812
812
vararg = NO_VARARG
813
813
pos_only = min_pos = max_pos = min_kw_only = pseudo_args = 0
@@ -1250,7 +1250,7 @@ def parser_body(
1250
1250
if new_or_init :
1251
1251
methoddef_define = ''
1252
1252
1253
- if f .kind == METHOD_NEW :
1253
+ if f .kind is METHOD_NEW :
1254
1254
parser_prototype = parser_prototype_keyword
1255
1255
else :
1256
1256
return_value_declaration = "int return_value = -1;"
@@ -1475,7 +1475,7 @@ def render_function(
1475
1475
last_group = 0
1476
1476
first_optional = len (selfless )
1477
1477
positional = selfless and selfless [- 1 ].is_positional_only ()
1478
- new_or_init = f .kind in ( METHOD_NEW , METHOD_INIT )
1478
+ new_or_init = f .kind . new_or_init
1479
1479
has_option_groups = False
1480
1480
1481
1481
# offset i by -1 because first_optional needs to ignore self
@@ -2441,9 +2441,28 @@ def __repr__(self) -> str:
2441
2441
""" .strip ().split ())
2442
2442
2443
2443
2444
- INVALID , CALLABLE , STATIC_METHOD , CLASS_METHOD , METHOD_INIT , METHOD_NEW = """
2445
- INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
2446
- """ .replace ("," , "" ).strip ().split ()
2444
+ class FunctionKind (enum .Enum ):
2445
+ INVALID = enum .auto ()
2446
+ CALLABLE = enum .auto ()
2447
+ STATIC_METHOD = enum .auto ()
2448
+ CLASS_METHOD = enum .auto ()
2449
+ METHOD_INIT = enum .auto ()
2450
+ METHOD_NEW = enum .auto ()
2451
+
2452
+ @functools .cached_property
2453
+ def new_or_init (self ) -> bool :
2454
+ return self in {FunctionKind .METHOD_INIT , FunctionKind .METHOD_NEW }
2455
+
2456
+ def __repr__ (self ) -> str :
2457
+ return f"<FunctionKind.{ self .name } >"
2458
+
2459
+
2460
+ INVALID : Final = FunctionKind .INVALID
2461
+ CALLABLE : Final = FunctionKind .CALLABLE
2462
+ STATIC_METHOD : Final = FunctionKind .STATIC_METHOD
2463
+ CLASS_METHOD : Final = FunctionKind .CLASS_METHOD
2464
+ METHOD_INIT : Final = FunctionKind .METHOD_INIT
2465
+ METHOD_NEW : Final = FunctionKind .METHOD_NEW
2447
2466
2448
2467
ParamDict = dict [str , "Parameter" ]
2449
2468
ReturnConverterType = Callable [..., "CReturnConverter" ]
@@ -2471,7 +2490,7 @@ class Function:
2471
2490
return_converter : CReturnConverter
2472
2491
return_annotation : object = inspect .Signature .empty
2473
2492
docstring : str = ''
2474
- kind : str = CALLABLE
2493
+ kind : FunctionKind = CALLABLE
2475
2494
coexist : bool = False
2476
2495
# docstring_only means "don't generate a machine-readable
2477
2496
# signature, just a normal docstring". it's True for
@@ -2497,15 +2516,16 @@ def render_parameters(self) -> list[Parameter]:
2497
2516
2498
2517
@property
2499
2518
def methoddef_flags (self ) -> str | None :
2500
- if self .kind in ( METHOD_INIT , METHOD_NEW ) :
2519
+ if self .kind . new_or_init :
2501
2520
return None
2502
2521
flags = []
2503
- if self .kind == CLASS_METHOD :
2504
- flags .append ('METH_CLASS' )
2505
- elif self .kind == STATIC_METHOD :
2506
- flags .append ('METH_STATIC' )
2507
- else :
2508
- assert self .kind == CALLABLE , "unknown kind: " + repr (self .kind )
2522
+ match self .kind :
2523
+ case FunctionKind .CLASS_METHOD :
2524
+ flags .append ('METH_CLASS' )
2525
+ case FunctionKind .STATIC_METHOD :
2526
+ flags .append ('METH_STATIC' )
2527
+ case _ as kind :
2528
+ assert kind is FunctionKind .CALLABLE , f"unknown kind: { kind !r} "
2509
2529
if self .coexist :
2510
2530
flags .append ('METH_COEXIST' )
2511
2531
return '|' .join (flags )
@@ -3888,7 +3908,7 @@ def correct_name_for_self(
3888
3908
if f .cls :
3889
3909
return "PyObject *" , "self"
3890
3910
return "PyObject *" , "module"
3891
- if f .kind == STATIC_METHOD :
3911
+ if f .kind is STATIC_METHOD :
3892
3912
return "void *" , "null"
3893
3913
if f .kind in (CLASS_METHOD , METHOD_NEW ):
3894
3914
return "PyTypeObject *" , "type"
@@ -3921,9 +3941,8 @@ def pre_render(self):
3921
3941
self .type = self .specified_type or self .type or default_type
3922
3942
3923
3943
kind = self .function .kind
3924
- new_or_init = kind in (METHOD_NEW , METHOD_INIT )
3925
3944
3926
- if ( kind == STATIC_METHOD ) or new_or_init :
3945
+ if kind is STATIC_METHOD or kind . new_or_init :
3927
3946
self .show_in_signature = False
3928
3947
3929
3948
# tp_new (METHOD_NEW) functions are of type newfunc:
@@ -3973,7 +3992,7 @@ def render(self, parameter, data):
3973
3992
parameter is a clinic.Parameter instance.
3974
3993
data is a CRenderData instance.
3975
3994
"""
3976
- if self .function .kind == STATIC_METHOD :
3995
+ if self .function .kind is STATIC_METHOD :
3977
3996
return
3978
3997
3979
3998
self ._render_self (parameter , data )
@@ -3992,8 +4011,8 @@ def set_template_dict(self, template_dict):
3992
4011
kind = self .function .kind
3993
4012
cls = self .function .cls
3994
4013
3995
- if (( kind in ( METHOD_NEW , METHOD_INIT )) and cls and cls .typedef ) :
3996
- if kind == METHOD_NEW :
4014
+ if kind . new_or_init and cls and cls .typedef :
4015
+ if kind is METHOD_NEW :
3997
4016
type_check = (
3998
4017
'({0} == base_tp || {0}->tp_init == base_tp->tp_init)'
3999
4018
).format (self .name )
@@ -4337,7 +4356,7 @@ class DSLParser:
4337
4356
parameter_state : int
4338
4357
seen_positional_with_default : bool
4339
4358
indent : IndentStack
4340
- kind : str
4359
+ kind : FunctionKind
4341
4360
coexist : bool
4342
4361
parameter_continuation : str
4343
4362
preserve_output : bool
@@ -4626,7 +4645,7 @@ def state_modulename_name(self, line: str | None) -> None:
4626
4645
function_name = fields .pop ()
4627
4646
module , cls = self .clinic ._module_and_class (fields )
4628
4647
4629
- if not (existing_function .kind == self .kind and existing_function .coexist == self .coexist ):
4648
+ if not (existing_function .kind is self .kind and existing_function .coexist == self .coexist ):
4630
4649
fail ("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)" )
4631
4650
function = existing_function .copy (
4632
4651
name = function_name , full_name = full_name , module = module ,
@@ -4679,11 +4698,11 @@ def state_modulename_name(self, line: str | None) -> None:
4679
4698
fail (f"{ fields [- 1 ]} is a special method and cannot be converted to Argument Clinic! (Yet.)" )
4680
4699
4681
4700
if fields [- 1 ] == '__new__' :
4682
- if (self .kind != CLASS_METHOD ) or (not cls ):
4701
+ if (self .kind is not CLASS_METHOD ) or (not cls ):
4683
4702
fail ("__new__ must be a class method!" )
4684
4703
self .kind = METHOD_NEW
4685
4704
elif fields [- 1 ] == '__init__' :
4686
- if (self .kind != CALLABLE ) or (not cls ):
4705
+ if (self .kind is not CALLABLE ) or (not cls ):
4687
4706
fail ("__init__ must be a normal method, not a class or static method!" )
4688
4707
self .kind = METHOD_INIT
4689
4708
if not return_converter :
@@ -5203,7 +5222,7 @@ def state_function_docstring(self, line):
5203
5222
def format_docstring (self ):
5204
5223
f = self .function
5205
5224
5206
- new_or_init = f .kind in ( METHOD_NEW , METHOD_INIT )
5225
+ new_or_init = f .kind . new_or_init
5207
5226
if new_or_init and not f .docstring :
5208
5227
# don't render a docstring at all, no signature, nothing.
5209
5228
return f .docstring
0 commit comments