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")
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
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
(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()
buildRules(args, options.output)
-if __name__ == "__main__": main()
+if __name__ == "__main__": main()