4
#===============================================================================
6
#===============================================================================
9
#4.0.264 - version update
15
from fnmatch import fnmatch
16
from flock import flock
20
logger = logging.getLogger('.'.join([os.path.splitext(os.path.basename(sys.argv[0]))[0],'manager','filtergraph',__name__]))
26
'deletezerolength': True,
38
deletezerolength = True
51
def open(self,parent,cfg):
53
self.stage = cfg['stage']
55
self.errors.append([__name__,'missing','[%s] \"stage=<missing>\"'%(__name__.split(',')[-1])])
56
logger.error('%s\t%s',*self.errors[-1][1:])
58
self.roottype = cfg['roottype'].strip(',').split(',')[0]
59
self.p.roottype = cfg['roottype'].strip(',').split(',')[0]
61
self.errors.append([__name__,'missing','[%s] \"roottype=<missing>\"'%(__name__.split(',')[-1])])
62
logger.error('%s\t%s',*self.errors[-1][1:])
63
self.append = 'a' if cfg['append'] else 'w'
64
self.deletezerolength = cfg['deletezerolength']
65
self.encoding = 'utf8' if 'utf8' in cfg['encoding'].lower().replace('-','') else cfg['encoding']
66
self.eol = '\x0d\x0a' if 'win' in cfg['eol'].lower() else '\x0a' if 'linux' in cfg['eol'].lower() or 'unix' in cfg['eol'].lower() or 'posix' in cfg['eol'].lower() else cfg['eol']
67
self.null = cfg['null']
68
self.rendertypes = os.extsep+cfg['rendertypes'].lstrip(os.extsep)
69
self.rootfolder = self.normalizeroot(cfg['rootfolder'])
70
self.safemode = cfg['safemode']
72
def run(self,fileobj,k=None,mode=None):
73
'''saves buffer to file'''
76
# skip if self.null set
79
# skip if k defined but not in fileobj
80
if k and not k in fileobj: return -2
82
keys = [k] if k else fileobj.keys()
86
# remove empty output buffers
88
result = self.__removeempty(fileobj,key)
89
if result: return result
91
# test if any removed buffers are 'tm' alignments and skip to avoid creating mis-aligned files
93
if not key in fileobj.keys() and len(key) > 3 and key[cf.kind] == 'tm':
96
# save when everything is ok
98
for key in fileobj.keys():
99
# update file extension to rendertypes
100
if not fnmatch(os.path.splitext(fileobj[key]['filelist'][cf.basename])[1],self.rendertypes):
101
fileobj[key]['filelist'][cf.basename] = fileobj[key]['filelist'][cf.basename]+self.rendertypes
102
result = self.__save(fileobj,key,mode) or result
106
def flush(self,fileobj,k=None):
107
'''move temp output files to server'''
111
result = -2 if self.__mkfolder(fileobj,k) else self.__push(fileobj,k)
113
# create destination folders (test write access)
114
for k in fileobj.keys():
115
result = self.__mkfolder(fileobj,k) or result
116
# move tempfile to output path
118
for k in fileobj.keys():
119
result = self.__push(fileobj,k) or result
120
for k in fileobj.keys():
127
def getroot(self,rootfolder):
128
'''Splits rootfolder to file system and rootfolder'''
129
folder = os.path.abspath(os.path.expanduser(rootfolder.rstrip().replace('/',os.sep).replace('\\',os.sep)))
130
if fnmatch(folder,'?:*'):
131
# DOS drive letter : folder
132
fss, folder = folder.split(':')
134
elif fnmatch(folder,'*:*'):
135
# ssh hostname : folder
136
fss, folder = folder.split(':')
138
elif fnmatch(folder,'\\\\*\\*'):
139
# MS Windows UNC \ folder
140
fss = '\\\\'+folder.lstrip(os.sep).split(os.sep)[0]
141
folder = folder.replace(fss,'')
145
folder = os.path.normpath(folder)
146
if folder == '.': folder = '*'
147
folder = folder.lstrip('\\/')
148
return [unicode(fss), unicode(folder)]
150
def normalizeroot(self,rootfolder):
151
return rootfolder.replace('\\',os.sep).replace('/',os.sep)
153
def __save(self,fileobj,k,mode):
154
mode = self.append if not mode else mode
156
f = codecs.open(fileobj[k]['tempname'],mode,self.encoding)
157
f.write('%s%s'%(self.eol.join(fileobj[k]['tempbuff']),self.eol))
160
logger.exception('%s\t%s - %s',*['failed',self.p.cfinput[k]['tempname'],str(e)])
162
logger.debug('%s\t%s',*['file',fileobj[k]['tempname']])
164
def __removeempty(self,fileobj,k):
165
if os.path.exists(os.sep.join(fileobj[k]['filelist'])) and self.safemode:
166
logger.warn('%s\t%s - %s',*['skip','output already exists',os.sep.join(fileobj[k]['filelist']),])
169
elif not sum([len(line.strip()) for line in fileobj[k]['tempbuff']]):
170
if not 'workbench' in fileobj[k]['filelist'][cf.stage] and not 'extract' in fileobj[k]['filelist'][cf.stage]:
171
logger.warn('%s\t%s - %s',*['skip','empty data',fileobj[k]['tempname']])
172
if os.path.exists(os.sep.join(fileobj[k]['filelist'])) and self.deletezerolength:
173
os.unlink(os.sep.join(fileobj[k]['filelist']))
175
os.removedirs(os.path.dirname(os.sep.join(fileobj[k]['filelist'])))
177
if not e.errno == 39:
178
logger.exception('%s\t%s, %s, %s',*['failed',e.errno,e.strerror,os.sep.join(fileobj[k]['filelist']),])
181
def __mkfolder(self,fileobj,k):
182
if os.path.exists(fileobj[k]['tempname']):
184
os.makedirs(os.path.dirname(os.sep.join(fileobj[k]['filelist'])))
186
if not e.errno == 17:
187
logger.exception('%s\t%s, %s, %s',*['failed',e.errno,e.strerror,e.filename,])
190
def __push(self,fileobj,k):
191
if not k in fileobj: return
192
if os.path.exists(fileobj[k]['tempname']):
194
shutil.move(fileobj[k]['tempname'],os.sep.join(fileobj[k]['filelist']))
198
logger.debug('%s\t%s',*['file',os.sep.join(fileobj[k]['filelist'])])
201
'''Command prompt help.'''
202
return "\n%s\n\tUsage:\n\tfrom %s import reader\n"%(
203
os.path.basename(sys.argv[0]),
204
os.path.splitext(os.path.basename(sys.argv[0]))[0]
207
licensetxt=u'''CorpusFiltergraph™ v4.0
208
Copyright © 2010-2012 Precision Translation Tools Co., Ltd.
210
This program is free software: you can redistribute it and/or modify
211
it under the terms of the GNU Lesser General Public License as published by
212
the Free Software Foundation, either version 3 of the License, or
213
(at your option) any later version.
215
This program is distributed in the hope that it will be useful,
216
but WITHOUT ANY WARRANTY; without even the implied warranty of
217
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
218
GNU Lesser General Public License for more details.
220
You should have received a copy of the GNU Lesser General Public License
221
along with this program. If not, see http://www.gnu.org/licenses/.
223
For more information, please contact Precision Translation Tools Co., Ltd.
224
at: http://www.precisiontranslationtools.com'''
226
if __name__ == "__main__":
229
sys.stdout.write(usage().encode('utf8')+'\n')