josh-gmail-backup 0.104
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/gmail-backup +6 -0
- data/bin/gmail-backup-gui +6 -0
- data/gmail-backup-gui.pyo +0 -0
- data/gmail-backup-gui.sh +2 -0
- data/gmail-backup.gemspec +36 -0
- data/gmail-backup.pyo +0 -0
- data/gmail-backup.sh +2 -0
- data/gmb.gif +0 -0
- data/gmb.ico +0 -0
- data/gmb.pyo +0 -0
- data/svc/LICENSE.TXT +12 -0
- data/svc/__init__.py +0 -0
- data/svc/egg.py +166 -0
- data/svc/map.py +123 -0
- data/svc/osutils.py +67 -0
- data/svc/registry.py +171 -0
- data/svc/retrans.py +225 -0
- data/svc/scripting/__init__.py +1461 -0
- data/svc/scripting/conversions.py +157 -0
- data/svc/scripting/externals.py +580 -0
- data/svc/scripting/extractors.py +361 -0
- data/svc/scripting/help.py +173 -0
- data/svc/template.py +76 -0
- data/svc/utils.py +261 -0
- metadata +77 -0
@@ -0,0 +1,580 @@
|
|
1
|
+
# Copyright (C) 2008 Jan Svec and Filip Jurcicek
|
2
|
+
#
|
3
|
+
# YOU USE THIS TOOL ON YOUR OWN RISK!
|
4
|
+
#
|
5
|
+
# email: info@gmail-backup.com
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# Disclaimer of Warranty
|
9
|
+
# ----------------------
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, licensor provides
|
12
|
+
# this tool (and each contributor provides its contributions) on an "AS IS"
|
13
|
+
# BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
14
|
+
# implied, including, without limitation, any warranties or conditions of
|
15
|
+
# TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR
|
16
|
+
# PURPOSE. You are solely responsible for determining the appropriateness of
|
17
|
+
# using this work and assume any risks associated with your exercise of
|
18
|
+
# permissions under this license.
|
19
|
+
|
20
|
+
import sys
|
21
|
+
import os
|
22
|
+
import re
|
23
|
+
import time
|
24
|
+
import getpass
|
25
|
+
from copy import copy
|
26
|
+
from threading import Thread
|
27
|
+
from select import select
|
28
|
+
from subprocess import Popen, PIPE
|
29
|
+
|
30
|
+
from svc.egg import PythonEgg, MetaEgg
|
31
|
+
from svc.scripting import *
|
32
|
+
from svc.utils import sym, issequence
|
33
|
+
|
34
|
+
import warnings
|
35
|
+
|
36
|
+
Generator = sym('Generator')
|
37
|
+
AllowOverwrite = sym('AllowOverwrite')
|
38
|
+
OmitStdout = sym('OmitStdout')
|
39
|
+
AsyncMethod = sym('AsyncMethod')
|
40
|
+
# TODO:
|
41
|
+
# GNUargs = sym('GNUargs')
|
42
|
+
ExecGenerator = sym('ExecGenerator')
|
43
|
+
ExecList = sym('ExecList')
|
44
|
+
ExecStr = sym('ExecStr')
|
45
|
+
ExecNoStdout = sym('ExecNoStdout')
|
46
|
+
ExecAsync = sym('ExecAsync')
|
47
|
+
|
48
|
+
class ExternalError(OSError):
|
49
|
+
pass
|
50
|
+
|
51
|
+
class ExternalMethod(PythonEgg):
|
52
|
+
def __init__(self, file_name, name=None, args=[], logger=None, env=None, path=None, etype=ExecGenerator, pre_func=None, post_func=None):
|
53
|
+
super(ExternalMethod, self).__init__()
|
54
|
+
if path is None:
|
55
|
+
self.fileName = file_name
|
56
|
+
else:
|
57
|
+
self.fileName = os.path.join(path, file_name)
|
58
|
+
if name is None:
|
59
|
+
self.name = os.path.basename(file_name)
|
60
|
+
else:
|
61
|
+
self.name = name
|
62
|
+
self.args = args
|
63
|
+
self.logger = logger
|
64
|
+
self.env = env
|
65
|
+
if self.getExecuteMethod(etype) is None:
|
66
|
+
raise ValueError("Unknown execute type: %r" % etype)
|
67
|
+
self.etype = etype
|
68
|
+
self.pre_func = pre_func
|
69
|
+
self.post_func = post_func
|
70
|
+
|
71
|
+
def _logStderr(self, line):
|
72
|
+
if self.logger:
|
73
|
+
self.logger(self, line)
|
74
|
+
else:
|
75
|
+
sys.stderr.write(line)
|
76
|
+
|
77
|
+
def getOSEnv(self):
|
78
|
+
return dict(os.environ)
|
79
|
+
|
80
|
+
def getEnv(self):
|
81
|
+
e = self.getOSEnv()
|
82
|
+
if self._env is not None:
|
83
|
+
e.update(self._env)
|
84
|
+
return e
|
85
|
+
|
86
|
+
def setEnv(self, env):
|
87
|
+
self._env = env
|
88
|
+
|
89
|
+
def _strEnv(self, env):
|
90
|
+
ret = {}
|
91
|
+
for key, value in env.iteritems():
|
92
|
+
ret[key] = str(value)
|
93
|
+
return ret
|
94
|
+
|
95
|
+
def _strArgs(self, args):
|
96
|
+
return [str(a) for a in args]
|
97
|
+
|
98
|
+
def getArgs(self):
|
99
|
+
return self._args
|
100
|
+
|
101
|
+
def setArgs(self, args):
|
102
|
+
self._args = args
|
103
|
+
|
104
|
+
def execute(self, *args, **kwargs):
|
105
|
+
"""Executes program `fn` with cmdline `args` and in environment `env`
|
106
|
+
|
107
|
+
It would raise an ExternalError if the program `fn` returned non-zero
|
108
|
+
exit status. Environment of new process is initialized using
|
109
|
+
`self.getEnv` method and updated with `env`.
|
110
|
+
|
111
|
+
:Returns:
|
112
|
+
Generator yielding lines of stdout of `fn`
|
113
|
+
"""
|
114
|
+
stdin = kwargs.pop('stdin', None)
|
115
|
+
stdin_file = kwargs.pop('stdin_file', None)
|
116
|
+
stdout_file = kwargs.pop('stdout_file', None)
|
117
|
+
env = kwargs.pop('env', {})
|
118
|
+
|
119
|
+
if kwargs:
|
120
|
+
raise TypeError("Bad keyword arguments: %s" % kwargs.keys())
|
121
|
+
|
122
|
+
if stdin is not None and stdin_file is not None:
|
123
|
+
raise TypeError("You cannot use both stdin and stdin_file argument")
|
124
|
+
|
125
|
+
e = dict(self.getEnv())
|
126
|
+
e.update(env)
|
127
|
+
e = self._strEnv(e)
|
128
|
+
args = self._strArgs(self.args + list(args))
|
129
|
+
|
130
|
+
to_close = []
|
131
|
+
|
132
|
+
if stdin is not None:
|
133
|
+
stdin_func = iter(stdin)
|
134
|
+
stdin = PIPE
|
135
|
+
elif stdin_file is not None:
|
136
|
+
stdin_func = None
|
137
|
+
stdin = file(stdin_file, 'r')
|
138
|
+
to_close.append(stdin)
|
139
|
+
else:
|
140
|
+
stdin_func = None
|
141
|
+
stdin = None
|
142
|
+
|
143
|
+
if stdout_file is not None:
|
144
|
+
stdout = file(stdout_file, 'w')
|
145
|
+
to_close.append(stdout)
|
146
|
+
else:
|
147
|
+
stdout = PIPE
|
148
|
+
|
149
|
+
exec_list = [self.fileName] + args
|
150
|
+
if self.pre_func is not None:
|
151
|
+
self.pre_func(self, exec_list, env)
|
152
|
+
try:
|
153
|
+
process = Popen(exec_list, shell=False, env=e,
|
154
|
+
stdin=stdin, stdout=stdout, stderr=PIPE, bufsize=0)
|
155
|
+
except OSError, e:
|
156
|
+
raise ExternalError("Couldn't execute external method %r: %s" % (self.name, e))
|
157
|
+
|
158
|
+
stdin = process.stdin
|
159
|
+
stdout = process.stdout
|
160
|
+
stderr = process.stderr
|
161
|
+
if stdout_file is not None:
|
162
|
+
poll_r = [stderr]
|
163
|
+
else:
|
164
|
+
poll_r = [stdout, stderr]
|
165
|
+
if stdin_func is not None:
|
166
|
+
poll_w = [stdin]
|
167
|
+
else:
|
168
|
+
poll_w = []
|
169
|
+
|
170
|
+
while poll_r or poll_w:
|
171
|
+
readable, writeable, errorable = select(poll_r, poll_w, [])
|
172
|
+
|
173
|
+
if stderr in readable:
|
174
|
+
line = stderr.readline()
|
175
|
+
if not line:
|
176
|
+
stderr.close()
|
177
|
+
poll_r.remove(stderr)
|
178
|
+
else:
|
179
|
+
self._logStderr(line)
|
180
|
+
continue
|
181
|
+
|
182
|
+
if stdout in readable:
|
183
|
+
line = stdout.readline()
|
184
|
+
if not line:
|
185
|
+
stdout.close()
|
186
|
+
poll_r.remove(stdout)
|
187
|
+
else:
|
188
|
+
yield line
|
189
|
+
|
190
|
+
if stdin in errorable:
|
191
|
+
poll_w.remove(stdin)
|
192
|
+
elif stdin in writeable:
|
193
|
+
try:
|
194
|
+
stdin.write(stdin_func.next())
|
195
|
+
except StopIteration:
|
196
|
+
stdin.close()
|
197
|
+
poll_w.remove(stdin)
|
198
|
+
|
199
|
+
retcode = process.wait()
|
200
|
+
for f in to_close:
|
201
|
+
f.close()
|
202
|
+
if self.post_func is not None:
|
203
|
+
self.post_func(self, exec_list, env)
|
204
|
+
if retcode < 0:
|
205
|
+
raise ExternalError("External method %s (%r) killed by signal (%d)" % (self.name, ' '.join(exec_list), -retcode))
|
206
|
+
elif retcode > 0:
|
207
|
+
raise ExternalError("External method %s (%r) returned with nonzero exit status (%d)" % (self.name, ' '.join(exec_list), retcode))
|
208
|
+
|
209
|
+
def executeGenerator(self, *args, **kwargs):
|
210
|
+
return self.execute(*args, **kwargs)
|
211
|
+
|
212
|
+
__iter__ = executeGenerator
|
213
|
+
|
214
|
+
def executeList(self, *args, **kwargs):
|
215
|
+
return list(self.execute(*args, **kwargs))
|
216
|
+
|
217
|
+
def executeStr(self, *args, **kwargs):
|
218
|
+
return ''.join(self.execute(*args, **kwargs))
|
219
|
+
|
220
|
+
def executeNoStdout(self, *args, **kwargs):
|
221
|
+
for foo in self.execute(*args, **kwargs):
|
222
|
+
pass
|
223
|
+
|
224
|
+
def executeAsync(self, *args, **kwargs):
|
225
|
+
t = Thread(target=self.executeNoStdout, args=args, kwargs=kwargs)
|
226
|
+
t.setDaemon(False)
|
227
|
+
t.start()
|
228
|
+
return t
|
229
|
+
|
230
|
+
def getExecuteMethod(self, etype):
|
231
|
+
etype = str(etype)
|
232
|
+
if not etype.startswith('Exec'):
|
233
|
+
return None
|
234
|
+
etype = etype[4:]
|
235
|
+
return getattr(self, 'execute%s' % etype, None)
|
236
|
+
|
237
|
+
def __call__(self, *args, **kwargs):
|
238
|
+
m = self.getExecuteMethod(self.etype)
|
239
|
+
return m(*args, **kwargs)
|
240
|
+
|
241
|
+
def new(self, *args, **kwargs):
|
242
|
+
if 'stdin' in kwargs:
|
243
|
+
stdin = kwargs.pop('stdin')
|
244
|
+
else:
|
245
|
+
stdin = None
|
246
|
+
|
247
|
+
if 'env' in kwargs:
|
248
|
+
env = kwargs.pop('env')
|
249
|
+
else:
|
250
|
+
env = {}
|
251
|
+
|
252
|
+
if kwargs:
|
253
|
+
raise TypeError("Bad keyword arguments: %s" % kwargs.keys())
|
254
|
+
|
255
|
+
e = dict(self.getEnv())
|
256
|
+
e.update(env)
|
257
|
+
e = self._strEnv(e)
|
258
|
+
args = self._strArgs(self.args + list(args))
|
259
|
+
|
260
|
+
ret = copy(self)
|
261
|
+
ret.setArgs(args)
|
262
|
+
return ret
|
263
|
+
|
264
|
+
|
265
|
+
# Pipeline overloading
|
266
|
+
def __or__(left, right):
|
267
|
+
return Pipeline( (left, right) )
|
268
|
+
|
269
|
+
def __ror__(right, left):
|
270
|
+
return Pipeline( (left, right) )
|
271
|
+
|
272
|
+
def __rshift__(self, fn):
|
273
|
+
return Pipeline( (self,), redir_stdout=fn)
|
274
|
+
|
275
|
+
def __rrshift__(self, fn):
|
276
|
+
return Pipeline( (self,), redir_stdin=fn)
|
277
|
+
|
278
|
+
class Pipeline(PythonEgg):
|
279
|
+
def __init__(self, pipeline, redir_stdin=None, redir_stdout=None):
|
280
|
+
super(Pipeline, self).__init__()
|
281
|
+
self.setupPipeline(pipeline, redir_stdin, redir_stdout)
|
282
|
+
|
283
|
+
def setupPipeline(self, pipeline, redir_stdin, redir_stdout):
|
284
|
+
ret = []
|
285
|
+
|
286
|
+
no_stdin = False
|
287
|
+
|
288
|
+
for i, item in enumerate(pipeline):
|
289
|
+
first = (i==0)
|
290
|
+
last = (i==len(pipeline)-1)
|
291
|
+
|
292
|
+
item_callable = callable(item)
|
293
|
+
|
294
|
+
if not item_callable:
|
295
|
+
if first:
|
296
|
+
no_stdin = True
|
297
|
+
else:
|
298
|
+
raise ValueError("Items in pipeline must be callable")
|
299
|
+
|
300
|
+
if isinstance(item, Pipeline):
|
301
|
+
if first and item.redir_stdin is not None:
|
302
|
+
if redir_stdin:
|
303
|
+
raise ValueError("Input of pipeline is redirected")
|
304
|
+
else:
|
305
|
+
redir_stdin = item.redir_stdin
|
306
|
+
if last and item.redir_stdout is not None:
|
307
|
+
if redir_stdout:
|
308
|
+
raise ValueError("Output of pipeline is redirected")
|
309
|
+
else:
|
310
|
+
redir_stdout = item.redir_stdout
|
311
|
+
ret.extend(item._pipeline)
|
312
|
+
else:
|
313
|
+
if not callable(item):
|
314
|
+
if first:
|
315
|
+
no_stdin = True
|
316
|
+
else:
|
317
|
+
raise ValueError("Items in pipeline must be callable")
|
318
|
+
ret.append(item)
|
319
|
+
|
320
|
+
self._pipeline = tuple(ret)
|
321
|
+
self.no_stdin = no_stdin
|
322
|
+
self.redir_stdin = redir_stdin
|
323
|
+
self.redir_stdout = redir_stdout
|
324
|
+
|
325
|
+
def getOSEnv(self):
|
326
|
+
return dict(os.environ)
|
327
|
+
|
328
|
+
def _strEnv(self, env):
|
329
|
+
ret = {}
|
330
|
+
for key, value in env.iteritems():
|
331
|
+
ret[key] = str(value)
|
332
|
+
return ret
|
333
|
+
|
334
|
+
def execute(self, stdin=None, env={}):
|
335
|
+
e = self.getOSEnv()
|
336
|
+
e.update(env)
|
337
|
+
e = self._strEnv(e)
|
338
|
+
|
339
|
+
pipeline = self._pipeline
|
340
|
+
|
341
|
+
if self.no_stdin and stdin is not None:
|
342
|
+
raise ValueError("Pipeline doesn't have a stdin")
|
343
|
+
|
344
|
+
if self.redir_stdin and stdin is not None:
|
345
|
+
raise ValueError("Pipeline have a redirected stdin")
|
346
|
+
|
347
|
+
generator = stdin
|
348
|
+
for i, item in enumerate(pipeline):
|
349
|
+
first = (i==0)
|
350
|
+
last = (i==len(pipeline)-1)
|
351
|
+
|
352
|
+
if isinstance(item, ExternalMethod):
|
353
|
+
if not last:
|
354
|
+
method = item.executeGenerator
|
355
|
+
else:
|
356
|
+
method = item
|
357
|
+
kwargs = {}
|
358
|
+
if self.redir_stdin is not None and first:
|
359
|
+
kwargs['stdin_file'] = self.redir_stdin
|
360
|
+
else:
|
361
|
+
kwargs['stdin'] = generator
|
362
|
+
if self.redir_stdout is not None and last:
|
363
|
+
kwargs['stdout_file'] = self.redir_stdout
|
364
|
+
generator = method(env=e, **kwargs)
|
365
|
+
elif callable(item):
|
366
|
+
generator = item(generator)
|
367
|
+
else:
|
368
|
+
generator = item
|
369
|
+
return generator
|
370
|
+
|
371
|
+
def __call__(self, *args, **kwargs):
|
372
|
+
return self.execute(*args, **kwargs)
|
373
|
+
|
374
|
+
def __iter__(self):
|
375
|
+
return self.execute()
|
376
|
+
|
377
|
+
# Pipeline overloading
|
378
|
+
def __or__(left, right):
|
379
|
+
return Pipeline( (left, right) )
|
380
|
+
|
381
|
+
def __ror__(right, left):
|
382
|
+
return Pipeline( (left, right) )
|
383
|
+
|
384
|
+
def __rshift__(self, fn):
|
385
|
+
return Pipeline( (self,), redir_stdout=fn)
|
386
|
+
|
387
|
+
def __rrshift__(self, fn):
|
388
|
+
return Pipeline( (self,), redir_stdin=fn)
|
389
|
+
|
390
|
+
class MetaExternalMethods(MetaEgg):
|
391
|
+
def __init__(cls, name, bases, dict):
|
392
|
+
super(MetaExternalMethods, cls).__init__(name, bases, dict)
|
393
|
+
if cls.externalMethods:
|
394
|
+
cls.__bases__ = cls.__bases__ + (cls.createClassExternals(), )
|
395
|
+
|
396
|
+
def createClassExternals(cls):
|
397
|
+
class rClass(object):
|
398
|
+
pass
|
399
|
+
|
400
|
+
rClass.__name__ = '%sExternals' % cls.__name__
|
401
|
+
rClass.__module__ = cls.__module__
|
402
|
+
|
403
|
+
meth_dict = cls.unifyExternalMethods(cls.externalMethods)
|
404
|
+
done_dict = {}
|
405
|
+
|
406
|
+
for dir in cls.externalMethodDirs:
|
407
|
+
for meth_name in os.listdir(dir):
|
408
|
+
meth_path = os.path.join(dir, meth_name)
|
409
|
+
if meth_name in meth_dict:
|
410
|
+
# TODO: Check for inconsitencies in method specifiers
|
411
|
+
if Generator in meth_dict[meth_name]:
|
412
|
+
warnings.warn("Don't use Generator, use ExecGenerator instead", DeprecationWarning, 3)
|
413
|
+
meth = cls.createMethod(meth_name, meth_path, ExecGenerator)
|
414
|
+
elif OmitStdout in meth_dict[meth_name]:
|
415
|
+
warnings.warn("Don't use OmitStdout, use ExecNoStdout instead", DeprecationWarning, 3)
|
416
|
+
meth = cls.createMethod(meth_name, meth_path, ExecNoStdout)
|
417
|
+
elif AsyncMethod in meth_dict[meth_name]:
|
418
|
+
warnings.warn("Don't use AsyncMethod, use ExecAsync instead", DeprecationWarning, 3)
|
419
|
+
meth = cls.createMethod(meth_name, meth_path, ExecAsync)
|
420
|
+
elif ExecGenerator in meth_dict[meth_name]:
|
421
|
+
meth = cls.createMethod(meth_name, meth_path, ExecGenerator)
|
422
|
+
elif ExecNoStdout in meth_dict[meth_name]:
|
423
|
+
meth = cls.createMethod(meth_name, meth_path, ExecNoStdout)
|
424
|
+
elif ExecAsync in meth_dict[meth_name]:
|
425
|
+
meth = cls.createMethod(meth_name, meth_path, ExecAsync)
|
426
|
+
else:
|
427
|
+
meth = cls.createMethod(meth_name, meth_path, ExecList)
|
428
|
+
|
429
|
+
if ExScript.command in meth_dict[meth_name]:
|
430
|
+
meth = ExScript.command(meth)
|
431
|
+
child_meth = getattr(cls, meth_name, None)
|
432
|
+
if child_meth is not None and not ExScript.isCommand(child_meth):
|
433
|
+
raise TypeError("External method %r defined as ExScript.command, but method in derived class %r is not decorated" % \
|
434
|
+
(meth_name, cls.__name__))
|
435
|
+
|
436
|
+
if meth_name in done_dict and AllowOverwrite not in meth_dict[meth_name]:
|
437
|
+
raise TypeError("External method %r is defined in two different places: %r and %r" % \
|
438
|
+
(meth_name, done_dict[meth_name], dir))
|
439
|
+
setattr(rClass, meth_name, meth)
|
440
|
+
|
441
|
+
done_dict[meth_name] = dir
|
442
|
+
|
443
|
+
rest = set(meth_dict) - set(done_dict)
|
444
|
+
if rest:
|
445
|
+
raise ValueError('External method %r not found' % rest.pop())
|
446
|
+
|
447
|
+
return rClass
|
448
|
+
|
449
|
+
def unifyExternalMethods(cls, em):
|
450
|
+
ret = {}
|
451
|
+
for meth_name, specifiers in em.iteritems():
|
452
|
+
if issequence(specifiers):
|
453
|
+
ret[meth_name] = set(specifiers)
|
454
|
+
else:
|
455
|
+
ret[meth_name] = set([specifiers])
|
456
|
+
return ret
|
457
|
+
|
458
|
+
def createMethod(cls, name, path, etype):
|
459
|
+
def rMethod(self, *args, **kwargs):
|
460
|
+
meth = ExternalMethod(path, name=name, etype=etype,
|
461
|
+
logger=self._logExternalStderr, env=self._externalEnv,
|
462
|
+
pre_func=self._logPreExec, post_func=self._logPostExec)
|
463
|
+
return meth(*args, **kwargs)
|
464
|
+
|
465
|
+
cls.adoptMethod(rMethod, name)
|
466
|
+
return rMethod
|
467
|
+
|
468
|
+
def adoptMethod(cls, meth, name):
|
469
|
+
meth.__name__ = name
|
470
|
+
meth.__module__ = cls.__module__
|
471
|
+
|
472
|
+
|
473
|
+
class ExternalMethods(PythonEgg):
|
474
|
+
__metaclass__ = MetaExternalMethods
|
475
|
+
externalMethodDirs = []
|
476
|
+
externalMethods = {}
|
477
|
+
|
478
|
+
def _logPreExec(self, method, cmdline, env):
|
479
|
+
pass
|
480
|
+
|
481
|
+
def _logPostExec(self, method, cmdline, env):
|
482
|
+
pass
|
483
|
+
|
484
|
+
def _logExternalStderr(self, method, line):
|
485
|
+
sys.stdout.write(line)
|
486
|
+
|
487
|
+
def _getExternalEnv(self):
|
488
|
+
return os.environ
|
489
|
+
|
490
|
+
class ExternalScript(ExScript, ExternalMethods):
|
491
|
+
externalMethodDirs = []
|
492
|
+
externalMethods = {}
|
493
|
+
settingsFiles = []
|
494
|
+
|
495
|
+
def __init__(self, *args, **kwargs):
|
496
|
+
super(ExternalScript, self).__init__(*args, **kwargs)
|
497
|
+
self._settings = dict(os.environ)
|
498
|
+
|
499
|
+
def getSettings(self):
|
500
|
+
return self._settings
|
501
|
+
|
502
|
+
def sourceEnv(self, fn):
|
503
|
+
SKIP = ['PWD', 'SHLVL', '_']
|
504
|
+
env = Popen(['/bin/bash', '-c', 'source %s; env' % fn], env=self.settings, stdout=PIPE).communicate()[0]
|
505
|
+
for line in env.splitlines():
|
506
|
+
try:
|
507
|
+
name, val = line.split('=', 1)
|
508
|
+
except ValueError:
|
509
|
+
continue
|
510
|
+
if val.startswith('()'):
|
511
|
+
continue
|
512
|
+
if name in SKIP: continue
|
513
|
+
self.settings[name] = val
|
514
|
+
|
515
|
+
def storeEnv(self, fn, info={}):
|
516
|
+
AU = 'Author'
|
517
|
+
DT = 'Date'
|
518
|
+
FN = 'Filename'
|
519
|
+
info = dict(info)
|
520
|
+
|
521
|
+
info[AU] = getpass.getuser()
|
522
|
+
info[DT] = time.strftime('%Y-%m-%d-%H:%M:%S')
|
523
|
+
info[FN] = os.path.basename(fn)
|
524
|
+
key_order = [AU, DT, FN]
|
525
|
+
|
526
|
+
fw = file(fn, 'w')
|
527
|
+
try:
|
528
|
+
fw.write("#!/bin/bash\n\n")
|
529
|
+
while info:
|
530
|
+
if key_order:
|
531
|
+
key = key_order.pop(0)
|
532
|
+
else:
|
533
|
+
key = sorted(info)[0]
|
534
|
+
value = info.pop(key)
|
535
|
+
fw.write("# %20s: %s\n" % (key, value))
|
536
|
+
fw.write('\n')
|
537
|
+
|
538
|
+
for key, value in sorted(self.settings.items()):
|
539
|
+
value = str(value)
|
540
|
+
if key not in os.environ or value != os.environ[key]:
|
541
|
+
if re.search(r'\s', value):
|
542
|
+
fw.write('export %s="%s"\n' % (key, value))
|
543
|
+
else:
|
544
|
+
fw.write('export %s=%s\n' % (key, value))
|
545
|
+
|
546
|
+
fw.write("\n\n###########################\n# Operating environment #\n###########################\n\n")
|
547
|
+
for key, value in sorted(os.environ.items()):
|
548
|
+
if re.search(r'\s', value):
|
549
|
+
fw.write('# %s="%s"\n' % (key, value))
|
550
|
+
else:
|
551
|
+
fw.write('# %s=%s\n' % (key, value))
|
552
|
+
finally:
|
553
|
+
fw.close()
|
554
|
+
|
555
|
+
def _getExternalEnv(self):
|
556
|
+
return self.settings
|
557
|
+
|
558
|
+
def _logPreExec(self, method, cmdline, env):
|
559
|
+
self.logger.info('Running external method %s.%s (%r)', self.__class__.__name__, method.name, ' '.join(cmdline))
|
560
|
+
|
561
|
+
def _logExternalStderr(self, method, line):
|
562
|
+
for l in line.splitlines():
|
563
|
+
self.logger.error('%s.%s: %s', self.__class__.__name__, method.name, l)
|
564
|
+
|
565
|
+
def getManagerArgs(self):
|
566
|
+
m_args = super(ExternalScript, self).getManagerArgs()
|
567
|
+
m_args['specification'].update({
|
568
|
+
'__premain__.settings': (Multiple, String),
|
569
|
+
})
|
570
|
+
m_args['docs'].update({
|
571
|
+
'settings': "Additional shell files with settings",
|
572
|
+
})
|
573
|
+
return m_args
|
574
|
+
|
575
|
+
def premain(self, settings=[], **kwargs):
|
576
|
+
ret = super(ExternalScript, self).premain(**kwargs)
|
577
|
+
settings = self.settingsFiles + settings
|
578
|
+
for fn in settings:
|
579
|
+
self.sourceEnv(fn)
|
580
|
+
return ret
|