]> rtime.felk.cvut.cz Git - omk.git/commitdiff
Almost final version of omkbuild.py
authorMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 10 May 2006 22:47:00 +0000 (22:47 +0000)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 10 May 2006 22:47:00 +0000 (22:47 +0000)
darcs-hash:20060510224710-f2ef6-3baf59200bd2cbb2b18e054ed90fb51bb3fc7e66.gz

omkbuild.py

index ed08875e7c4628d3218e1cf8499dd79a0a8e19d8..5dc7c3a9982ee996cfc89a5799c39f50217655f6 100755 (executable)
@@ -35,17 +35,40 @@ import sys
 import string
 import re
 
+class LineList(list):
+    """List of text lines"""
+    def getDiff(self, other):
+        s = ''
+        for i in range(len(self)):
+            if self[i] != other[i]:
+                s += ("  Line %d differs!\n" % i)
+                s += "  -"+self[i].rstrip() + "\n"
+                s += "  +"+other[i].rstrip() + "\n"
+                break
+        return s
+    
+    def __str__(self):
+        s = ''
+        for l in self: s += l
+        return s
+
+    def loadFromFile(self, fname):
+        """Loads itself from file."""
+        f = open(fname, "r")
+        self.expand(f.readlines())
+        f.close
+
 class Snippet:
     def __init__(self, fname = None):
         """Initializes the snippet and if fname is given, reads it
         from file"""
         self.name = ""
-        self.legal = []
-        self.doc = []
-        self.code = []
-        if fname: self.readFromFile(fname)
+        self.legal = LineList()
+        self.doc = LineList()
+        self.code = LineList()
+        if fname: self.loadFromFile(fname)
         
-    def readFromFile(self, fname):
+    def loadFromFile(self, fname):
         """Loads snippet from file."""
         self.name = fname
         f = open(fname, "r")
@@ -55,8 +78,7 @@ class Snippet:
         f.close
 
     def readLines(self, lines):
-        """Parses the snippet given in the list and stores it in
-        self."""
+        """Parses the snippet given as a list and stores it in itself."""
         currentPart = self.legal
         counter = 0
 
@@ -71,35 +93,134 @@ class Snippet:
 
         if not self.doc:
             self.doc = self.legal
-            self.legal = []
+            self.legal = LineList()
 
-    def asLines(self):
-        lines = []
+    def asLinesList(self):
+        lines = LineList()
         for type in ['legal', 'doc', 'code']:
             for line in self.__dict__[type]:
                 lines.append(line)
         return lines
 
     def __str__(self):
-        s = ""
-        lines = self.asLines()
-        for l in lines: s += l
-        return s
+        return str(self.asLinesList())
 
     def __repr__(self):
         s = "<Snippet: %s>" % self.name
         return s
 
     def __cmp__(self, other):
-        ret = self.name.__cmp__(other.name)
+        ret = cmp(self.name, other.name)
         if ret != 0: return ret
-        ret = self.legal.__cmp__(other.legal)
+        ret = cmp(self.legal, other.legal)
         if ret != 0: return ret
-        ret = self.doc.__cmp__(other.doc)
+        ret = cmp(self.doc, other.doc)
         if ret != 0: return ret
-        ret = self.code.__cmp__(other.code)
+        ret = cmp(self.code, other.code)
         return ret
 
+    def __getitem__(self, key):
+        return {
+            'legal': self.legal,
+            'doc'  : self.doc,
+            'code' : self.code
+            }[key]
+
+    def getDiff(self, other):
+        return self.asLinesList().getDiff(other.asLinesList())
+
+class Snippets:
+    """Collection of snippets, where snippets can be accessed
+    individually by name (like dictionary) or sequentionaly in the
+    order they were added."""
+    def __init__(self):
+        self._snippets = dict()
+        self._order = list()
+
+    def __iadd__(self, snippet):
+        assert isinstance(snippet, Snippet)
+        self._snippets[snippet.name] = snippet
+        self._order += [snippet]
+        return self
+
+    def __getitem__(self, key):
+        return self._snippets[key]
+
+    def __contains__(self, item):
+        return item in self._snippets
+
+    def __iter__(self):
+        return iter(self._order)
+
+    def __cmp__(self, other):
+        return cmp(self._snippets, other._snippets)
+
+    def loadFromFiles(self, fnames):
+        """Reads the snippets from several files and adds them to itself."""
+        for fn in fnames:
+            self += Snippet(fn)
+        
+    def loadFromDict(self, snipDict):
+        """Adds snippets to itself from dictionary of LineLists."""
+        for s in snipDict:
+            snip = Snippet()
+            snip.name = s
+            snip.readLines(snipDict[s])
+            self += snip
+
+    def getDiff(self, other):
+        assert isinstance(other, Snippets)
+        s = ''
+        for snip in self:
+            if (snip != other[snip.name]):
+                s += "Snippet %s:\n" % snip.name
+                s += snip.getDiff(other[snip.name])
+        return s
+
+class MakefileRules(LineList):
+    def __init__(self):
+        self.snippets = Snippets()
+        self.rules = LineList()
+
+    def combine(self):
+        """Combine self.snippets and produces self.rules"""
+        self.rules = LineList()
+
+        for type in ['legal', 'doc', 'code']:
+            for snip in self.snippets:
+                lines = snip[type]
+                if len(lines) == 0: continue
+                firstLine = string.rstrip(lines[0])
+                self.rules += [firstLine.ljust(60)+" #OMK@%s\n"%snip.name]
+                self.rules += lines[1:]
+                #self.rules += ['a'] # test error
+
+    def split(self):
+        """Split self.rules to the original snippets in self.snippets."""
+        self.snippets = Snippets()
+        snipDict = self._getSnipDicts()
+        self.snippets.loadFromDict(snipDict)
+
+    def _getSnipDicts(self):
+        """Split self.rules to the original snippets, which are
+        returened as dictionary of LineLists."""
+        snipBegin = re.compile("^(.*)#OMK@(.*)$")
+        snipDict = dict()
+        currentLinesList = None
+
+        for line in self.rules:
+            match = snipBegin.match(line)
+            if match:
+                line = match.group(1).rstrip() + "\n"
+                snipName = match.group(2)
+                if not snipName in snipDict:
+                    snipDict[snipName] = LineList()
+                currentLinesList = snipDict[snipName]
+
+            currentLinesList.append(line);
+        return snipDict
+
+
 def parseCommandLine():
     parser = OptionParser(usage = """
     %prog [-o FILE] snippet1 snippet2 ...      build Makefile.rules from snippets
@@ -114,98 +235,42 @@ def parseCommandLine():
     (options, args) = parser.parse_args()
     return options, args
 
-def splitToSnippets(rules):
-    """Split rules to the original snippets. The output is dictinary
-    of lists of lines"""
-
-    snipBegin = re.compile("^(.*)#OMK@(.*)$")
-    snipDict = dict()
-    currentLinesList = None
-
-    for line in rules:
-        match = snipBegin.match(line)
-        if match:
-            line = match.group(1).rstrip() + "\n"
-            snipName = match.group(2)
-            if not snipName in snipDict:
-                snipDict[snipName] = []
-            currentLinesList = snipDict[snipName]
-
-        currentLinesList.append(line);
-    return snipDict
-
-def convertSnipDict(snipDict):
-    """Takes dictionary of snippets, where each snippet is a lists of
-    lines, as the input argument and returns dictionary of snippets objects"""
-    outDict = dict()
-
-    for s in snipDict:
-        snip = Snippet()
-        snip.name = s
-        snip.readLines(snipDict[s])
-        outDict[s] = snip
-    return outDict
-
-def readSnippets(fnames):
-    """Reads the snippets from several files and retuns them as a
-    dictionaly indexed by file name."""
-    snipDict = dict()
-        
-    for fn in fnames:
-        snipDict[fn] = Snippet(fn)
-
-    return snipDict
-
-    
-def combineRules(snippets):
-    """Combine all snippents from the snippets dictionary to one list
-    of lines."""
-
-    rules = list()
-
-    for type in ['legal', 'doc', 'code']:
-        for s in snippets:
-            snip = snippets[s]
-            if len(snip.__dict__[type]) == 0: continue
-            firstLine = string.rstrip(snip.__dict__[type][0])
-            rules.append(firstLine.ljust(60)+" #OMK@%s\n"%snip.name)
-            rules.extend(snip.__dict__[type][1:]);
-    return rules
-
-def assertSameSnippets(d1, d2):
-    theSame = d1==d2
-    if not theSame:
-        # Generate an error message
-        for s in d1:
-            if (d1[s] != d2[s]):
-                sys.stderr.write("Consistency error: ")
-                s1 = d1[s]
-                s2 = d2[s]
-                for i in range(len(s1)):
-                    if s1[i] != s2[i]:
-                        sys.stderr.write("snippet %s, line %d differs!\n")
-                
-    return theSame
-
 def buildRules(fnames, output):
-    snipDict = readSnippets(fnames)
-    rules = combineRules(snipDict)
-    snipDict2 = convertSnipDict(splitToSnippets(rules))
-
-    if assertSameSnippets(snipDict, snipDict2) == False:
+    rules = MakefileRules()
+    rules.snippets.loadFromFiles(fnames)
+    rules.combine()
+
+    rulesCheck = MakefileRules()
+    rulesCheck.rules = rules.rules
+    rulesCheck.split()
+
+    if rules.snippets != rulesCheck.snippets:
+        sys.stderr.write("Consistency error:\n")
+        diff = rules.snippets.getDiff(rulesCheck.snippets)
+        sys.stderr.write(diff)
         sys.exit(1)
         
-
     if output: f = open(output,"w+")
-    else:
-        f = sys.stdout
-
-    f.writelines(rules)
-
+    else: f = sys.stdout
+    f.writelines(rules.rules)
     f.close()
 
 def splitRules(rulesFN, output):
-    pass
+    rules = MakefileRules()
+    rules.rules.loadFromFile(rulesFN)
+    rules.split()
+
+    rulesCheck = MakefileRules()
+    rulesCheck.snippets = rules.snippets
+    rulesCheck.combine()
+
+    if rules.rules != rulesCheck.rules:
+        sys.stderr.write("Consistency error:\n")
+        diff = rules.rules.getDiff(rulesCheck.rules)
+        sys.stderr.write(diff)
+        sys.exit(1)
+
+    #TODO: Store snippets to files
 
 def main():
     (options, args) = parseCommandLine()
@@ -215,4 +280,4 @@ def main():
         buildRules(args, options.output)
 
 
-if __name__ == "__main__":    main()
+if __name__ == "__main__": main()