Skip to content

Commit

Permalink
add 2to3 script to migrate (some) PyQt signal/slots to new style
Browse files Browse the repository at this point in the history
  • Loading branch information
jef-n committed Feb 10, 2016
1 parent d11c689 commit 7128a35
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 6 deletions.
Empty file added scripts/qgis_fixes/__init__.py
Empty file.
24 changes: 18 additions & 6 deletions scripts/qgis_fixes/fix_pyqt.py
Expand Up @@ -297,6 +297,8 @@
"QPoint",
"QPointF",
"QDirIterator",
]),
(None, [
"SIGNAL",
"SLOT",
]),
Expand Down Expand Up @@ -397,19 +399,21 @@ def transform_member(self, node, results):
pref = mod_member.prefix
member = results.get("member")

missing = False

# Simple case with only a single member being imported
if member:
# this may be a list of length one, or just a node
if isinstance(member, list):
member = member[0]
new_name = None
new_name = ''
for change in MAPPING[mod_member.value]:
if member.value in change[1]:
new_name = change[0]
break
if new_name:
mod_member.replace(Name(new_name, prefix=pref))
else:
elif new_name == '':
self.cannot_convert(node, "This is an invalid module element")

# Multiple members being imported
Expand All @@ -430,14 +434,16 @@ def transform_member(self, node, results):
found = False
for change in MAPPING[mod_member.value]:
if member_name in change[1]:
if change[0] not in mod_dict:
modules.append(change[0])
mod_dict.setdefault(change[0], []).append(member)
if change[0] is not None:
if change[0] not in mod_dict:
modules.append(change[0])
mod_dict.setdefault(change[0], []).append(member)
found = True
if not found:
f = open("/tmp/missing", "a+")
f.write("member %s of %s not found\n" % (member_name, mod_member.value))
f.close()
missing = True

new_nodes = []
indentation = find_indentation(node)
Expand All @@ -450,6 +456,7 @@ def handle_name(name, prefix):
name.children[2].clone()]
return [Node(syms.import_as_name, kids)]
return [Name(name.value, prefix=prefix)]

for module in modules:
elts = mod_dict[module]
names = []
Expand All @@ -462,13 +469,18 @@ def handle_name(name, prefix):
new.prefix = indentation
new_nodes.append(new)
first = False

if new_nodes:
nodes = []
for new_node in new_nodes[:-1]:
nodes.extend([new_node, Newline()])
nodes.append(new_nodes[-1])

if node.prefix:
nodes[0].prefix = node.prefix

node.replace(nodes)
else:
elif missing:
self.cannot_convert(node, "All module elements are invalid")

def transform_dot(self, node, results):
Expand Down
73 changes: 73 additions & 0 deletions scripts/qgis_fixes/fix_signals.py
@@ -0,0 +1,73 @@
"""Migrate signals from old style to new style
"""
# Author: Juergen E. Fischer

# .connect( sender, signal, receiver, slot )

# Local imports
from lib2to3 import fixer_base, pytree
from lib2to3.fixer_util import Call, Name, Attr, ArgList, Node, syms

import re


class FixSignals(fixer_base.BaseFix):
PATTERN = """
(
power<
any trailer< '.' method=('connect'|'disconnect') >
trailer<
'('
arglist<
sender=any ','
power< 'SIGNAL' trailer< '(' signal=any ')' > > ','
slot=any
>
')'
>
>
|
power<
emitter=any trailer< '.' 'emit' >
trailer<
'('
args=arglist<
power< 'SIGNAL' trailer< '(' signal=any ')' > >
( ',' any )*
>
')'
>
>
)
"""

# def match(self, node):
# res = super(FixSignals, self).match( node )
# r = repr(node)
# if "emit" in r:
# print "yes" if res else "no", ": ", r
# return res

def transform(self, node, results):
signal = results.get("signal").value
signal = re.sub('^["\']([^(]+)(?:\(.*\))?["\']$', '\\1', signal)

if 'emitter' in results:
emitter = results.get("emitter").clone()
emitter.prefix = node.prefix
args = results.get("args").clone()
args.children = args.children[2:]
if args.children:
args.children[0].prefix = ''
res = Node(syms.power, [emitter, Name('.'), Name(signal), Name('.'), Name('emit')] + [ArgList([args])])
else:
sender = results.get("sender").clone()
method = results.get("method")
if isinstance(method, list):
method = method[0]
method = method.clone()
sender.prefix = node.prefix
slot = results.get("slot").clone()
slot.prefix = ""
res = Node(syms.power, [sender, Name('.'), Name(signal), Name('.'), method] + [ArgList([slot])])
return res

1 comment on commit 7128a35

@nyalldawson
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

FYI for the c++ code we can use clazy to do a similar automatic port.

Please sign in to comment.