22
22
_DEFAULT_TYPING_IMPORTS = (
23
23
'Any' ,
24
24
'Callable' ,
25
+ 'ClassVar' ,
25
26
'Dict' ,
26
27
'Iterable' ,
27
28
'Iterator' ,
@@ -243,7 +244,13 @@ def strip_or_import(typ: str, module: ModuleType, imports: List[str]) -> str:
243
244
return stripped_type
244
245
245
246
246
- def generate_c_property_stub (name : str , obj : object , output : List [str ], readonly : bool ,
247
+ def is_static_property (obj : object ) -> bool :
248
+ return type (obj ).__name__ == 'pybind11_static_property'
249
+
250
+
251
+ def generate_c_property_stub (name : str , obj : object ,
252
+ static_properties : List [str ],
253
+ properties : List [str ], readonly : bool ,
247
254
module : Optional [ModuleType ] = None ,
248
255
imports : Optional [List [str ]] = None ) -> None :
249
256
"""Generate property stub using introspection of 'obj'.
@@ -273,11 +280,17 @@ def infer_prop_type(docstr: Optional[str]) -> Optional[str]:
273
280
if module is not None and imports is not None :
274
281
inferred = strip_or_import (inferred , module , imports )
275
282
276
- output .append ('@property' )
277
- output .append ('def {}(self) -> {}: ...' .format (name , inferred ))
278
- if not readonly :
279
- output .append ('@{}.setter' .format (name ))
280
- output .append ('def {}(self, val: {}) -> None: ...' .format (name , inferred ))
283
+ if is_static_property (obj ):
284
+ trailing_comment = " # read-only" if readonly else ""
285
+ static_properties .append (
286
+ '{}: ClassVar[{}] = ...{}' .format (name , inferred , trailing_comment )
287
+ )
288
+ else : # regular property
289
+ properties .append ('@property' )
290
+ properties .append ('def {}(self) -> {}: ...' .format (name , inferred ))
291
+ if not readonly :
292
+ properties .append ('@{}.setter' .format (name ))
293
+ properties .append ('def {}(self, val: {}) -> None: ...' .format (name , inferred ))
281
294
282
295
283
296
def generate_c_type_stub (module : ModuleType ,
@@ -298,6 +311,7 @@ def generate_c_type_stub(module: ModuleType,
298
311
items = sorted (obj_dict .items (), key = lambda x : method_name_sort_key (x [0 ]))
299
312
methods = [] # type: List[str]
300
313
types = [] # type: List[str]
314
+ static_properties = [] # type: List[str]
301
315
properties = [] # type: List[str]
302
316
done = set () # type: Set[str]
303
317
for attr , value in items :
@@ -322,19 +336,19 @@ def generate_c_type_stub(module: ModuleType,
322
336
class_sigs = class_sigs )
323
337
elif is_c_property (value ):
324
338
done .add (attr )
325
- generate_c_property_stub (attr , value , properties , is_c_property_readonly (value ),
339
+ generate_c_property_stub (attr , value , static_properties , properties ,
340
+ is_c_property_readonly (value ),
326
341
module = module , imports = imports )
327
342
elif is_c_type (value ):
328
343
generate_c_type_stub (module , attr , value , types , imports = imports , sigs = sigs ,
329
344
class_sigs = class_sigs )
330
345
done .add (attr )
331
346
332
- variables = []
333
347
for attr , value in items :
334
348
if is_skipped_attribute (attr ):
335
349
continue
336
350
if attr not in done :
337
- variables .append ('%s: %s = ...' % (
351
+ static_properties .append ('%s: ClassVar[%s] = ...' % (
338
352
attr , strip_or_import (get_type_fullname (type (value )), module , imports )))
339
353
all_bases = obj .mro ()
340
354
if all_bases [- 1 ] is object :
@@ -361,21 +375,21 @@ def generate_c_type_stub(module: ModuleType,
361
375
)
362
376
else :
363
377
bases_str = ''
364
- if not methods and not variables and not properties and not types :
365
- output .append ('class %s%s: ...' % (class_name , bases_str ))
366
- else :
378
+ if types or static_properties or methods or properties :
367
379
output .append ('class %s%s:' % (class_name , bases_str ))
368
380
for line in types :
369
381
if output and output [- 1 ] and \
370
382
not output [- 1 ].startswith ('class' ) and line .startswith ('class' ):
371
383
output .append ('' )
372
384
output .append (' ' + line )
373
- for variable in variables :
374
- output .append (' %s' % variable )
375
- for method in methods :
376
- output .append (' %s' % method )
377
- for prop in properties :
378
- output .append (' %s' % prop )
385
+ for line in static_properties :
386
+ output .append (' %s' % line )
387
+ for line in methods :
388
+ output .append (' %s' % line )
389
+ for line in properties :
390
+ output .append (' %s' % line )
391
+ else :
392
+ output .append ('class %s%s: ...' % (class_name , bases_str ))
379
393
380
394
381
395
def get_type_fullname (typ : type ) -> str :
0 commit comments