|
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- '''
- Template module for a Kai's Text Tools.
-
- (c) 2013 Ivan "Kai SD" Korystin
-
- License: GPLv3
- '''
-
- import re
- class TemplateV3(object):
- '''
- Class for reading ATGv3 templates.
- '''
- pass
-
- class TemplateV2(object):
- '''
- Class for reading ATGv2 templates.
- '''
-
- def __init__(self, filename=None, encoding='utf-8', text=''):
- '''
- Constructor
- '''
- if filename:
- with open(filename, 'r') as templateFile:
- topline = templateFile.readline().decode(encoding)
- if not topline.startswith('ATGV2'):
- raise BaseException('%s is not an ATGv2 template' % (filename))
-
- key = templateFile.readline().decode(encoding)
- if key[:2] == '[$' and key[-3:-1] == '$]':
- keyInfo = key[2:-2].split('$')
- if len(keyInfo) < 4:
- raise BaseException('%s has bad ATGv2 key' % (filename))
- self.keyField = keyInfo[0]
- self.extension = keyInfo[1]
- self.prefix = keyInfo[2]
- self.encoding = keyInfo[3]
- if 'oneFile' in keyInfo[4:]:
- self.oneFile = True
- else:
- self.oneFile = False
- if 'transpose' in keyInfo[4:]:
- self.transpose = True
- else:
- self.transpose = False
- self.text = u''
- else:
- raise BaseException('%s has bad ATGv2 key' % (filename))
-
- for i in templateFile.readlines():
- self.text += i.decode(encoding)
- else:
- self.text = text
-
- self.key = u''
- self.footer = u''
- self.replacement = {}
- self._data = None
- self._multiWords = None
-
- def parse(text):
- topParts = []
- matches = {}
-
- openers = re.finditer('\[\$.*?\$', text)
- closers = re.finditer('\$\]', text)
- ops = []
- try:
- cl = closers.next()
- while not cl is None:
- try:
- op = openers.next()
- if op.start() < cl.start():
- ops.append(op)
- else:
- idx = -1
- try:
- while ops[idx].start() > cl.start():
- idx -= 1
- except:
- raise BaseException('Template parsing error: can not find the opener for '+str(cl.start()))
- matches[ops[idx]] = cl
- if len(ops) == 1 or idx == -len(ops):
- topParts.append(ops[idx])
- del ops[idx]
- ops.append(op)
- try:
- cl = closers.next()
- except StopIteration:
- cl = None
- except StopIteration:
- idx = -1
- try:
- while ops[idx].start() > cl.start():
- idx -= 1
- except:
- raise BaseException('Template parsing error: can not find the opener for '+str(cl.start()))
- matches[ops[idx]] = cl
- if len(ops) == 1 or idx == -len(ops):
- topParts.append(ops[idx])
- del ops[idx]
- try:
- cl = closers.next()
- except StopIteration:
- cl = None
- except StopIteration:
- pass
- parts = []
- for i in topParts:
- startPoint = i.end()
- endPoint = matches[i].start()
- p = (i.group()[2:-1], text[startPoint:endPoint])
- if p[0].startswith('ATG'):
- parts.insert(0, p)
- else:
- parts.append(p)
- return parts
-
- partCommands = {}
-
- def plain(index, flow, keytag):
- if not keytag in self._data.keys:
- self.warning('WARNING: keyword not found in table - %s' % (keytag))
- return flow
- return flow.replace('[$%s$]' % (keytag), unicode(self._data[keytag, index]))
- partCommands['_ATGPLAIN'] = plain
-
- def nPlain(index, flow, keytag, number):
- if not keytag+str(number) in self._data.keys:
- self.warning('WARNING: keyword not found in table - %s' % (keytag+str(number)))
- return flow
- return flow.replace('[$%s$]' % (keytag), unicode(self._data[keytag+str(number), index]))
-
- def lIndex(index, flow, keytag, number):
- return flow.replace('[$ATGLINDEX$]', str(number))
-
- def addkey(index, flow, text):
- if self.key.find(text) < 0:
- self.key += text
- key = '[$ATGkey$' + text + '$]'
- return flow.replace(key,'')
- partCommands['ATGkey'] = addkey
-
- def addFooter(index, flow, text):
- if self.footer.find(text) < 0:
- self.footer += text
- key = '[$ATGFOOTER$' + text + '$]'
- return flow.replace(key,'')
- partCommands['ATGFOOTER'] = addFooter
-
- def addList(index, flow, string):
- key = '[$ATGLIST$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string[len(string.split('$')[0])+1:]
- keyTag = string.split('$')[0]
- subparts = parse(sub)
- myText = u''
- if not keyTag in self._multiWords:
- self.warning('Keytag %s is not multiple!' % (keyTag))
- return flow
- for j in xrange(1, self._multiWords[keyTag]+1):
- subText = sub
- for sp in subparts:
- if sp[0] in self._multiWords:
- subText = nPlain(index, subText, sp[0], j)
- elif sp[0] == 'ATGLINDEX':
- subText = lIndex(index, subText, sp[0], j)
- elif sp[0] in partCommands:
- subText = partCommands[sp[0]](index, subText, sp[1])
- elif sp[1] == '':
- subText = plain(index, subText, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- if not self._data[keyTag+str(j), index] == u'':
- myText += subText
- return flow.replace(key, myText)
- partCommands['ATGLIST'] = addList
-
- def addListCut(index, flow, string):
- key = '[$ATGLISTCUT$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string[len(string.split('$')[0])+1:]
- keyTag = string.split('$')[0]
- subparts = parse(sub)
- myText = u''
- if not keyTag in self._multiWords:
- self.warning('Keytag %s is not multiple!' % (keyTag))
- return flow
- for j in xrange(1, self._multiWords[keyTag]+1):
- subText = sub
- for sp in subparts:
- if sp[0] in self._multiWords:
- subText = nPlain(index, subText, sp[0], j)
- elif sp[0] == 'ATGLINDEX':
- subText = lIndex(index, subText, sp[0], j)
- elif sp[0] in partCommands:
- subText = partCommands[sp[0]](index, subText, sp[1])
- elif sp[1] == '':
- subText = plain(index, subText, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- if not self._data[keyTag+str(j), index] == u'':
- myText += subText
- return flow.replace(key, myText[:-1])
- partCommands['ATGLISTCUT'] = addListCut
-
- def addIf(index, flow, string):
- key = '[$ATGIF$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string[len(string.split('$')[0])+len(string.split('$')[1])+2:]
- keyTag = string.split('$')[0]
- targetValue = string.split('$')[1]
- subparts = parse(sub)
- myText = u''
- if self._data[keyTag, 0] == []:
- self.warning('WARNING: keyword not found in table - %s' % (keyTag))
- return flow
- if unicode(self._data[keyTag, index]) == unicode(targetValue):
- subText = sub
- for sp in subparts:
- if sp[0] in partCommands:
- subText = partCommands[sp[0]](index, subText, sp[1])
- elif sp[1] == '':
- subText = plain(index, subText, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- myText += subText
- return flow.replace(key, myText)
- partCommands['ATGIF'] = addIf
-
- def addIfNot(index, flow, string):
- key = '[$ATGIFNOT$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string[len(string.split('$')[0])+len(string.split('$')[1])+2:]
- keyTag = string.split('$')[0]
- targetValue = string.split('$')[1]
- subparts = parse(sub)
- myText = u''
- if self._data[keyTag, 0] == []:
- self.warning('WARNING: keyword not found in table - %s' % (keyTag))
- return flow
- if not unicode(self._data[keyTag, index]) == unicode(targetValue):
- subText = sub
- for sp in subparts:
- if sp[0] in partCommands:
- subText = partCommands[sp[0]](index, subText, sp[1])
- elif sp[1] == '':
- subText = plain(index, subText, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- myText += subText
- return flow.replace(key, myText)
- partCommands['ATGIFNOT'] = addIfNot
-
- def addGreater(index, flow, string):
- key = '[$ATGGREATER$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string[len(string.split('$')[0])+len(string.split('$')[1])+2:]
- keyTag = string.split('$')[0]
- targetValue = string.split('$')[1]
- subparts = parse(sub)
- myText = u''
- if self._data[keyTag, 0] == []:
- self.warning('WARNING: keyword not found in table - %s' % (keyTag))
- return flow
- try:
- if float(self._data[keyTag, index]) > float(targetValue):
- subText = sub
- for sp in subparts:
- if sp[0] in partCommands:
- subText = partCommands[sp[0]](index, subText, sp[1])
- elif sp[1] == '':
- subText = plain(index, subText, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- myText += subText
- except:
- self.warning('ERROR: trying to compare uncomparable values!')
- return flow.replace(key, myText)
- partCommands['ATGGREATER'] = addGreater
-
- def addLess(index, flow, string):
- key = '[$ATGLESS$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string[len(string.split('$')[0])+len(string.split('$')[1])+2:]
- keyTag = string.split('$')[0]
- targetValue = string.split('$')[1]
- subparts = parse(sub)
- myText = u''
- if self._data[keyTag, 0] == []:
- self.warning('WARNING: keyword not found in table - %s' % (keyTag))
- return flow
- try:
- if float(self._data[keyTag, index]) < float(targetValue):
- subText = sub
- for sp in subparts:
- if sp[0] in partCommands:
- subText = partCommands[sp[0]](index, subText, sp[1])
- elif sp[1] == '':
- subText = plain(index, subText, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- myText += subText
- except:
- self.warning('ERROR: trying to compare uncomparable values!')
- return flow.replace(key, myText)
- partCommands['ATGLESS'] = addLess
-
- def addReplace(index, flow, string):
- key = '[$ATGREPLACE$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- targetString = string[len(string.split('$')[0])+1:]
- srcString = string.split('$')[0]
- self.replacement[srcString] = targetString
- key = '[$ATGREPLACE$' + string + '$]'
- return flow.replace(key,'')
- partCommands['ATGREPLACE'] = addReplace
-
- def addPrefix(index, flow, string):
- key = '[$ATGPREFIX$%s$%s$]' % (string.split('$')[0], string[len(string.split('$')[0])+1:])
- sub = string
- subparts = parse(sub)
- for sp in subparts:
- if sp[0] in partCommands:
- sub = partCommands[sp[0]](index, sub, sp[1])
- elif sp[1] == '':
- sub = plain(index, sub, sp[0])
- else:
- self.warning('Warning: unknown command '+sp[0])
- self.bonusPrefix += sub
- key = '[$ATGPREFIX$' + string + '$]'
- return flow.replace(key,'')
- partCommands['ATGPREFIX'] = addPrefix
-
- def skip(index, flow, string):
- return u'[$ATGSKIP_DO$]'
- partCommands['ATGSKIP'] = skip
-
- def prev(index, flow, string):
- key = '[$ATGPREV$%s$]' % (string.split('$')[0])
- keytag = string.split('$')[0]
- if self._data[keytag, 0] == []:
- self.warning('WARNING: keyword not found in table - %s' % (keytag))
- return flow
- if index == 0:
- self.log('INFORMATION: Skipping ATGPREV tag for entry with index = 0')
- return u'[$ATGSKIP_DO$]'
- return flow.replace('[$ATGPREV$%s$]' % (keytag), unicode(self._data.col_by_key(keytag)[index-1]))
- partCommands['ATGPREV'] = prev
-
- self.commands = partCommands
- self.parts = parse(self.text)
-
- def process(self, data):
- self._data = data
-
- multiWords = {}
- numbs = ('1','2','3','4','5','6','7','8','9','0')
-
- for i in data.keys:
- multi = False
- while i[-1] in numbs:
- i = i[:-1]
- multi = True
- if multi:
- if i in multiWords:
- multiWords[i] += 1
- else:
- multiWords[i] = 1
- self._multiWords = multiWords
-
- if self.oneFile:
- out = ''
- else:
- out = {}
- index = 0
- partCommands = self.commands
- for element in data.col_by_key(self.keyField):
- self.bonusPrefix = self.prefix
- text = self.text
- for i in self.parts:
- if i[0] in partCommands:
- text = partCommands[i[0]](index, text, i[1])
- elif i[1] == u'':
- text = partCommands['_ATGPLAIN'](index, text, i[0])
- else:
- self.warning('Warning: unknown command '+i[0])
- for i in self.replacement:
- text = text.replace(i, self.replacement[i])
- self.replacement = {}
- index += 1
-
- if u'[$ATGSKIP_DO$]' in text:
- self.log('ATGSKIP Tag found. Skipping ' + unicode(element) + '.')
- else:
- if self.oneFile:
- out += text
- else:
- name = self.bonusPrefix + unicode(element)
- out[name] = text
- self.log('Created %s' % (element))
-
- if self.oneFile:
- out = self.key + out + self.footer
-
- return out
-
- def warning(self, text):
- print text
-
- def log(self, text):
- pass
-
- @staticmethod
- def express(cls, text, **kwargs):
- obj = cls()
- obj.text = text
- self.keyField = kwargs.get('keyField', 'Index')
- self.extension = kwargs.get('extension', '')
- self.prefix = kwargs.get('prefix', '')
- self.encoding = kwargs.get('encoding', 'utf-8')
- return obj
|