I have a bunch of long pyqt scripts, in which the original author wrote code like this
from PyQt4.QtGui import *
from PyQt4.QtCore import *
...
Is there a smart or quick way to change the code to
from PyQt4 import QtGui,QtCore
...
and also prefix every pyqt class with module name? eg
change QDialog
to QtGui.QDialog
, with sublime editor or pycharm ? or any other editor?
I read about one can add custom fixers to 2to3 script, and repurpose that tool for this, but that doesn't seem a simple task. Or build ast tree and do the replace by yourself ( sounds more complex and maybe it is reinventing the wheel ). Or should I just write regex replace script and just parse all the .py files ? ( sounds unsafe )
edit: I read the original question, it seems my question is a subset of it, finally I used a hacky solution, since I knew the code I want to fix is pyqt.
bad_file = '/path/to/bad_file'
import re
from PyQt4 import QtCore,QtGui
QtCore_mappings = [x for x in dir(QtCore) if '_' not in x]
QtGui_mappings = [x for x in dir(QtGui) if '_' not in x]
mappings = {'QtCore':QtCore_mappings,'QtGui':QtGui_mappings }
cache={}
def find_class_long_name(c):
for k,v in mappings.iteritems():
if c in v:
return '%s.%s' % (k,c)
else:
return None
with open(bad_file) as f:
code = f.read()
all_classes = re.findall(r'\bQ[A-Z]\w*\b', code)
all_classes=set(all_classes)
for c in all_classes:
new_c = find_class_long_name(c)
if new_c:
print '%s ---> %s' % (c, new_c)
code=re.sub(r'\b%s\b' %c,new_c,code)
else:
print 'skipped:',c
# write code to new file
update 2: I think I can just replace the module import lines without changing the code
def find_module(c):
for k,v in mappings.iteritems():
if c in v:
return k
else:
return None
with open(bad_file) as f:
code = f.read()
# print code
all_classes = re.findall(r'\bQ[A-Z]\w*\b', code)
all_classes=set(all_classes)
for c in all_classes:
c_module = find_module(c)
if c_module:
cache[c_module].append(c)
else:
print 'skipped:',c
cmd = ''
for k,v in cache.iteritems():
if cache[k]:
cmd+='from %s import (%s)' % (k, ', '.join(sorted(cache[k])))
cmd+='\n'
print 'new import:\n'
print cmd