Source

pida-main / tools / rewrite_actions_code.py

#!/usr/bin/python
from __future__ import print_function
import sys


class ActionCall(object):
    def __init__(self, name, type, tooltip, doc, stock, callback=None, accel=None, glob=False):
        self.name = name
        self.type = type
        self.tooltip = tooltip
        self.doc = doc
        self.stock = stock
        self.callback = callback and callback[5:] # strip self.
        self.accel = accel
        self.glob = bool(glob)

    @property
    def needs_rename(self):
        return '-' in self.name

    @property
    def new_name(self):
        return self.name.replace('-','_')

    @property
    def needs_handler_rename(self):
        return self.callback is not None and 'on_' + self.new_name != self.callback


print('automated action rewrite of', sys.argv[1])
with open(sys.argv[1]) as fp:
    lines = list(fp)
old_lines = lines[:]


def findrange(lines, startcond, stopcond, pos=0, last=None, finalize=False):
    start = None
    for i in range(pos, last or len(lines)):
        line = lines[i]
        if start is None and startcond(line):
            start = i
            continue
        if start is not None and stopcond(line):
            end = i
            return start, end
    if finalize and start is not None:
        return start, last
    return None, None


def find_iter(lines, startcond, stopcond, pos=0, last=None):
    last = last or len(lines)
    pos, end = findrange(lines, startcond, stopcond, pos, last)
    while end is not None:
        yield pos, end
        pos, end = findrange(lines, startcond, stopcond, end, last, finalize=True)

def parse_action(lines):
    lines = [x.strip(' \n,') for x in lines]
    name = lines[0].strip('"\'')
    type = lines[1]
    tooltip = lines[2]
    doc = lines[3]
    stock = lines[4]
    if len(lines) > 5:
        callback = lines[5]
        if callback == 'None':
            callback = None
    else:
        callback = None
    return ActionCall(name, type, tooltip, doc, stock, callback,
                      # accel, global
                      *lines[6:])

start, end = findrange(lines,
    startcond = lambda line: '(ActionsConfig)' in line,
    stopcond = lambda line: line.startswith('class') or line[0] == '#',
)


print("actionsconfig:", start, end)

c_start, c_end = findrange(lines,
    startcond=lambda line: 'create_actions' in line,
    stopcond=lambda line: ' def ' in line,
    pos=start, last=end)

actions = []

renames = {}
print('actions:')
for a_start, a_end in find_iter(lines,
    startcond=lambda line:'create_action(' in line,
    stopcond=lambda line: line.strip() == ')',
    pos=c_start, last=c_end):
        action = parse_action(lines[a_start+1: a_end])
        print('  ', action.name, action.callback, end=' ')
        print('h' if action.needs_handler_rename else '', 'n' if action.needs_rename else '', sep='')
        actions.append(action)
        if action.needs_handler_rename:
            renames[action.callback] = action



print('methods:')
for m_start, m_end in find_iter(lines,
    startcond=lambda line: 'def' in line,
    stopcond=lambda line: 'def' in line,
    pos=start, last=end):
    funcdef = lines[m_start].strip()
    func_name = funcdef[4:].split('(')[0]
    if func_name in renames:
        print('  ', funcdef, '->', renames[func_name].name)
        lines[m_start] = lines[m_start].replace(
            func_name,
            'on_' + renames[func_name].new_name,
        )
    else:
        print('  ', funcdef)


new_action_lines = []
a = new_action_lines.append
a('\n')
a('    actions = [\n')

for action in actions:
    a('        %s(\'%s\',\n' % (action.type, action.new_name))
    a('            %s,\n' % action.tooltip)
    a('            %s,\n' % action.doc)
    a('            %s),\n' % action.stock)

a('    ]\n')
a('\n')

all_accels = [action for action in actions if action.accel is not None]
accels = [action for action in all_accels if not action.glob]

if accels:
    a('    accels = {\n')
    for action in accels:
            a('        \'%s\': %s,\n' % (action.name, action.accel) )
    a('    }\n')
    a('\n')

global_accels = [action for action in all_accels if action.glob]
if global_accels:
    a('    global_accels = {\n')
    for action in global_accels:
        if action.accel is not None and action.glob:
            a('        \'%s\': %s,\n' % (action.name, action.accel) )
    a('    }\n')
    a('\n')


lines[c_start:c_end] = new_action_lines


import difflib

print(''.join(difflib.unified_diff(old_lines, lines,
                                   fromfile='a/'+sys.argv[1],
                                   tofile='b/'+sys.argv[1],
                                  )))