Skip to content

Instantly share code, notes, and snippets.

@julien-duponchelle
Created April 17, 2015 15:01
Show Gist options
  • Save julien-duponchelle/62e3a961dcd689376bdf to your computer and use it in GitHub Desktop.
Save julien-duponchelle/62e3a961dcd689376bdf to your computer and use it in GitHub Desktop.
QT4 to QT5 GNS3 migration
import os
import sys
import re
import inspect
from PyQt5 import QtWidgets
class FilePatcher:
def __init__(self, path):
self._path = path
self._line_number = 1
self._previous_line = None
self._line = None
self._parent_classes = []
self._qtwidgets_imported = False
def error(self, msg):
print("ERROR: {}:{} {}".format(self._path,self._line_number, msg))
sys.exit(1)
def info(self, msg , *args):
msg = msg + " ".join(args)
print("INFO: {}:{} {}".format(self._path,self._line_number, msg))
def patch(self):
out = ""
with open(self._path) as f:
previous_line = None
for self._line in f.readlines():
self.fix_object_inheritance()
self.get_parent_class()
if self._previous_line:
self.error_double_init()
self.fix_qt_widgets()
self.fix_init_with_self()
self.fix_super_with_argument()
self.fix_call_without_super()
self.error_import_missing()
self._line_number += 1
self._previous_line = self._line
out += self._line
with open(self._path, 'w+') as f:
f.write(out)
def get_parent_class(self):
"""Extract parent class to self._parent_classes var"""
if self._line.startswith("class "):
l = re.match(r".*\((.*)\):", self._line)
if l:
self._parent_classes = []
for cls in l.group(1).split(","):
self._parent_classes.append(cls.strip())
def fix_object_inheritance(self):
"""In Python3 you no longer need to inherit from object"""
if "(object):" in self._line:
self._line = re.sub(r"\(object\)", "", self._line)
def error_double_init(self):
"""
Detect double call to init and raise an error
"""
if ".__init__" in self._previous_line and ".__init__" in self._line:
self.error("Double init is no longer allowed")
def fix_super_with_argument(self):
"""
Thanks to Python 3 now we can call super() instead of super(MyClassParent)
"""
if re.match(r".*super\([^)].*", self._line):
self._line = re.sub(r"super\([^)]+\)", "super()", self._line)
self.info("Fix ", self._line.strip())
def fix_init_with_self(self):
"""
In some part of the code we have MyClassParent.__init__(self
Now we can use super().__init__
"""
if ".__init__(self" in self._line:
self._line = re.sub(r"([A-Z\.a-z0-9_-]+)\.__init__\(self,? ?", "super().__init__(", self._line)
def fix_call_without_super(self):
"""
We need to call parent with super instead of class name in order to avoid issues
"""
for cls in self._parent_classes:
m = re.match(r"(.*)({})\.([a-zA-Z]+)\((self, ? ?)(.*)".format(cls), self._line)
if m:
fixed = m.group(1) + "super()." + m.group(3) + "(" + m.group(5) + "\n"
self._line = fixed
def fix_qt_widgets(self):
"""
Replace QtGui by QtWidgets when require
"""
if self._line.startswith("from ") and "import" in self._line and "QtGui" in self._line and not "QtWidgets" in self._line:
self._line = self._line.strip() + ", QtWidgets\n"
if "QtGui." in self._line:
for name, obj in inspect.getmembers(QtWidgets):
self._line = self._line.replace("QtGui." + name, "QtWidgets." + name)
def error_import_missing(self):
"""
Check if we use QtWidgets without QtGui
"""
if "QtWidgets" in self._line:
if " import " in self._line:
self._qtwidgets_imported = True
else:
if self._qtwidgets_imported is False:
self.error("QtWidgets import missing")
for root, dirs, files in os.walk('gns3'):
for file in files:
if file.endswith('.py'):
FilePatcher(os.path.join(root, file)).patch()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment