@@ -2439,6 +2439,8 @@ def __repr__(self) -> str:
2439
2439
ParamDict = dict [str , "Parameter" ]
2440
2440
ReturnConverterType = Callable [..., "CReturnConverter" ]
2441
2441
2442
+
2443
+ @dc .dataclass (repr = False )
2442
2444
class Function :
2443
2445
"""
2444
2446
Mutable duck type for inspect.Function.
@@ -2450,49 +2452,34 @@ class Function:
2450
2452
It will always be true that
2451
2453
(not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2452
2454
"""
2455
+ parameters : ParamDict = dc .field (default_factory = dict )
2456
+ _ : dc .KW_ONLY
2457
+ name : str
2458
+ module : Module
2459
+ cls : Class | None = None
2460
+ c_basename : str | None = None
2461
+ full_name : str | None = None
2462
+ return_converter : CReturnConverter
2463
+ return_annotation : object = inspect .Signature .empty
2464
+ docstring : str = ''
2465
+ kind : str = CALLABLE
2466
+ coexist : bool = False
2467
+ # docstring_only means "don't generate a machine-readable
2468
+ # signature, just a normal docstring". it's True for
2469
+ # functions with optional groups because we can't represent
2470
+ # those accurately with inspect.Signature in 3.4.
2471
+ docstring_only : bool = False
2453
2472
2454
- def __init__ (
2455
- self ,
2456
- parameters : ParamDict | None = None ,
2457
- * ,
2458
- name : str ,
2459
- module : Module ,
2460
- cls : Class | None = None ,
2461
- c_basename : str | None = None ,
2462
- full_name : str | None = None ,
2463
- return_converter : CReturnConverter ,
2464
- return_annotation = inspect .Signature .empty ,
2465
- docstring : str | None = None ,
2466
- kind : str = CALLABLE ,
2467
- coexist : bool = False ,
2468
- docstring_only : bool = False
2469
- ) -> None :
2470
- self .parameters = parameters or {}
2471
- self .return_annotation = return_annotation
2472
- self .name = name
2473
- self .full_name = full_name
2474
- self .module = module
2475
- self .cls = cls
2476
- self .parent = cls or module
2477
- self .c_basename = c_basename
2478
- self .return_converter = return_converter
2479
- self .docstring = docstring or ''
2480
- self .kind = kind
2481
- self .coexist = coexist
2473
+ def __post_init__ (self ) -> None :
2474
+ self .parent : Class | Module = self .cls or self .module
2482
2475
self .self_converter : self_converter | None = None
2483
- # docstring_only means "don't generate a machine-readable
2484
- # signature, just a normal docstring". it's True for
2485
- # functions with optional groups because we can't represent
2486
- # those accurately with inspect.Signature in 3.4.
2487
- self .docstring_only = docstring_only
2488
-
2489
- self .rendered_parameters = None
2476
+ self .__render_parameters__ : list [Parameter ] | None = None
2490
2477
2491
- __render_parameters__ = None
2492
2478
@property
2493
- def render_parameters (self ):
2479
+ def render_parameters (self ) -> list [ Parameter ] :
2494
2480
if not self .__render_parameters__ :
2495
- self .__render_parameters__ = l = []
2481
+ l : list [Parameter ] = []
2482
+ self .__render_parameters__ = l
2496
2483
for p in self .parameters .values ():
2497
2484
p = p .copy ()
2498
2485
p .converter .pre_render ()
@@ -2517,49 +2504,30 @@ def methoddef_flags(self) -> str | None:
2517
2504
def __repr__ (self ) -> str :
2518
2505
return '<clinic.Function ' + self .name + '>'
2519
2506
2520
- def copy (self , ** overrides ) -> "Function" :
2521
- kwargs = {
2522
- 'name' : self .name , 'module' : self .module , 'parameters' : self .parameters ,
2523
- 'cls' : self .cls , 'c_basename' : self .c_basename ,
2524
- 'full_name' : self .full_name ,
2525
- 'return_converter' : self .return_converter , 'return_annotation' : self .return_annotation ,
2526
- 'docstring' : self .docstring , 'kind' : self .kind , 'coexist' : self .coexist ,
2527
- 'docstring_only' : self .docstring_only ,
2528
- }
2529
- kwargs .update (overrides )
2530
- f = Function (** kwargs )
2507
+ def copy (self , ** overrides : Any ) -> Function :
2508
+ f = dc .replace (self , ** overrides )
2531
2509
f .parameters = {
2532
2510
name : value .copy (function = f )
2533
2511
for name , value in f .parameters .items ()
2534
2512
}
2535
2513
return f
2536
2514
2537
2515
2516
+ @dc .dataclass (repr = False , slots = True )
2538
2517
class Parameter :
2539
2518
"""
2540
2519
Mutable duck type of inspect.Parameter.
2541
2520
"""
2542
-
2543
- def __init__ (
2544
- self ,
2545
- name : str ,
2546
- kind : inspect ._ParameterKind ,
2547
- * ,
2548
- default = inspect .Parameter .empty ,
2549
- function : Function ,
2550
- converter : "CConverter" ,
2551
- annotation = inspect .Parameter .empty ,
2552
- docstring : str | None = None ,
2553
- group : int = 0
2554
- ) -> None :
2555
- self .name = name
2556
- self .kind = kind
2557
- self .default = default
2558
- self .function = function
2559
- self .converter = converter
2560
- self .annotation = annotation
2561
- self .docstring = docstring or ''
2562
- self .group = group
2521
+ name : str
2522
+ kind : inspect ._ParameterKind
2523
+ _ : dc .KW_ONLY
2524
+ default : object = inspect .Parameter .empty
2525
+ function : Function
2526
+ converter : CConverter
2527
+ annotation : object = inspect .Parameter .empty
2528
+ docstring : str = ''
2529
+ group : int = 0
2530
+ right_bracket_count : int = dc .field (init = False , default = 0 )
2563
2531
2564
2532
def __repr__ (self ) -> str :
2565
2533
return '<clinic.Parameter ' + self .name + '>'
@@ -2576,18 +2544,19 @@ def is_vararg(self) -> bool:
2576
2544
def is_optional (self ) -> bool :
2577
2545
return not self .is_vararg () and (self .default is not unspecified )
2578
2546
2579
- def copy (self , ** overrides ) -> "Parameter" :
2580
- kwargs = {
2581
- 'name' : self .name , 'kind' : self .kind , 'default' :self .default ,
2582
- 'function' : self .function , 'converter' : self .converter , 'annotation' : self .annotation ,
2583
- 'docstring' : self .docstring , 'group' : self .group ,
2584
- }
2585
- kwargs .update (overrides )
2586
- if 'converter' not in overrides :
2547
+ def copy (
2548
+ self ,
2549
+ / ,
2550
+ * ,
2551
+ converter : CConverter | None = None ,
2552
+ function : Function | None = None ,
2553
+ ** overrides : Any
2554
+ ) -> Parameter :
2555
+ function = function or self .function
2556
+ if not converter :
2587
2557
converter = copy .copy (self .converter )
2588
- converter .function = kwargs ['function' ]
2589
- kwargs ['converter' ] = converter
2590
- return Parameter (** kwargs )
2558
+ converter .function = function
2559
+ return dc .replace (self , ** overrides , function = function , converter = converter )
2591
2560
2592
2561
def get_displayname (self , i : int ) -> str :
2593
2562
if i == 0 :
@@ -2761,7 +2730,7 @@ def __init__(self,
2761
2730
# Positional args:
2762
2731
name : str ,
2763
2732
py_name : str ,
2764
- function ,
2733
+ function : Function ,
2765
2734
default : object = unspecified ,
2766
2735
* , # Keyword only args:
2767
2736
c_default : str | None = None ,
@@ -2800,7 +2769,9 @@ def __init__(self,
2800
2769
# about the function in the init.
2801
2770
# (that breaks if we get cloned.)
2802
2771
# so after this change we will noisily fail.
2803
- self .function = LandMine ("Don't access members of self.function inside converter_init!" )
2772
+ self .function : Function | LandMine = LandMine (
2773
+ "Don't access members of self.function inside converter_init!"
2774
+ )
2804
2775
self .converter_init (** kwargs )
2805
2776
self .function = function
2806
2777
@@ -2810,7 +2781,7 @@ def converter_init(self):
2810
2781
def is_optional (self ) -> bool :
2811
2782
return (self .default is not unspecified )
2812
2783
2813
- def _render_self (self , parameter : str , data : CRenderData ) -> None :
2784
+ def _render_self (self , parameter : Parameter , data : CRenderData ) -> None :
2814
2785
self .parameter = parameter
2815
2786
name = self .parser_name
2816
2787
@@ -2870,7 +2841,7 @@ def _render_non_self(self, parameter, data):
2870
2841
if cleanup :
2871
2842
data .cleanup .append ('/* Cleanup for ' + name + ' */\n ' + cleanup .rstrip () + "\n " )
2872
2843
2873
- def render (self , parameter : str , data : CRenderData ) -> None :
2844
+ def render (self , parameter : Parameter , data : CRenderData ) -> None :
2874
2845
"""
2875
2846
parameter is a clinic.Parameter instance.
2876
2847
data is a CRenderData instance.
@@ -5246,7 +5217,7 @@ def format_docstring(self):
5246
5217
assert isinstance (parameters [0 ].converter , self_converter )
5247
5218
# self is always positional-only.
5248
5219
assert parameters [0 ].is_positional_only ()
5249
- parameters [0 ].right_bracket_count = 0
5220
+ assert parameters [0 ].right_bracket_count = = 0
5250
5221
positional_only = True
5251
5222
for p in parameters [1 :]:
5252
5223
if not p .is_positional_only ():
0 commit comments