@@ -121,6 +121,7 @@ def __init__(self):
121
121
self .doxy_inside_sip_run : int = 0
122
122
self .has_pushed_force_int : bool = False
123
123
self .attribute_docstrings = defaultdict (dict )
124
+ self .attribute_typehints = defaultdict (dict )
124
125
self .struct_docstrings = defaultdict (dict )
125
126
self .current_method_name : str = ""
126
127
self .static_methods = defaultdict (dict )
@@ -1335,16 +1336,22 @@ def convert_type(cpp_type: str) -> str:
1335
1336
"QString" : "str" ,
1336
1337
"void" : "None" ,
1337
1338
"qint64" : "int" ,
1339
+ "quint64" : "int" ,
1340
+ "qreal" : "float" ,
1338
1341
"unsigned long long" : "int" ,
1339
1342
"long long" : "int" ,
1340
1343
"qlonglong" : "int" ,
1344
+ "qgssize" : "int" ,
1341
1345
"long" : "int" ,
1342
1346
"QStringList" : "List[str]" ,
1343
1347
"QVariantList" : "List[object]" ,
1344
1348
"QVariantMap" : "Dict[str, object]" ,
1345
1349
"QVariant" : "object" ,
1346
1350
}
1347
1351
1352
+ cpp_type = cpp_type .replace ("static " , "" )
1353
+ cpp_type = cpp_type .replace ("const " , "" )
1354
+
1348
1355
# Handle templates
1349
1356
template_match = re .match (r"(\w+)\s*<\s*(.+)\s*>" , cpp_type )
1350
1357
if template_match :
@@ -2883,15 +2890,31 @@ def cpp_to_python_signature(cpp_function: str) -> str:
2883
2890
and CONTEXT .comment
2884
2891
):
2885
2892
attribute_name_match = re .match (
2886
- r"^.*?\s[*&]*(\w+);.*$" , CONTEXT .current_line
2893
+ r"^\s*(.*?)\s[*&]*(\w+);.*$" , CONTEXT .current_line
2894
+ )
2895
+ dbg_info (
2896
+ f"got member { attribute_name_match .group (2 )} of type { attribute_name_match .group (1 )} "
2887
2897
)
2888
2898
class_name = CONTEXT .current_fully_qualified_struct_name ()
2889
2899
dbg_info (
2890
- f"storing attribute docstring for { class_name } : { attribute_name_match .group (1 )} "
2900
+ f"storing attribute docstring for { class_name } : { attribute_name_match .group (2 )} "
2891
2901
)
2892
2902
CONTEXT .attribute_docstrings [class_name ][
2893
- attribute_name_match .group (1 )
2903
+ attribute_name_match .group (2 )
2894
2904
] = CONTEXT .comment
2905
+
2906
+ try :
2907
+ typehint = convert_type (attribute_name_match .group (1 ))
2908
+ except AssertionError :
2909
+ exit_with_error (
2910
+ f"Cannot convert c++ type { attribute_name_match .group (1 )} to Python type for member { attribute_name_match .group (2 )} . Ensure fully qualified class name is used"
2911
+ )
2912
+ dbg_info (
2913
+ f"storing attribute typehint { typehint } for { class_name } (was { attribute_name_match .group (1 )} )"
2914
+ )
2915
+ CONTEXT .attribute_typehints [class_name ][
2916
+ attribute_name_match .group (2 )
2917
+ ] = typehint
2895
2918
elif (
2896
2919
CONTEXT .current_fully_qualified_struct_name ()
2897
2920
and re .search (r"\s*struct " , CONTEXT .current_line )
@@ -3210,6 +3233,23 @@ def cpp_to_python_signature(cpp_function: str) -> str:
3210
3233
f"{ class_name } .__attribute_docs__ = { str (attribute_docstrings )} "
3211
3234
)
3212
3235
3236
+ for class_name , attribute_typehints in CONTEXT .attribute_typehints .items ():
3237
+ if not attribute_typehints :
3238
+ continue
3239
+
3240
+ annotations_str = "{"
3241
+ for attribute_name , typehint in attribute_typehints .items ():
3242
+ annotations_str += f"'{ attribute_name } ': "
3243
+ annotations_str += {"int" : "int" , "float" : "float" , "str" : "str" }.get (
3244
+ typehint , f"'{ typehint } '"
3245
+ )
3246
+ annotations_str += ", "
3247
+ annotations_str = annotations_str [:- 2 ] + "}"
3248
+
3249
+ class_additions [class_name ].append (
3250
+ f"{ class_name } .__annotations__ = { annotations_str } "
3251
+ )
3252
+
3213
3253
for class_name , static_methods in CONTEXT .static_methods .items ():
3214
3254
for method_name , is_static in static_methods .items ():
3215
3255
if not is_static :
0 commit comments