Blame common/scangobj-merge.py

Packit Service 963350
#!/usr/bin/python
Packit Service 963350
# -*- Mode: Python -*-
Packit Service 963350
# vi:si:et:sw=4:sts=4:ts=4
Packit Service 963350
Packit Service 963350
"""
Packit Service 963350
parse, merge and write gstdoc-scanobj files
Packit Service 963350
"""
Packit Service 963350
Packit Service 963350
from __future__ import print_function, unicode_literals
Packit Service 963350
Packit Service 963350
import codecs
Packit Service 963350
import os
Packit Service 963350
import sys
Packit Service 963350
Packit Service 963350
def debug(*args):
Packit Service 963350
    pass
Packit Service 963350
Packit Service 963350
# OrderedDict class based on
Packit Service 963350
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
Packit Service 963350
# Licensed under the Python License
Packit Service 963350
class OrderedDict(dict):
Packit Service 963350
    def __init__(self):
Packit Service 963350
        self._keys = []
Packit Service 963350
        dict.__init__(self)
Packit Service 963350
Packit Service 963350
    def __delitem__(self, key):
Packit Service 963350
        dict.__delitem__(self, key)
Packit Service 963350
        self._keys.remove(key)
Packit Service 963350
Packit Service 963350
    def __setitem__(self, key, item):
Packit Service 963350
        dict.__setitem__(self, key, item)
Packit Service 963350
        if key not in self._keys: self._keys.append(key)
Packit Service 963350
Packit Service 963350
    def clear(self):
Packit Service 963350
        dict.clear(self)
Packit Service 963350
        self._keys = []
Packit Service 963350
Packit Service 963350
    def copy(self):
Packit Service 963350
        dict = dict.copy(self)
Packit Service 963350
        dict._keys = self._keys[:]
Packit Service 963350
        return dict
Packit Service 963350
Packit Service 963350
    def items(self):
Packit Service 963350
        return zip(self._keys, self.values())
Packit Service 963350
Packit Service 963350
    def keys(self):
Packit Service 963350
        return self._keys
Packit Service 963350
Packit Service 963350
    def popitem(self):
Packit Service 963350
        try:
Packit Service 963350
            key = self._keys[-1]
Packit Service 963350
        except IndexError:
Packit Service 963350
            raise KeyError('dictionary is empty')
Packit Service 963350
Packit Service 963350
        val = self[key]
Packit Service 963350
        del self[key]
Packit Service 963350
Packit Service 963350
        return (key, val)
Packit Service 963350
Packit Service 963350
    def setdefault(self, key, failobj = None):
Packit Service 963350
        dict.setdefault(self, key, failobj)
Packit Service 963350
        if key not in self._keys: self._keys.append(key)
Packit Service 963350
Packit Service 963350
    def update(self, dict):
Packit Service 963350
        dict.update(self, dict)
Packit Service 963350
        for key in dict.keys():
Packit Service 963350
            if key not in self._keys: self._keys.append(key)
Packit Service 963350
Packit Service 963350
    def values(self):
Packit Service 963350
        return map(self.get, self._keys)
Packit Service 963350
Packit Service 963350
class Object:
Packit Service 963350
    def __init__(self, name):
Packit Service 963350
        self._signals = OrderedDict()
Packit Service 963350
        self._args = OrderedDict()
Packit Service 963350
        self.name = name
Packit Service 963350
Packit Service 963350
    def __repr__(self):
Packit Service 963350
        return "<Object %s>" % self.name
Packit Service 963350
Packit Service 963350
    def add_signal(self, signal, overwrite=True):
Packit Service 963350
        if not overwrite and signal.name in self._signals:
Packit Service 963350
            raise IndexError("signal %s already in %r" % (signal.name, self))
Packit Service 963350
        self._signals[signal.name] = signal
Packit Service 963350
Packit Service 963350
    def add_arg(self, arg, overwrite=True):
Packit Service 963350
        if not overwrite and arg.name in self._args:
Packit Service 963350
            raise IndexError("arg %s already in %r" % (arg.name, self))
Packit Service 963350
        self._args[arg.name] = arg
Packit Service 963350
Packit Service 963350
class Docable:
Packit Service 963350
    def __init__(self, **kwargs):
Packit Service 963350
        for key in self.attrs:
Packit Service 963350
            setattr(self, key, kwargs[key])
Packit Service 963350
        self.dict = kwargs
Packit Service 963350
Packit Service 963350
    def __repr__(self):
Packit Service 963350
        return "<%r %s>" % (str(self.__class__), self.name)
Packit Service 963350
Packit Service 963350
class Signal(Docable):
Packit Service 963350
    attrs = ['name', 'returns', 'args']
Packit Service 963350
Packit Service 963350
class Arg(Docable):
Packit Service 963350
    attrs = ['name', 'type', 'range', 'flags', 'nick', 'blurb', 'default']
Packit Service 963350
Packit Service 963350
class GDoc:
Packit Service 963350
    def load_file(self, filename):
Packit Service 963350
        try:
Packit Service 963350
            lines = codecs.open(filename, encoding='utf-8').readlines()
Packit Service 963350
            self.load_data("".join(lines))
Packit Service 963350
        except IOError:
Packit Service 963350
            print ("WARNING - could not read from %s" % filename)
Packit Service 963350
        except UnicodeDecodeError as e:
Packit Service 963350
            print ("WARNING - could not parse %s: %s" % (filename, e))
Packit Service 963350
Packit Service 963350
    def save_file(self, filename, backup=False):
Packit Service 963350
        """
Packit Service 963350
        Save the information to the given file if the file content changed.
Packit Service 963350
        """
Packit Service 963350
        olddata = None
Packit Service 963350
        try:
Packit Service 963350
            lines = codecs.open(filename, encoding='utf-8').readlines()
Packit Service 963350
            olddata = "".join(lines)
Packit Service 963350
        except IOError:
Packit Service 963350
            print ("WARNING - could not read from %s" % filename)
Packit Service 963350
        newdata = self.get_data()
Packit Service 963350
        if olddata and olddata == newdata:
Packit Service 963350
            return
Packit Service 963350
Packit Service 963350
        if olddata:
Packit Service 963350
            if backup:
Packit Service 963350
                os.rename(filename, filename + '.bak')
Packit Service 963350
Packit Service 963350
        handle = codecs.open(filename, "w", encoding='utf-8')
Packit Service 963350
        handle.write(newdata)
Packit Service 963350
        handle.close()
Packit Service 963350
Packit Service 963350
class Signals(GDoc):
Packit Service 963350
    def __init__(self):
Packit Service 963350
        self._objects = OrderedDict()
Packit Service 963350
Packit Service 963350
    def load_data(self, data):
Packit Service 963350
        """
Packit Service 963350
        Load the .signals lines, creating our list of objects and signals.
Packit Service 963350
        """
Packit Service 963350
        import re
Packit Service 963350
        smatcher = re.compile(
Packit Service 963350
            '(?s)'                                      # make . match \n
Packit Service 963350
            '<SIGNAL>\n(.*?)</SIGNAL>\n'
Packit Service 963350
            )
Packit Service 963350
        nmatcher = re.compile(
Packit Service 963350
            '<NAME>'
Packit Service 963350
            '(?P<object>\S*)'                           # store object
Packit Service 963350
            '::'
Packit Service 963350
            '(?P<signal>\S*)'                           # store signal
Packit Service 963350
            '</NAME>'
Packit Service 963350
        )
Packit Service 963350
        rmatcher = re.compile(
Packit Service 963350
            '(?s)'                                      # make . match \n
Packit Service 963350
            '<RETURNS>(?P<returns>\S*)</RETURNS>\n'     # store returns
Packit Service 963350
            '(?P<args>.*)'                              # store args
Packit Service 963350
        )
Packit Service 963350
        for block in smatcher.findall(data):
Packit Service 963350
            nmatch = nmatcher.search(block)
Packit Service 963350
            if nmatch:
Packit Service 963350
                o = nmatch.group('object')
Packit Service 963350
                debug("Found object", o)
Packit Service 963350
                debug("Found signal", nmatch.group('signal'))
Packit Service 963350
                if o not in self._objects:
Packit Service 963350
                    object = Object(o)
Packit Service 963350
                    self._objects[o] = object
Packit Service 963350
Packit Service 963350
                rmatch = rmatcher.search(block)
Packit Service 963350
                if rmatch:
Packit Service 963350
                    dict = rmatch.groupdict().copy()
Packit Service 963350
                    dict['name'] = nmatch.group('signal')
Packit Service 963350
                    signal = Signal(**dict)
Packit Service 963350
                    self._objects[o].add_signal(signal)
Packit Service 963350
Packit Service 963350
    def get_data(self):
Packit Service 963350
        lines = []
Packit Service 963350
        for o in self._objects.values():
Packit Service 963350
            for s in o._signals.values():
Packit Service 963350
                block = """<SIGNAL>
Packit Service 963350
<NAME>%(object)s::%(name)s</NAME>
Packit Service 963350
<RETURNS>%(returns)s</RETURNS>
Packit Service 963350
%(args)s</SIGNAL>
Packit Service 963350
"""
Packit Service 963350
                d = s.dict.copy()
Packit Service 963350
                d['object'] = o.name
Packit Service 963350
                lines.append(block % d)
Packit Service 963350
Packit Service 963350
        return "\n".join(lines) + '\n'
Packit Service 963350
Packit Service 963350
class Args(GDoc):
Packit Service 963350
    def __init__(self):
Packit Service 963350
        self._objects = OrderedDict()
Packit Service 963350
Packit Service 963350
    def load_data(self, data):
Packit Service 963350
        """
Packit Service 963350
        Load the .args lines, creating our list of objects and args.
Packit Service 963350
        """
Packit Service 963350
        import re
Packit Service 963350
        amatcher = re.compile(
Packit Service 963350
            '(?s)'                                      # make . match \n
Packit Service 963350
            '<ARG>\n(.*?)</ARG>\n'
Packit Service 963350
            )
Packit Service 963350
        nmatcher = re.compile(
Packit Service 963350
            '<NAME>'
Packit Service 963350
            '(?P<object>\S*)'                           # store object
Packit Service 963350
            '::'
Packit Service 963350
            '(?P<arg>\S*)'                              # store arg
Packit Service 963350
            '</NAME>'
Packit Service 963350
        )
Packit Service 963350
        rmatcher = re.compile(
Packit Service 963350
            '(?s)'                                      # make . match \n
Packit Service 963350
            '<TYPE>(?P<type>\S*)</TYPE>\n'              # store type
Packit Service 963350
            '<RANGE>(?P<range>.*?)</RANGE>\n'           # store range
Packit Service 963350
            '<FLAGS>(?P<flags>\S*)</FLAGS>\n'           # store flags
Packit Service 963350
            '<NICK>(?P<nick>.*?)</NICK>\n'              # store nick
Packit Service 963350
            '<BLURB>(?P<blurb>.*?)</BLURB>\n'           # store blurb
Packit Service 963350
            '<DEFAULT>(?P<default>.*?)</DEFAULT>\n'     # store default
Packit Service 963350
        )
Packit Service 963350
        for block in amatcher.findall(data):
Packit Service 963350
            nmatch = nmatcher.search(block)
Packit Service 963350
            if nmatch:
Packit Service 963350
                o = nmatch.group('object')
Packit Service 963350
                debug("Found object", o)
Packit Service 963350
                debug("Found arg", nmatch.group('arg'))
Packit Service 963350
                if o not in self._objects:
Packit Service 963350
                    object = Object(o)
Packit Service 963350
                    self._objects[o] = object
Packit Service 963350
Packit Service 963350
                rmatch = rmatcher.search(block)
Packit Service 963350
                if rmatch:
Packit Service 963350
                    dict = rmatch.groupdict().copy()
Packit Service 963350
                    dict['name'] = nmatch.group('arg')
Packit Service 963350
                    arg = Arg(**dict)
Packit Service 963350
                    self._objects[o].add_arg(arg)
Packit Service 963350
                else:
Packit Service 963350
                    print ("ERROR: could not match arg from block %s" % block)
Packit Service 963350
Packit Service 963350
    def get_data(self):
Packit Service 963350
        lines = []
Packit Service 963350
        for o in self._objects.values():
Packit Service 963350
            for a in o._args.values():
Packit Service 963350
                block = """<ARG>
Packit Service 963350
<NAME>%(object)s::%(name)s</NAME>
Packit Service 963350
<TYPE>%(type)s</TYPE>
Packit Service 963350
<RANGE>%(range)s</RANGE>
Packit Service 963350
<FLAGS>%(flags)s</FLAGS>
Packit Service 963350
<NICK>%(nick)s</NICK>
Packit Service 963350
<BLURB>%(blurb)s</BLURB>
Packit Service 963350
<DEFAULT>%(default)s</DEFAULT>
Packit Service 963350
</ARG>
Packit Service 963350
"""
Packit Service 963350
                d = a.dict.copy()
Packit Service 963350
                d['object'] = o.name
Packit Service 963350
                lines.append(block % d)
Packit Service 963350
Packit Service 963350
        return "\n".join(lines) + '\n'
Packit Service 963350
Packit Service 963350
class SingleLine(GDoc):
Packit Service 963350
    def __init__(self):
Packit Service 963350
        self._objects = []
Packit Service 963350
Packit Service 963350
    def load_data(self, data):
Packit Service 963350
        """
Packit Service 963350
        Load the .interfaces/.prerequisites lines, merge duplicates
Packit Service 963350
        """
Packit Service 963350
        # split data on '\n'
Packit Service 963350
        lines = data.splitlines();
Packit Service 963350
        # merge them into self._objects
Packit Service 963350
        for line in lines:
Packit Service 963350
            if line not in self._objects:
Packit Service 963350
                self._objects.append(line)
Packit Service 963350
Packit Service 963350
    def get_data(self):
Packit Service 963350
        lines = sorted(self._objects)
Packit Service 963350
        return "\n".join(lines) + '\n'
Packit Service 963350
Packit Service 963350
def main(argv):
Packit Service 963350
    modulename = None
Packit Service 963350
    try:
Packit Service 963350
        modulename = argv[1]
Packit Service 963350
    except IndexError:
Packit Service 963350
        sys.stderr.write('Please provide a documentation module name\n')
Packit Service 963350
        sys.exit(1)
Packit Service 963350
Packit Service 963350
    signals = Signals()
Packit Service 963350
    signals.load_file(modulename + '.signals')
Packit Service 963350
    signals.load_file(modulename + '.signals.new')
Packit Service 963350
    signals.save_file(modulename + '.signals', backup=True)
Packit Service 963350
    os.unlink(modulename + '.signals.new')
Packit Service 963350
Packit Service 963350
    args = Args()
Packit Service 963350
    args.load_file(modulename + '.args')
Packit Service 963350
    args.load_file(modulename + '.args.new')
Packit Service 963350
    args.save_file(modulename + '.args', backup=True)
Packit Service 963350
    os.unlink(modulename + '.args.new')
Packit Service 963350
Packit Service 963350
    ifaces = SingleLine()
Packit Service 963350
    ifaces.load_file(modulename + '.interfaces')
Packit Service 963350
    ifaces.load_file(modulename + '.interfaces.new')
Packit Service 963350
    ifaces.save_file(modulename + '.interfaces', backup=True)
Packit Service 963350
    os.unlink(modulename + '.interfaces.new')
Packit Service 963350
Packit Service 963350
    prereq = SingleLine()
Packit Service 963350
    prereq.load_file(modulename + '.prerequisites')
Packit Service 963350
    prereq.load_file(modulename + '.prerequisites.new')
Packit Service 963350
    prereq.save_file(modulename + '.prerequisites', backup=True)
Packit Service 963350
    os.unlink(modulename + '.prerequisites.new')
Packit Service 963350
Packit Service 963350
main(sys.argv)