@@ -33,3 +33,5 @@ nosetests.xml | |||
.mr.developer.cfg | |||
.project | |||
.pydevproject | |||
GoogleIssues2CSV.py |
@@ -1,74 +0,0 @@ | |||
#!/usr/bin/python | |||
# -*- coding: utf-8 -*- | |||
''' | |||
Advanced Text Generator module for a KaiSD Text Tools. | |||
(c) 2013 Ivan "Kai SD" Korystin | |||
License: GPLv3 | |||
''' | |||
from os.path import join, exists | |||
from os import makedirs | |||
class ATG: | |||
''' | |||
Advanced Text Generator is a class, created to generate multiple | |||
text files from table data. | |||
''' | |||
def __init__(self, data, template): | |||
''' | |||
Constructor. | |||
data - an instance of the data.Data class (i.e. CSVData) | |||
template - an instance of the template.Template class (i.e. TemplateV2) | |||
''' | |||
self.data = data | |||
self.template = template | |||
self.out = template.process(data) | |||
if type(self.out) == dict: | |||
self.multiple = True | |||
else: | |||
self.multiple = False | |||
def write_files(self, outputDir='.'): | |||
''' | |||
Write generated files to the given directory. | |||
''' | |||
encoding = self.template.encoding | |||
extension = self.template.extension | |||
out = self.out | |||
if self.multiple: | |||
for name in out.keys(): | |||
namepath = name.replace('\\', '/').split('/') | |||
newpath = u'' | |||
for i in namepath[:-1]: | |||
newpath = join(newpath, i) | |||
if not exists(join(unicode(outputDir),newpath)): | |||
makedirs(join(unicode(outputDir),newpath)) | |||
fname = join(unicode(outputDir),name+'.'+extension) | |||
if fname.endswith('.'): | |||
fname = fname[:-1] | |||
f = open(fname, 'w') | |||
f.write(out[name].encode(encoding)) | |||
self.log(' Saved %s' % (name+'.'+extension)) | |||
f.close() | |||
else: | |||
name = self.template.bonusPrefix + '.' + extension | |||
if name == '.': | |||
name = self.template.keyField | |||
namepath = name.replace('\\', '/').split('/') | |||
newpath = u'' | |||
for i in namepath[:-1]: | |||
newpath = join(newpath, i) | |||
if not exists(join(unicode(outputDir),newpath)): | |||
makedirs(join(unicode(outputDir),newpath)) | |||
f = open(join(unicode(outputDir),name+'.'+extension), 'w') | |||
f.write(out.encode(encoding)) | |||
self.log(' Saved %s' % (name+'.'+extension)) | |||
f.close() | |||
def log(self, text): | |||
''' | |||
Print information | |||
''' | |||
pass |
@@ -1,168 +0,0 @@ | |||
#!/usr/bin/python | |||
# -*- coding: utf-8 -*- | |||
''' | |||
Advanced Text Replacer module for a KaiSD Text Tools. | |||
(c) 2013 Ivan "Kai SD" Korystin | |||
License: GPLv3 | |||
''' | |||
import re | |||
class ATR: | |||
''' | |||
Advanced Text Replacer - is a class, created to make multiple replacements | |||
in the content or names of text file. | |||
It can make plain replacements, or use ATG templates to do something more complex. | |||
''' | |||
def __init__(self, files): | |||
''' | |||
Constructor | |||
''' | |||
self.files = files | |||
self.replacements = [] | |||
def plain_replace(self, pattern, string, regexp=False): | |||
''' | |||
Replaces the given pattern with string in files. | |||
''' | |||
if regexp: | |||
pattern = re.compile(pattern) | |||
self.replacements.append((pattern, string)) | |||
def templated_replace(self, pattern, template, data, keyFormat='filename', regexp=False): | |||
''' | |||
Replaces the given pattern with data formated by template. | |||
Valid values for keyFormat: | |||
filename - take data rows by filename(path ignored), key value of the data row should store the filename. | |||
fullname - as filename, but with path. | |||
index - take data rows in order, key value of the data row should store the index. Indexes starts with 0. | |||
If filename or index cannot be found in data keys, pattern will not be replaced. | |||
''' | |||
if regexp: | |||
pattern = re.compile(pattern) | |||
strings = template.process(data) | |||
self.replacements.append((pattern, strings, keyFormat)) | |||
def write_in_place(self): | |||
''' | |||
Do replacement and save the files | |||
''' | |||
for f in self.files: | |||
out = u'' | |||
with open(f, 'rb') as file: | |||
out = file.read() | |||
idx = 0 | |||
for r in self.replacements: | |||
if type(r[0]) in (str, unicode): | |||
pattern = re.compile(re.escape(r[0])) | |||
string = r[1] | |||
elif type(r[0]) is dict and len(r) == 3: | |||
if r[2] == 'filename': | |||
fname = f.replace('\\', '/').split('/')[-1] | |||
string = f[1].get(fname, None) | |||
elif r[2] == 'fullname': | |||
string = f[1].get(f, None) | |||
elif r[2] == 'index': | |||
fname = f.replace('\\', '/').split('/')[-1] | |||
string = f[1].get(idx, None) | |||
else: | |||
raise BaseException('Unknown data key format.') | |||
elif hasattr(r[0], 'match'): | |||
pattern = r[0] | |||
string = r[1] | |||
else: | |||
raise BaseException('Unknown pattern type.') | |||
if string: | |||
out = re.sub(pattern, string, out) | |||
with open(f, 'wb') as outfile: | |||
outfile.write(out) | |||
def write_new_files(self, outfiles): | |||
''' | |||
Do replacement, but save to given files instead of the original ones. | |||
''' | |||
if not len(outfiles) == len(self.files): | |||
raise BaseException('Lists of original and new files has different length.') | |||
for f in self.files: | |||
out = u'' | |||
with open(f, 'rb') as file: | |||
out = file.read() | |||
idx = 0 | |||
for r in self.replacements: | |||
if type(r[0]) in (str, unicode): | |||
pattern = re.compile(re.escape(r[0])) | |||
string = r[1] | |||
elif type(r[0]) is dict and len(r) == 3: | |||
if r[2] == 'filename': | |||
fname = f.replace('\\', '/').split('/')[-1] | |||
string = f[1].get(fname, None) | |||
elif r[2] == 'fullname': | |||
string = f[1].get(f, None) | |||
elif r[2] == 'index': | |||
fname = f.replace('\\', '/').split('/')[-1] | |||
string = f[1].get(idx, None) | |||
else: | |||
raise BaseException('Unknown data key format.') | |||
elif hasattr(r[0], 'match'): | |||
pattern = r[0] | |||
string = r[1] | |||
else: | |||
raise BaseException('Unknown pattern type.') | |||
if string: | |||
out = re.sub(pattern, string, out) | |||
with open(outfiles[self.files.index(f)], 'wb') as outfile: | |||
outfile.write(out) | |||
def replace_in_names(self): | |||
''' | |||
Do replacement, but in file names instead of file content. Returns the list of new file names, | |||
you can use it with writeNewFiles() method. | |||
''' | |||
out = [] | |||
for f in self.files: | |||
new = f | |||
idx = 0 | |||
for r in self.replacements: | |||
if type(r[0]) in (str, unicode): | |||
pattern = re.compile(re.escape(r[0])) | |||
string = r[1] | |||
elif type(r[0]) is dict and len(r) == 3: | |||
if r[2] == 'filename': | |||
fname = f.replace('\\', '/').split('/')[-1] | |||
string = f[1].get(fname, None) | |||
elif r[2] == 'fullname': | |||
string = f[1].get(f, None) | |||
elif r[2] == 'index': | |||
fname = f.replace('\\', '/').split('/')[-1] | |||
string = f[1].get(idx, None) | |||
else: | |||
raise BaseException('Unknown data key format.') | |||
elif hasattr(r[0], 'match'): | |||
pattern = r[0] | |||
string = r[1] | |||
else: | |||
raise BaseException('Unknown pattern type.') | |||
if string: | |||
new = re.sub(pattern, string, new) | |||
out.append(new) | |||
return out | |||
def clear_replacements(self): | |||
''' | |||
Removes all replacements. | |||
''' | |||
self.replacements = [] | |||
def log(self, string): | |||
''' | |||
Print information | |||
''' | |||
pass |
@@ -1,191 +0,0 @@ | |||
#!/usr/bin/python | |||
# -*- coding: utf-8 -*- | |||
''' | |||
Data module for a KaiSD Text Tools. | |||
(c) 2013 Ivan "Kai SD" Korystin | |||
License: GPLv3 | |||
''' | |||
import csv, codecs | |||
class Data: | |||
''' | |||
Empty data class. Can be used for a subclassing or procedural data creation. | |||
''' | |||
def __init__(self, *args, **kwargs): | |||
''' | |||
Constructor | |||
''' | |||
self.keys = [] | |||
self.rows = [] | |||
def __getitem__(self, pair): | |||
''' | |||
Returns a value for given key and row. | |||
''' | |||
key = pair[0] | |||
row = pair[1] | |||
keys = self.keys | |||
rows = self.rows | |||
if key in keys: | |||
if len(rows) > row: | |||
return rows[row][keys.index(key)] | |||
else: | |||
raise BaseException('Row %i not found in data' % (row)) | |||
else: | |||
raise BaseException('Named value %s not found in data' % (key)) | |||
def __setitem__(self, pair, value): | |||
''' | |||
Sets a value for given key and row. | |||
''' | |||
key = pair[0] | |||
row = pair[1] | |||
keys = self.keys | |||
rows = self.rows | |||
if key in keys: | |||
if len(rows) > row: | |||
rows[row][keys.index(key)] = value | |||
else: | |||
raise BaseException('Row %i not found in data' % (row)) | |||
else: | |||
raise BaseException('Named value %s not found in data' % (key)) | |||
def __str__(self): | |||
''' | |||
Returns data as string. | |||
''' | |||
return str((self.keys, self.rows)) | |||
def __repr__(self): | |||
return self.__str__() | |||
def has_key(self, key): | |||
''' | |||
Returns True if given key exists in data | |||
''' | |||
return key in self.keys | |||
def add_rows(self, n=1): | |||
''' | |||
Adds some empty rows to the data. | |||
''' | |||
keys = self.keys | |||
rows = self.rows | |||
for n in xrange(0, n): | |||
row = [] | |||
for k in keys: | |||
row.append('') | |||
rows.append(row) | |||
def add_keys(self, *h): | |||
''' | |||
Adds new keys to the data. | |||
''' | |||
keys = self.keys | |||
rows = self.rows | |||
for i in h: | |||
keys.append(i) | |||
for r in rows: | |||
for i in h: | |||
r.append('') | |||
def col_by_key(self, key): | |||
''' | |||
Returns a column by header's name | |||
''' | |||
cols = [] | |||
keys = self.keys | |||
rows = self.rows | |||
if key in keys: | |||
idx = keys.index(key) | |||
for r in rows: | |||
cols.append(r[idx]) | |||
else: | |||
raise BaseException('Named value %s not found in data' % (key)) | |||
return tuple(cols) | |||
def row_by_idx(self, idx): | |||
''' | |||
Returns a row by index. | |||
''' | |||
return tuple(self.rows[idx]) | |||
class CSVData(Data): | |||
''' | |||
Class for reading CSV files. | |||
''' | |||
class Reader: | |||
class Recoder: | |||
def __init__(self, f, encoding): | |||
self.reader = codecs.getreader(encoding)(f) | |||
def __iter__(self): | |||
return self | |||
def next(self): | |||
return self.reader.next().encode("utf-8") | |||
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): | |||
f = self.Recoder(f, encoding) | |||
self.reader = csv.reader(f, dialect=dialect, **kwds) | |||
def next(self): | |||
row = self.reader.next() | |||
return [unicode(s, "utf-8") for s in row] | |||
def __iter__(self): | |||
return self | |||
def __init__(self, filename, encoding='utf-8', delimiter=';', quotechar='"', **kwargs): | |||
''' | |||
Constructor. | |||
filename - CSV table filename | |||
encoding - CSV table encoding | |||
delimiter - CSV table delimiter | |||
quotechar - CSV table quotechar | |||
transpose=True - transpose the table | |||
''' | |||
csvfile = self.Reader(open(filename), encoding=encoding, delimiter=delimiter, quotechar=quotechar) | |||
sourceData = [] | |||
sourcekeys = None | |||
if kwargs.get('transpose', False): | |||
sourcekeys = [] | |||
rowData = [] | |||
for i in csvfile: | |||
sourcekeys.append(i[0]) | |||
for k in xrange(1, len(i)): | |||
sourceData.append([]) | |||
try: | |||
i[k] = int(i[k]) | |||
except: | |||
try: | |||
i[k] = float(i[k]) | |||
except: | |||
i[k] = i[k] | |||
rowData.append(i[1:]) | |||
sourceData = list(map(lambda *x:x, *rowData)) | |||
else: | |||
for i in csvfile: | |||
if sourcekeys is None: | |||
sourcekeys = i | |||
else: | |||
for k in xrange(0, len(i)): | |||
try: | |||
i[k] = int(i[k]) | |||
except: | |||
try: | |||
i[k] = float(i[k]) | |||
except: | |||
i[k] = i[k] | |||
sourceData.append(i) | |||
self.keys = sourcekeys | |||
self.rows = sourceData |
@@ -1,47 +0,0 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | |||
<html><head><title>Python: module atg</title> | |||
</head><body bgcolor="#f0f0f8"> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading"> | |||
<tr bgcolor="#7799ee"> | |||
<td valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>atg</strong></big></big></font></td | |||
><td align=right valign=bottom | |||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///C:/users/kaisd/documents/workbench/programming/ktt/src/atg.py">c:\users\kaisd\documents\workbench\programming\ktt\src\atg.py</a></font></td></tr></table> | |||
<p><tt>Advanced Text Generator module for a KaiSD Text Tools.<br> | |||
<br> | |||
(c) 2013 Ivan "Kai SD" Korystin <br> | |||
<br> | |||
License: GPLv3</tt></p> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ee77aa"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr> | |||
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td> | |||
<td width="100%"><dl> | |||
<dt><font face="helvetica, arial"><a href="atg.html#ATG">ATG</a> | |||
</font></dt></dl> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ffc8d8"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#000000" face="helvetica, arial"><a name="ATG">class <strong>ATG</strong></a></font></td></tr> | |||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td> | |||
<td colspan=2><tt>Advanced Text Generator is a class, created to generate multiple<br> | |||
text files from table data.<br> </tt></td></tr> | |||
<tr><td> </td> | |||
<td width="100%">Methods defined here:<br> | |||
<dl><dt><a name="ATG-__init__"><strong>__init__</strong></a>(self, data, template)</dt><dd><tt>Constructor.<br> | |||
data - an instance of the data.Data class (i.e. CSVData)<br> | |||
template - an instance of the template.Template class (i.e. TemplateV2)</tt></dd></dl> | |||
<dl><dt><a name="ATG-log"><strong>log</strong></a>(self, text)</dt><dd><tt>Print information</tt></dd></dl> | |||
<dl><dt><a name="ATG-write_files"><strong>write_files</strong></a>(self, outputDir<font color="#909090">='.'</font>)</dt><dd><tt>Write generated files to the given directory.</tt></dd></dl> | |||
</td></tr></table></td></tr></table> | |||
</body></html> |
@@ -1,70 +0,0 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | |||
<html><head><title>Python: module atr</title> | |||
</head><body bgcolor="#f0f0f8"> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading"> | |||
<tr bgcolor="#7799ee"> | |||
<td valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>atr</strong></big></big></font></td | |||
><td align=right valign=bottom | |||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///C:/users/kaisd/documents/workbench/programming/ktt/src/atr.py">c:\users\kaisd\documents\workbench\programming\ktt\src\atr.py</a></font></td></tr></table> | |||
<p><tt>Advanced Text Replacer module for a KaiSD Text Tools.<br> | |||
<br> | |||
(c) 2013 Ivan "Kai SD" Korystin <br> | |||
<br> | |||
License: GPLv3</tt></p> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#aa55cc"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr> | |||
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td> | |||
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="re.html">re</a><br> | |||
</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ee77aa"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr> | |||
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td> | |||
<td width="100%"><dl> | |||
<dt><font face="helvetica, arial"><a href="atr.html#ATR">ATR</a> | |||
</font></dt></dl> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ffc8d8"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#000000" face="helvetica, arial"><a name="ATR">class <strong>ATR</strong></a></font></td></tr> | |||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td> | |||
<td colspan=2><tt>Advanced Text Replacer - is a class, created to make multiple replacements<br> | |||
in the content or names of text file.<br> | |||
It can make plain replacements, or use ATG templates to do something more complex.<br> </tt></td></tr> | |||
<tr><td> </td> | |||
<td width="100%">Methods defined here:<br> | |||
<dl><dt><a name="ATR-__init__"><strong>__init__</strong></a>(self, files)</dt><dd><tt>Constructor</tt></dd></dl> | |||
<dl><dt><a name="ATR-clear_replacements"><strong>clear_replacements</strong></a>(self)</dt><dd><tt>Removes all replacements.</tt></dd></dl> | |||
<dl><dt><a name="ATR-log"><strong>log</strong></a>(self, string)</dt><dd><tt>Print information</tt></dd></dl> | |||
<dl><dt><a name="ATR-plain_replace"><strong>plain_replace</strong></a>(self, pattern, string, regexp<font color="#909090">=False</font>)</dt><dd><tt>Replaces the given pattern with string in files.</tt></dd></dl> | |||
<dl><dt><a name="ATR-replace_in_names"><strong>replace_in_names</strong></a>(self)</dt><dd><tt>Do replacement, but in file names instead of file content. Returns the list of new file names,<br> | |||
you can use it with writeNewFiles() method.</tt></dd></dl> | |||
<dl><dt><a name="ATR-templated_replace"><strong>templated_replace</strong></a>(self, pattern, template, data, keyFormat<font color="#909090">='filename'</font>, regexp<font color="#909090">=False</font>)</dt><dd><tt>Replaces the given pattern with data formated by template.<br> | |||
Valid values for keyFormat:<br> | |||
filename - take data rows by filename(path ignored), key value of the data row should store the filename.<br> | |||
fullname - as filename, but with path.<br> | |||
index - take data rows in order, key value of the data row should store the index. Indexes starts with 0.<br> | |||
If filename or index cannot be found in data keys, pattern will not be replaced.</tt></dd></dl> | |||
<dl><dt><a name="ATR-write_in_place"><strong>write_in_place</strong></a>(self)</dt><dd><tt>Do replacement and save the files</tt></dd></dl> | |||
<dl><dt><a name="ATR-write_new_files"><strong>write_new_files</strong></a>(self, outfiles)</dt><dd><tt>Do replacement, but save to given files instead of the original ones.</tt></dd></dl> | |||
</td></tr></table></td></tr></table> | |||
</body></html> |
@@ -1,114 +0,0 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | |||
<html><head><title>Python: module data</title> | |||
</head><body bgcolor="#f0f0f8"> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading"> | |||
<tr bgcolor="#7799ee"> | |||
<td valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>data</strong></big></big></font></td | |||
><td align=right valign=bottom | |||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///C:/users/kaisd/documents/workbench/programming/ktt/src/data.py">c:\users\kaisd\documents\workbench\programming\ktt\src\data.py</a></font></td></tr></table> | |||
<p><tt><a href="#Data">Data</a> module for a KaiSD Text Tools.<br> | |||
<br> | |||
(c) 2013 Ivan "Kai SD" Korystin <br> | |||
<br> | |||
License: GPLv3</tt></p> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#aa55cc"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr> | |||
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td> | |||
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="codecs.html">codecs</a><br> | |||
</td><td width="25%" valign=top><a href="csv.html">csv</a><br> | |||
</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ee77aa"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr> | |||
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td> | |||
<td width="100%"><dl> | |||
<dt><font face="helvetica, arial"><a href="data.html#Data">Data</a> | |||
</font></dt><dd> | |||
<dl> | |||
<dt><font face="helvetica, arial"><a href="data.html#CSVData">CSVData</a> | |||
</font></dt></dl> | |||
</dd> | |||
</dl> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ffc8d8"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#000000" face="helvetica, arial"><a name="CSVData">class <strong>CSVData</strong></a>(<a href="data.html#Data">Data</a>)</font></td></tr> | |||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td> | |||
<td colspan=2><tt>Class for reading CSV files.<br> </tt></td></tr> | |||
<tr><td> </td> | |||
<td width="100%">Methods defined here:<br> | |||
<dl><dt><a name="CSVData-__init__"><strong>__init__</strong></a>(self, filename, encoding<font color="#909090">='utf-8'</font>, delimiter<font color="#909090">=';'</font>, quotechar<font color="#909090">='"'</font>, **kwargs)</dt><dd><tt>Constructor.<br> | |||
<br> | |||
filename - CSV table filename<br> | |||
encoding - CSV table encoding<br> | |||
delimiter - CSV table delimiter<br> | |||
quotechar - CSV table quotechar<br> | |||
transpose=True - transpose the table</tt></dd></dl> | |||
<hr> | |||
Data and other attributes defined here:<br> | |||
<dl><dt><strong>Reader</strong> = <class data.Reader></dl> | |||
<hr> | |||
Methods inherited from <a href="data.html#Data">Data</a>:<br> | |||
<dl><dt><a name="CSVData-__getitem__"><strong>__getitem__</strong></a>(self, pair)</dt><dd><tt>Returns a value for given key and row.</tt></dd></dl> | |||
<dl><dt><a name="CSVData-__repr__"><strong>__repr__</strong></a>(self)</dt></dl> | |||
<dl><dt><a name="CSVData-__setitem__"><strong>__setitem__</strong></a>(self, pair, value)</dt><dd><tt>Sets a value for given key and row.</tt></dd></dl> | |||
<dl><dt><a name="CSVData-__str__"><strong>__str__</strong></a>(self)</dt><dd><tt>Returns data as string.</tt></dd></dl> | |||
<dl><dt><a name="CSVData-add_keys"><strong>add_keys</strong></a>(self, *h)</dt><dd><tt>Adds new keys to the data.</tt></dd></dl> | |||
<dl><dt><a name="CSVData-add_rows"><strong>add_rows</strong></a>(self, n<font color="#909090">=1</font>)</dt><dd><tt>Adds some empty rows to the data.</tt></dd></dl> | |||
<dl><dt><a name="CSVData-col_by_key"><strong>col_by_key</strong></a>(self, key)</dt><dd><tt>Returns a column by header's name</tt></dd></dl> | |||
<dl><dt><a name="CSVData-has_key"><strong>has_key</strong></a>(self, key)</dt><dd><tt>Returns True if given key exists in data</tt></dd></dl> | |||
<dl><dt><a name="CSVData-row_by_idx"><strong>row_by_idx</strong></a>(self, idx)</dt><dd><tt>Returns a row by index.</tt></dd></dl> | |||
</td></tr></table> <p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ffc8d8"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#000000" face="helvetica, arial"><a name="Data">class <strong>Data</strong></a></font></td></tr> | |||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td> | |||
<td colspan=2><tt>Empty data class. Can be used for a subclassing or procedural data creation.<br> </tt></td></tr> | |||
<tr><td> </td> | |||
<td width="100%">Methods defined here:<br> | |||
<dl><dt><a name="Data-__getitem__"><strong>__getitem__</strong></a>(self, pair)</dt><dd><tt>Returns a value for given key and row.</tt></dd></dl> | |||
<dl><dt><a name="Data-__init__"><strong>__init__</strong></a>(self, *args, **kwargs)</dt><dd><tt>Constructor</tt></dd></dl> | |||
<dl><dt><a name="Data-__repr__"><strong>__repr__</strong></a>(self)</dt></dl> | |||
<dl><dt><a name="Data-__setitem__"><strong>__setitem__</strong></a>(self, pair, value)</dt><dd><tt>Sets a value for given key and row.</tt></dd></dl> | |||
<dl><dt><a name="Data-__str__"><strong>__str__</strong></a>(self)</dt><dd><tt>Returns data as string.</tt></dd></dl> | |||
<dl><dt><a name="Data-add_keys"><strong>add_keys</strong></a>(self, *h)</dt><dd><tt>Adds new keys to the data.</tt></dd></dl> | |||
<dl><dt><a name="Data-add_rows"><strong>add_rows</strong></a>(self, n<font color="#909090">=1</font>)</dt><dd><tt>Adds some empty rows to the data.</tt></dd></dl> | |||
<dl><dt><a name="Data-col_by_key"><strong>col_by_key</strong></a>(self, key)</dt><dd><tt>Returns a column by header's name</tt></dd></dl> | |||
<dl><dt><a name="Data-has_key"><strong>has_key</strong></a>(self, key)</dt><dd><tt>Returns True if given key exists in data</tt></dd></dl> | |||
<dl><dt><a name="Data-row_by_idx"><strong>row_by_idx</strong></a>(self, idx)</dt><dd><tt>Returns a row by index.</tt></dd></dl> | |||
</td></tr></table></td></tr></table> | |||
</body></html> |
@@ -1,135 +0,0 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | |||
<html><head><title>Python: module template</title> | |||
</head><body bgcolor="#f0f0f8"> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading"> | |||
<tr bgcolor="#7799ee"> | |||
<td valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>template</strong></big></big></font></td | |||
><td align=right valign=bottom | |||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///C:/users/kaisd/documents/workbench/programming/ktt/src/template.py">c:\users\kaisd\documents\workbench\programming\ktt\src\template.py</a></font></td></tr></table> | |||
<p><tt><a href="#Template">Template</a> module for a KaiSD Text Tools.<br> | |||
<br> | |||
(c) 2013 Ivan "Kai SD" Korystin <br> | |||
<br> | |||
License: GPLv3</tt></p> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#aa55cc"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr> | |||
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td> | |||
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="re.html">re</a><br> | |||
</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ee77aa"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr> | |||
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td> | |||
<td width="100%"><dl> | |||
<dt><font face="helvetica, arial"><a href="template.html#Template">Template</a> | |||
</font></dt><dd> | |||
<dl> | |||
<dt><font face="helvetica, arial"><a href="template.html#TemplateV2">TemplateV2</a> | |||
</font></dt></dl> | |||
</dd> | |||
</dl> | |||
<p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ffc8d8"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#000000" face="helvetica, arial"><a name="Template">class <strong>Template</strong></a></font></td></tr> | |||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td> | |||
<td colspan=2><tt>Empty template class. Generates empty text.<br> </tt></td></tr> | |||
<tr><td> </td> | |||
<td width="100%">Methods defined here:<br> | |||
<dl><dt><a name="Template-log"><strong>log</strong></a>(self, text)</dt><dd><tt>Print information</tt></dd></dl> | |||
<dl><dt><a name="Template-process"><strong>process</strong></a>(self, data)</dt><dd><tt>Replace this method in subclasses.</tt></dd></dl> | |||
<dl><dt><a name="Template-warning"><strong>warning</strong></a>(self, text)</dt><dd><tt>Prints a warning</tt></dd></dl> | |||
</td></tr></table> <p> | |||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> | |||
<tr bgcolor="#ffc8d8"> | |||
<td colspan=3 valign=bottom> <br> | |||
<font color="#000000" face="helvetica, arial"><a name="TemplateV2">class <strong>TemplateV2</strong></a>(<a href="template.html#Template">Template</a>)</font></td></tr> | |||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td> | |||
<td colspan=2><tt>Class for reading ATGv2 templates.<br> | |||
<br> | |||
ATGv2 template file should be a plain text file, starting with the line<br> | |||
ATGV2<br> | |||
followed by the info line:<br> | |||
[$KeyField$Extension$Prefix$Encoding$]<br> | |||
where<br> | |||
KeyField - is a name of a data column, that contains an identifier.<br> | |||
Extension - is the desired extension for the generated files.<br> | |||
Prefix - is the desired filename prefix for the generated files<br> | |||
Encoding - is the desired encoding for the generated files.<br> | |||
The line may also have some optional keywords before the closing bracket:<br> | |||
oneFile$ - place all generated text into a single file instead of<br> | |||
generating a file for each table row.<br> | |||
After the info line, you can put your text.<br> | |||
You can use following commands to handle the data:<br> | |||
* [$Name$], where Name is the column header,<br> | |||
will be replaced with value from the current row.<br> | |||
* [$ATGLINDEX$] will be replaced with the number of a current row.<br> | |||
* [$ATGHEADER$Text$] and [$ATGFOOTER$Text$] will place the given text<br> | |||
at the begining or at the end of the file. You can't use other<br> | |||
commands in this text.<br> | |||
* [$ATGLIST$Name$Text$], where Name is a multi-column header<br> | |||
(i.e. 'Col' will represent 'Col1', 'Col2', 'Col3' etc)<br> | |||
will repeat the given text for each non-empty value.<br> | |||
You can use other commands in Text. Also [$Name$] inside the list<br> | |||
will be replaced with the value for the current row and column.<br> | |||
* [$ATGLINDEX$] can be used only inside the ATGLIST text,<br> | |||
will be replaced with the current column index.<br> | |||
* [$ATGLISTCUT$Name$Text$] - same as ATGLIST, but the last symbol<br> | |||
will be removed. Useful for removing unnecessary newlines.<br> | |||
* [$ATGIF$Name$Value$Text$] will be replaced with the given text<br> | |||
only if the the given column's value is the same as the given one.<br> | |||
Will be replaced with the empty text otherwise. You can use other<br> | |||
commands in Text.<br> | |||
* [$ATGIFNOT$Name$Value$Text$] - same as ATGIF, but the column's value<br> | |||
should not be equal to the given one.<br> | |||
* [$ATGGREATER$Name$Value$Text$] - same as ATGIF, but the value should<br> | |||
be the number and it should be greater then the given one.<br> | |||
* [$ATGGREATER$Name$Value$Text$] - same as ATGGREATER, but the value<br> | |||
should be less then the given one.<br> | |||
* [$ATGREPLACE$Text1$Text2$] - Will replace Text1 with Text2. Replacements<br> | |||
will be done after all other commands. You can't use regular expressions or<br> | |||
other commands in the text.<br> | |||
* [$ATGPREFIX$Text$] - Will add the given text to the filename prefix.<br> | |||
You can use other commands in text, but do it carefully.<br> | |||
* [$ATGSKIP$] - Skip the current row. Use only in combination with the<br> | |||
ATGIF/ATGIFNOT, or you will generate nothing.<br> | |||
* [$ATGPREV$Name$], where Name is the column header,<br> | |||
will be replaced with the with the value of the given header from the<br> | |||
previous row. ATGSKIP will be used for the first row.<br> </tt></td></tr> | |||
<tr><td> </td> | |||
<td width="100%">Methods defined here:<br> | |||
<dl><dt><a name="TemplateV2-__init__"><strong>__init__</strong></a>(self, filename<font color="#909090">=None</font>, encoding<font color="#909090">='utf-8'</font>, text<font color="#909090">=''</font>)</dt><dd><tt>Constructor.<br> | |||
<br> | |||
filename - name of the ATGv2 template file.<br> | |||
encoding - encoding of the template file.<br> | |||
text - text to use if no filename has been provided.</tt></dd></dl> | |||
<dl><dt><a name="TemplateV2-process"><strong>process</strong></a>(self, data)</dt><dd><tt>Generate text for the given data.</tt></dd></dl> | |||
<hr> | |||
Static methods defined here:<br> | |||
<dl><dt><a name="TemplateV2-express"><strong>express</strong></a>(cls, text, **kwargs)</dt></dl> | |||
<hr> | |||
Methods inherited from <a href="template.html#Template">Template</a>:<br> | |||
<dl><dt><a name="TemplateV2-log"><strong>log</strong></a>(self, text)</dt><dd><tt>Print information</tt></dd></dl> | |||
<dl><dt><a name="TemplateV2-warning"><strong>warning</strong></a>(self, text)</dt><dd><tt>Prints a warning</tt></dd></dl> | |||
</td></tr></table></td></tr></table> | |||
</body></html> |
@@ -10,10 +10,8 @@ Part of KaiSD Text Tools | |||
License: GPLv3 | |||
''' | |||
from sys import argv | |||
from atg import ATG | |||
from data import CSVData | |||
from template import TemplateV2 | |||
from os.path import split | |||
from ktt import ATG, CSVData, TemplateV2 | |||
if __name__ == '__main__': | |||
if len(argv) == 3: | |||
@@ -1,482 +0,0 @@ | |||
#!/usr/bin/python | |||
# -*- coding: utf-8 -*- | |||
''' | |||
Template module for a KaiSD Text Tools. | |||
(c) 2013 Ivan "Kai SD" Korystin | |||
License: GPLv3 | |||
''' | |||
import re | |||
class Template: | |||
''' | |||
Empty template class. Generates empty text. | |||
''' | |||
def process(self, data): | |||
''' | |||
Replace this method in subclasses. | |||
''' | |||
return '' | |||
def warning(self, text): | |||
''' | |||
Prints a warning | |||
''' | |||
print text | |||
def log(self, text): | |||
''' | |||
Print information | |||
''' | |||
pass | |||
class TemplateV2(Template): | |||
''' | |||
Class for reading ATGv2 templates. | |||
ATGv2 template file should be a plain text file, starting with the line | |||
ATGV2 | |||
followed by the info line: | |||
[$KeyField$Extension$Prefix$Encoding$] | |||
where | |||
KeyField - is a name of a data column, that contains an identifier. | |||
Extension - is the desired extension for the generated files. | |||
Prefix - is the desired filename prefix for the generated files | |||
Encoding - is the desired encoding for the generated files. | |||
The line may also have some optional keywords before the closing bracket: | |||
oneFile$ - place all generated text into a single file instead of | |||
generating a file for each table row. | |||
After the info line, you can put your text. | |||
You can use following commands to handle the data: | |||
* [$Name$], where Name is the column header, | |||
will be replaced with value from the current row. | |||
* [$ATGLINDEX$] will be replaced with the number of a current row. | |||
* [$ATGHEADER$Text$] and [$ATGFOOTER$Text$] will place the given text | |||
at the begining or at the end of the file. You can't use other | |||
commands in this text. | |||
* [$ATGLIST$Name$Text$], where Name is a multi-column header | |||
(i.e. 'Col' will represent 'Col1', 'Col2', 'Col3' etc) | |||
will repeat the given text for each non-empty value. | |||
You can use other commands in Text. Also [$Name$] inside the list | |||
will be replaced with the value for the current row and column. | |||
* [$ATGLINDEX$] can be used only inside the ATGLIST text, | |||
will be replaced with the current column index. | |||
* [$ATGLISTCUT$Name$Text$] - same as ATGLIST, but the last symbol | |||
will be removed. Useful for removing unnecessary newlines. | |||
* [$ATGIF$Name$Value$Text$] will be replaced with the given text | |||
only if the the given column's value is the same as the given one. | |||
Will be replaced with the empty text otherwise. You can use other | |||
commands in Text. | |||
* [$ATGIFNOT$Name$Value$Text$] - same as ATGIF, but the column's value | |||
should not be equal to the given one. | |||
* [$ATGGREATER$Name$Value$Text$] - same as ATGIF, but the value should | |||
be the number and it should be greater then the given one. | |||
* [$ATGGREATER$Name$Value$Text$] - same as ATGGREATER, but the value | |||
should be less then the given one. | |||
* [$ATGREPLACE$Text1$Text2$] - Will replace Text1 with Text2. Replacements | |||
will be done after all other commands. You can't use regular expressions or | |||
other commands in the text. | |||
* [$ATGPREFIX$Text$] - Will add the given text to the filename prefix. | |||
You can use other commands in text, but do it carefully. | |||
* [$ATGSKIP$] - Skip the current row. Use only in combination with the | |||
ATGIF/ATGIFNOT, or you will generate nothing. | |||
* [$ATGPREV$Name$], where Name is the column header, | |||
will be replaced with the with the value of the given header from the | |||
previous row. ATGSKIP will be used for the first row. | |||
''' | |||
def __init__(self, filename=None, encoding='utf-8', text=''): | |||
''' | |||
Constructor. | |||
filename - name of the ATGv2 template file. | |||
encoding - encoding of the template file. | |||
text - text to use if no filename has been provided. | |||
''' | |||
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 | |||
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.header = 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 addHeader(index, flow, text): | |||
if self.header.find(text) < 0: | |||
self.header += text | |||
key = '[$ATGHEADER$' + text + '$]' | |||
return flow.replace(key,'') | |||
partCommands['ATGHEADER'] = addHeader | |||
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): | |||
''' | |||
Generate text for the given 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] = self.header + text + self.footer | |||
self.log('Created %s' % (element)) | |||
if self.oneFile: | |||
out = self.header + out + self.footer | |||
return out | |||
@staticmethod | |||
def express(cls, text, **kwargs): | |||
obj = cls() | |||
obj.text = text | |||
obj.keyField = kwargs.get('keyField', 'Index') | |||
obj.extension = kwargs.get('extension', '') | |||
obj.prefix = kwargs.get('prefix', '') | |||
obj.encoding = kwargs.get('encoding', 'utf-8') | |||
return obj |