2020import re
2121import sys
2222from pathlib import Path
23+ from typing import Optional
2324
2425
2526def qt_for_binding (binding ):
@@ -38,7 +39,7 @@ def qt_for_binding(binding):
3839
3940
4041class QtEnumConverter :
41- DEFAULT_IGNORED = ".tox,.eggs,build"
42+ DEFAULT_IGNORED = ".tox,.eggs,build,dist "
4243
4344 def __init__ (self , verbosity = 0 , ignored : str = DEFAULT_IGNORED ):
4445 self .ignored = ignored .split ("," )
@@ -52,6 +53,7 @@ def __init__(self, verbosity=0, ignored: str = DEFAULT_IGNORED):
5253 # The mapping of short to fully qualified enum names. Used to
5354 # update python scripts.
5455 self .enum_map : dict [str , str ] = {}
56+ self .partial_enum : Optional [re .Pattern ] = None
5557 # Module level view of all the enums also used to check for naming
5658 # conflicts where the short name maps to multiple long names.
5759 self .enum_module : dict [str , dict [str , list [str ]]] = {}
@@ -148,7 +150,45 @@ def convert_enums_in_file(self, filepath: Path, root: Path, dry_run: bool) -> in
148150 f .write (content )
149151 return changes
150152
151- def convert_all (self , directory : Path , dry_run : bool ) -> int :
153+ def find_partials (self , filepath : Path , root : Path ) -> int :
154+ """Find and report potential partial Enum uses
155+
156+ We can't automatically replace them as this has a high likelihood of
157+ false positives.
158+ """
159+ if not self .enum_map :
160+ self .enums_for_qt_py ()
161+
162+ if not self .partial_enum :
163+ enums = {v .split ('.' )[- 1 ] for v in self .enum_map .values ()}
164+ self .partial_enum = re .compile (fr"\.({ '|' .join (enums )} )(?!\w)" )
165+
166+ # Read the content
167+ with filepath .open ('r' , encoding = 'utf-8' , newline = '\n ' , errors = 'replace' ) as f :
168+ content = f .readlines ()
169+
170+ changes = 0
171+ relative = filepath .relative_to (root )
172+ for ln , line in enumerate (content ):
173+ clean_line = line .rstrip ()
174+ matches = set ()
175+ for v in self .enum_map .values ():
176+ clean_line = clean_line .replace (v , "" )
177+
178+ for match in self .partial_enum .findall (clean_line ):
179+ matches .add (match )
180+ if matches :
181+ if self .verbosity >= 0 :
182+ print (
183+ f'File: "{ relative } ", line:{ ln + 1 } , for { ", " .join (matches )} '
184+ )
185+ if self .verbosity >= 1 :
186+ print (f' { line .strip ()} ' )
187+ changes += 1
188+
189+ return changes
190+
191+ def convert_all (self , directory : Path , dry_run : bool , partial : bool = False ) -> int :
152192 """Search and replace all enums."""
153193 ignored = [directory / i for i in self .ignored ]
154194 changes = 0
@@ -174,7 +214,10 @@ def convert_all(self, directory: Path, dry_run: bool) -> int:
174214 continue
175215 if self .verbosity >= 2 :
176216 print (f"Checking: { filepath } " )
177- changes += self .convert_enums_in_file (filepath , directory , dry_run )
217+ if partial :
218+ changes += self .find_partials (filepath , directory )
219+ else :
220+ changes += self .convert_enums_in_file (filepath , directory , dry_run )
178221
179222 return changes
180223
@@ -249,13 +292,27 @@ def parse_args():
249292 "have duplicate names on the same class causing ambiguity with short "
250293 "names. dups requires PySide6 and the others require PySide2 installed." ,
251294 )
295+ parser .add_argument (
296+ "--partial" ,
297+ action = "store_true" ,
298+ help = "Report any potential enum uses that can not be automatically fixed. "
299+ "This can happen if the code accesses enums from the instance instead of "
300+ "directly from the class name." ,
301+ )
252302 parser .add_argument (
253303 '-v' ,
254304 '--verbosity' ,
255305 action = 'count' ,
256306 default = 0 ,
257307 help = "Increase the verbosity of the output." ,
258308 )
309+ parser .add_argument (
310+ '-q' ,
311+ '--quiet' ,
312+ action = "count" ,
313+ default = 0 ,
314+ help = "Decrease the verbosity of the output." ,
315+ )
259316 parser .add_argument (
260317 '--check' ,
261318 action = 'store_true' ,
@@ -282,6 +339,9 @@ def add_binding_info(data, qt):
282339if __name__ == "__main__" :
283340 args = parse_args ()
284341
342+ # Merge the quiet and verbosity arguments
343+ args .verbosity -= args .quiet
344+
285345 if args .show == "dups" :
286346 # Show duplicate enum short names found in PySide6
287347 checker = DuplicateEnums ()
@@ -303,10 +363,14 @@ def add_binding_info(data, qt):
303363 print (json .dumps (mappings , indent = 4 , sort_keys = True ))
304364 else :
305365 # Search .py files and update to fully qualified enum names
306- changes = mapper .convert_all (args .target , dry_run = not args .write )
366+ changes = mapper .convert_all (
367+ args .target , dry_run = not args .write , partial = args .partial
368+ )
307369
308370 # Report the number of enum changes
309- if args .write :
371+ if args .partial :
372+ print (f"{ changes } partial enums found." )
373+ elif args .write :
310374 print (f"{ changes } enums changed." )
311375 else :
312376 print (f"{ changes } enums require changes." )
0 commit comments