@@ -807,7 +807,7 @@ def output_templates(self, f):
807807 default_return_converter = (not f .return_converter or
808808 f .return_converter .type == 'PyObject *' )
809809
810- new_or_init = f .kind in ( METHOD_NEW , METHOD_INIT )
810+ new_or_init = f .kind . new_or_init
811811
812812 vararg = NO_VARARG
813813 pos_only = min_pos = max_pos = min_kw_only = pseudo_args = 0
@@ -1250,7 +1250,7 @@ def parser_body(
12501250 if new_or_init :
12511251 methoddef_define = ''
12521252
1253- if f .kind == METHOD_NEW :
1253+ if f .kind is METHOD_NEW :
12541254 parser_prototype = parser_prototype_keyword
12551255 else :
12561256 return_value_declaration = "int return_value = -1;"
@@ -1475,7 +1475,7 @@ def render_function(
14751475 last_group = 0
14761476 first_optional = len (selfless )
14771477 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
14791479 has_option_groups = False
14801480
14811481 # offset i by -1 because first_optional needs to ignore self
@@ -2441,9 +2441,28 @@ def __repr__(self) -> str:
24412441""" .strip ().split ())
24422442
24432443
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
24472466
24482467ParamDict = dict [str , "Parameter" ]
24492468ReturnConverterType = Callable [..., "CReturnConverter" ]
@@ -2471,7 +2490,7 @@ class Function:
24712490 return_converter : CReturnConverter
24722491 return_annotation : object = inspect .Signature .empty
24732492 docstring : str = ''
2474- kind : str = CALLABLE
2493+ kind : FunctionKind = CALLABLE
24752494 coexist : bool = False
24762495 # docstring_only means "don't generate a machine-readable
24772496 # signature, just a normal docstring". it's True for
@@ -2497,15 +2516,16 @@ def render_parameters(self) -> list[Parameter]:
24972516
24982517 @property
24992518 def methoddef_flags (self ) -> str | None :
2500- if self .kind in ( METHOD_INIT , METHOD_NEW ) :
2519+ if self .kind . new_or_init :
25012520 return None
25022521 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} "
25092529 if self .coexist :
25102530 flags .append ('METH_COEXIST' )
25112531 return '|' .join (flags )
@@ -3888,7 +3908,7 @@ def correct_name_for_self(
38883908 if f .cls :
38893909 return "PyObject *" , "self"
38903910 return "PyObject *" , "module"
3891- if f .kind == STATIC_METHOD :
3911+ if f .kind is STATIC_METHOD :
38923912 return "void *" , "null"
38933913 if f .kind in (CLASS_METHOD , METHOD_NEW ):
38943914 return "PyTypeObject *" , "type"
@@ -3921,9 +3941,8 @@ def pre_render(self):
39213941 self .type = self .specified_type or self .type or default_type
39223942
39233943 kind = self .function .kind
3924- new_or_init = kind in (METHOD_NEW , METHOD_INIT )
39253944
3926- if ( kind == STATIC_METHOD ) or new_or_init :
3945+ if kind is STATIC_METHOD or kind . new_or_init :
39273946 self .show_in_signature = False
39283947
39293948 # tp_new (METHOD_NEW) functions are of type newfunc:
@@ -3973,7 +3992,7 @@ def render(self, parameter, data):
39733992 parameter is a clinic.Parameter instance.
39743993 data is a CRenderData instance.
39753994 """
3976- if self .function .kind == STATIC_METHOD :
3995+ if self .function .kind is STATIC_METHOD :
39773996 return
39783997
39793998 self ._render_self (parameter , data )
@@ -3992,8 +4011,8 @@ def set_template_dict(self, template_dict):
39924011 kind = self .function .kind
39934012 cls = self .function .cls
39944013
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 :
39974016 type_check = (
39984017 '({0} == base_tp || {0}->tp_init == base_tp->tp_init)'
39994018 ).format (self .name )
@@ -4337,7 +4356,7 @@ class DSLParser:
43374356 parameter_state : int
43384357 seen_positional_with_default : bool
43394358 indent : IndentStack
4340- kind : str
4359+ kind : FunctionKind
43414360 coexist : bool
43424361 parameter_continuation : str
43434362 preserve_output : bool
@@ -4626,7 +4645,7 @@ def state_modulename_name(self, line: str | None) -> None:
46264645 function_name = fields .pop ()
46274646 module , cls = self .clinic ._module_and_class (fields )
46284647
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 ):
46304649 fail ("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)" )
46314650 function = existing_function .copy (
46324651 name = function_name , full_name = full_name , module = module ,
@@ -4679,11 +4698,11 @@ def state_modulename_name(self, line: str | None) -> None:
46794698 fail (f"{ fields [- 1 ]} is a special method and cannot be converted to Argument Clinic! (Yet.)" )
46804699
46814700 if fields [- 1 ] == '__new__' :
4682- if (self .kind != CLASS_METHOD ) or (not cls ):
4701+ if (self .kind is not CLASS_METHOD ) or (not cls ):
46834702 fail ("__new__ must be a class method!" )
46844703 self .kind = METHOD_NEW
46854704 elif fields [- 1 ] == '__init__' :
4686- if (self .kind != CALLABLE ) or (not cls ):
4705+ if (self .kind is not CALLABLE ) or (not cls ):
46874706 fail ("__init__ must be a normal method, not a class or static method!" )
46884707 self .kind = METHOD_INIT
46894708 if not return_converter :
@@ -5203,7 +5222,7 @@ def state_function_docstring(self, line):
52035222 def format_docstring (self ):
52045223 f = self .function
52055224
5206- new_or_init = f .kind in ( METHOD_NEW , METHOD_INIT )
5225+ new_or_init = f .kind . new_or_init
52075226 if new_or_init and not f .docstring :
52085227 # don't render a docstring at all, no signature, nothing.
52095228 return f .docstring
0 commit comments