josh-gmail-backup 0.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|