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
data/bin/gmail-backup
ADDED
Binary file
|
data/gmail-backup-gui.sh
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "gmail-backup"
|
3
|
+
s.version = "0.104"
|
4
|
+
s.date = "2008-10-15"
|
5
|
+
s.summary = "The ultimate one-click solution for doing backups of your GMail account"
|
6
|
+
s.email = "info@gmail-backup.com"
|
7
|
+
s.homepage = "http://www.gmail-backup.com/"
|
8
|
+
s.has_rdoc = false
|
9
|
+
s.authors = ["Jan Švec", "Filip Jurčíček"]
|
10
|
+
s.files = [
|
11
|
+
"gmail-backup-gui.pyo",
|
12
|
+
"gmail-backup-gui.sh",
|
13
|
+
"gmail-backup.gemspec",
|
14
|
+
"gmail-backup.pyo",
|
15
|
+
"gmail-backup.sh",
|
16
|
+
"gmb.gif",
|
17
|
+
"gmb.ico",
|
18
|
+
"gmb.pyo",
|
19
|
+
"svc/__init__.py",
|
20
|
+
"svc/egg.py",
|
21
|
+
"svc/LICENSE.TXT",
|
22
|
+
"svc/map.py",
|
23
|
+
"svc/osutils.py",
|
24
|
+
"svc/registry.py",
|
25
|
+
"svc/retrans.py",
|
26
|
+
"svc/scripting",
|
27
|
+
"svc/scripting/__init__.py",
|
28
|
+
"svc/scripting/conversions.py",
|
29
|
+
"svc/scripting/externals.py",
|
30
|
+
"svc/scripting/extractors.py",
|
31
|
+
"svc/scripting/help.py",
|
32
|
+
"svc/template.py",
|
33
|
+
"svc/utils.py"
|
34
|
+
]
|
35
|
+
s.executables = ["gmail-backup", "gmail-backup-gui"]
|
36
|
+
end
|
data/gmail-backup.pyo
ADDED
Binary file
|
data/gmail-backup.sh
ADDED
data/gmb.gif
ADDED
Binary file
|
data/gmb.ico
ADDED
Binary file
|
data/gmb.pyo
ADDED
Binary file
|
data/svc/LICENSE.TXT
ADDED
@@ -0,0 +1,12 @@
|
|
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 this tool (and each contributor provides its contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using this work and assume any risks associated with your exercise of permissions under this license.
|
12
|
+
|
data/svc/__init__.py
ADDED
File without changes
|
data/svc/egg.py
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2008 Jan Svec and Filip Jurcicek
|
3
|
+
#
|
4
|
+
# YOU USE THIS TOOL ON YOUR OWN RISK!
|
5
|
+
#
|
6
|
+
# email: info@gmail-backup.com
|
7
|
+
#
|
8
|
+
#
|
9
|
+
# Disclaimer of Warranty
|
10
|
+
# ----------------------
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, licensor provides
|
13
|
+
# this tool (and each contributor provides its contributions) on an "AS IS"
|
14
|
+
# BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
15
|
+
# implied, including, without limitation, any warranties or conditions of
|
16
|
+
# TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR
|
17
|
+
# PURPOSE. You are solely responsible for determining the appropriateness of
|
18
|
+
# using this work and assume any risks associated with your exercise of
|
19
|
+
# permissions under this license.
|
20
|
+
|
21
|
+
"""PythonEgg class module
|
22
|
+
"""
|
23
|
+
import inspect
|
24
|
+
|
25
|
+
from svc.utils import sym
|
26
|
+
|
27
|
+
class MetaEgg(type):
|
28
|
+
"""PythonEgg metaclass
|
29
|
+
"""
|
30
|
+
accessors = {
|
31
|
+
'get': ('getter', 0),
|
32
|
+
'is': ('getter', 0),
|
33
|
+
'set': ('setter', 1),
|
34
|
+
'del': ('deller', 0),
|
35
|
+
}
|
36
|
+
|
37
|
+
def __init__(cls, name, bases, dict):
|
38
|
+
cls.createProperties(dict)
|
39
|
+
super(MetaEgg, cls).__init__(name, bases, dict)
|
40
|
+
|
41
|
+
def createProperties(cls, dict):
|
42
|
+
props = {}
|
43
|
+
for name, object in dict.iteritems():
|
44
|
+
type, prop_name = cls.getPropertyDesc(name, object)
|
45
|
+
if type is None:
|
46
|
+
# No property
|
47
|
+
continue
|
48
|
+
item = props.setdefault(prop_name, {})
|
49
|
+
if type in item:
|
50
|
+
raise ValueError('More than one access method (%r) for property %r' \
|
51
|
+
% (item[type], prop_name))
|
52
|
+
item[type] = name
|
53
|
+
for prop_name in props:
|
54
|
+
d = cls.getAccessors(prop_name)
|
55
|
+
getter = d['getter']
|
56
|
+
setter = d['setter']
|
57
|
+
deller = d['deller']
|
58
|
+
setattr(cls, prop_name, property(getter, setter, deller))
|
59
|
+
|
60
|
+
@classmethod
|
61
|
+
def getPropertyDesc(cls, name, object):
|
62
|
+
NO_PROPERTY = None, None
|
63
|
+
if not inspect.isfunction(object):
|
64
|
+
return NO_PROPERTY
|
65
|
+
|
66
|
+
protected = False
|
67
|
+
if name[0] == '_':
|
68
|
+
protected = True
|
69
|
+
name = name[1:]
|
70
|
+
|
71
|
+
for prefix, (type, argcount) in cls.accessors.iteritems():
|
72
|
+
obj_argcount = object.func_code.co_argcount - 1 # Minus one for 'self'
|
73
|
+
if name.startswith(prefix) and obj_argcount == argcount:
|
74
|
+
name = name[len(prefix):]
|
75
|
+
if not name:
|
76
|
+
# Skip empty property name
|
77
|
+
continue
|
78
|
+
break
|
79
|
+
else:
|
80
|
+
return NO_PROPERTY
|
81
|
+
|
82
|
+
name = cls._suffixToProperty(name)
|
83
|
+
|
84
|
+
if protected:
|
85
|
+
name = '_' + name
|
86
|
+
|
87
|
+
return type, name
|
88
|
+
|
89
|
+
@classmethod
|
90
|
+
def _suffixToProperty(cls, suffix):
|
91
|
+
"""Converts suffix of attribute into property name
|
92
|
+
|
93
|
+
Examples:
|
94
|
+
getValue(), suffix 'Value', property 'value'
|
95
|
+
getSomeValue() 'SomeValue' 'someValue'
|
96
|
+
getASR() 'ASR' 'ASR'
|
97
|
+
getX() 'X' 'x'
|
98
|
+
"""
|
99
|
+
if len(suffix) == 1:
|
100
|
+
# One-char property name
|
101
|
+
return suffix.lower()
|
102
|
+
elif suffix[0].isupper() and suffix[1].islower():
|
103
|
+
# Word property like SomeProperty --> someProperty
|
104
|
+
return suffix[0].lower() + suffix[1:]
|
105
|
+
else:
|
106
|
+
# Word property like ASR --> ASR
|
107
|
+
return suffix
|
108
|
+
|
109
|
+
@classmethod
|
110
|
+
def _propertyToSuffix(cls, pname):
|
111
|
+
"""Inversion to _suffixToProperty()
|
112
|
+
"""
|
113
|
+
return pname[0].upper() + pname[1:]
|
114
|
+
|
115
|
+
def getAccessors(cls, name):
|
116
|
+
if name[0] == '_':
|
117
|
+
name = name[1:]
|
118
|
+
prefix = '_'
|
119
|
+
else:
|
120
|
+
prefix = ''
|
121
|
+
pname = cls._propertyToSuffix(name)
|
122
|
+
ret = {}
|
123
|
+
for method, (type, argcount) in cls.accessors.iteritems():
|
124
|
+
accessor = getattr(cls, '%s%s%s' % (prefix, method, pname), None)
|
125
|
+
ret[type] = accessor
|
126
|
+
return ret
|
127
|
+
|
128
|
+
class PythonEgg(object):
|
129
|
+
"""PythonEgg class
|
130
|
+
|
131
|
+
Main features:
|
132
|
+
- auto-creation of properties
|
133
|
+
"""
|
134
|
+
|
135
|
+
__metaclass__ = MetaEgg
|
136
|
+
|
137
|
+
def __init__(self, *args, **kwargs):
|
138
|
+
self._createMetaAttributes()
|
139
|
+
super(PythonEgg, self).__init__(*args, **kwargs)
|
140
|
+
|
141
|
+
def _createMetaAttributes(self):
|
142
|
+
for name, value in self.__class__.__dict__.iteritems():
|
143
|
+
if self._isMetaAttribute(name, value):
|
144
|
+
setattr(self, name, value(self))
|
145
|
+
|
146
|
+
def _isMetaAttribute(self, name, attr_value):
|
147
|
+
if isinstance(attr_value, MetaAttribute):
|
148
|
+
return True
|
149
|
+
if inspect.isclass(attr_value) \
|
150
|
+
and issubclass(attr_value, AttributeClass):
|
151
|
+
return True
|
152
|
+
|
153
|
+
class MetaAttribute(PythonEgg):
|
154
|
+
def __init__(self, creator, *args, **kwargs):
|
155
|
+
super(MetaAttribute, self).__init__()
|
156
|
+
self._creator = creator
|
157
|
+
self._args = args
|
158
|
+
self._kwargs = kwargs
|
159
|
+
|
160
|
+
def __call__(self, owner):
|
161
|
+
return self._creator(owner, *self._args, **self._kwargs)
|
162
|
+
|
163
|
+
class AttributeClass(PythonEgg):
|
164
|
+
def __init__(self, owner):
|
165
|
+
self.owner = owner
|
166
|
+
super(AttributeClass, self).__init__()
|
data/svc/map.py
ADDED
@@ -0,0 +1,123 @@
|
|
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 codecs
|
21
|
+
from svc.egg import PythonEgg
|
22
|
+
|
23
|
+
class HalfMap(PythonEgg, dict):
|
24
|
+
def __init__(self, *args, **kwargs):
|
25
|
+
super(HalfMap, self).__init__(*args, **kwargs)
|
26
|
+
self.setindex(0)
|
27
|
+
|
28
|
+
def newindex(self):
|
29
|
+
v = set(self.itervalues())
|
30
|
+
while self._index in v:
|
31
|
+
self._index += 1
|
32
|
+
return self._index
|
33
|
+
|
34
|
+
def setindex(self, value):
|
35
|
+
self._index = value
|
36
|
+
|
37
|
+
def add(self, key):
|
38
|
+
if key not in self:
|
39
|
+
value = self.newindex()
|
40
|
+
self[key] = value
|
41
|
+
return value
|
42
|
+
else:
|
43
|
+
return self[key]
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def readFromFile(cls, fn, encoding='utf-8', format=(unicode, int)):
|
47
|
+
fr = codecs.open(fn, 'r', encoding)
|
48
|
+
try:
|
49
|
+
ret = cls()
|
50
|
+
for line in fr:
|
51
|
+
split = line.split()
|
52
|
+
if len(split) == 0:
|
53
|
+
continue
|
54
|
+
elif len(split) != 2:
|
55
|
+
raise ValueError("Bad line in file %r: %r" % (fn, line))
|
56
|
+
key, value = split
|
57
|
+
key = format[0](key)
|
58
|
+
value = format[1](value)
|
59
|
+
ret[key] = value
|
60
|
+
return ret
|
61
|
+
finally:
|
62
|
+
fr.close()
|
63
|
+
|
64
|
+
def writeToFile(self, fn, encoding='utf-8'):
|
65
|
+
fw = codecs.open(fn, 'w', encoding)
|
66
|
+
try:
|
67
|
+
for k, v in sorted(self.items()):
|
68
|
+
fw.write('%s\t%s\n' % (k, v))
|
69
|
+
finally:
|
70
|
+
fw.close()
|
71
|
+
|
72
|
+
_unique_value = ['unique_value']
|
73
|
+
|
74
|
+
class SymMap(HalfMap):
|
75
|
+
def __init__(self, source=None, _inv=None):
|
76
|
+
super(SymMap, self).__init__()
|
77
|
+
if _inv is None:
|
78
|
+
self.inverse = self.__class__(_inv=self)
|
79
|
+
else:
|
80
|
+
self.inverse = _inv
|
81
|
+
if source is not None:
|
82
|
+
i = 0
|
83
|
+
for key, value in dict(source).iteritems():
|
84
|
+
self[key] = value
|
85
|
+
i += 1
|
86
|
+
self.setindex(i)
|
87
|
+
|
88
|
+
def clear(self, _inv=False):
|
89
|
+
super(SymMap, self).clear()
|
90
|
+
if not _inv:
|
91
|
+
self.inverse.clear(_inv=True)
|
92
|
+
|
93
|
+
def pop(self, *args):
|
94
|
+
ret = super(SymMap, self).pop(*args)
|
95
|
+
self.inverse.__delitem__(ret, _inv=True)
|
96
|
+
return ret
|
97
|
+
|
98
|
+
def popitem(self):
|
99
|
+
key, value = super(SymMap, self).popitem()
|
100
|
+
self.inverse.__delitem__(value, _inv=True)
|
101
|
+
return key, value
|
102
|
+
|
103
|
+
def setdefault(self, key, value=None):
|
104
|
+
raise NotImplementedError("Method SymMap.setdefault() is not implemented")
|
105
|
+
|
106
|
+
def __setitem__(self, key, value, _inv=False):
|
107
|
+
# FIXME:
|
108
|
+
# x = SymMap([(1, 2), (2, 3), (3, 4), (4, 1)])
|
109
|
+
# x[1] = 3
|
110
|
+
# x == {1: 3, 3: 4, 4: 1} ## Missing key 2
|
111
|
+
if key in self:
|
112
|
+
old_value = self[key]
|
113
|
+
self.inverse.__delitem__(old_value, _inv=True)
|
114
|
+
super(SymMap, self).__setitem__(key, value)
|
115
|
+
if not _inv:
|
116
|
+
self.inverse.__setitem__(value, key, _inv=True)
|
117
|
+
|
118
|
+
def __delitem__(self, key, _inv=False):
|
119
|
+
value = self[key]
|
120
|
+
super(SymMap, self).__delitem__(key)
|
121
|
+
if not _inv:
|
122
|
+
self.inverse.__delitem__(value, _inv=True)
|
123
|
+
|
data/svc/osutils.py
ADDED
@@ -0,0 +1,67 @@
|
|
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 os
|
21
|
+
|
22
|
+
def fsplit(path):
|
23
|
+
"""Recursive call of `os.path.split`
|
24
|
+
|
25
|
+
It splits `path` by recursive calling of `os.path.split` and returns lists
|
26
|
+
of path elements.
|
27
|
+
|
28
|
+
:RType: list
|
29
|
+
"""
|
30
|
+
ret = []
|
31
|
+
while path not in ['', '/']:
|
32
|
+
path, last = os.path.split(path)
|
33
|
+
ret.insert(0, last)
|
34
|
+
if path:
|
35
|
+
ret.insert(0, path)
|
36
|
+
return ret
|
37
|
+
|
38
|
+
def fjoin(path):
|
39
|
+
"""Recursive call of `os.path.join`
|
40
|
+
|
41
|
+
It joins path elements given by list `path` into single string using
|
42
|
+
`os.path.join`.
|
43
|
+
|
44
|
+
:RType: str
|
45
|
+
"""
|
46
|
+
ret = path[0]
|
47
|
+
for i in range(1, len(path)):
|
48
|
+
ret = os.path.join(ret, path[i])
|
49
|
+
return ret
|
50
|
+
|
51
|
+
def mkdirp(path):
|
52
|
+
"""Make directory `path` possibly creating its parents
|
53
|
+
|
54
|
+
If some of parent paths exists, nothing will happen. But if this path is
|
55
|
+
not a directory, OSError will be raised.
|
56
|
+
"""
|
57
|
+
path = fsplit(path)
|
58
|
+
full = ''
|
59
|
+
for elm in path:
|
60
|
+
full = os.path.join(full, elm)
|
61
|
+
if os.path.exists(full):
|
62
|
+
if not os.path.isdir(full):
|
63
|
+
raise OSError("Path %r is not directory" % full)
|
64
|
+
else:
|
65
|
+
os.mkdir(full)
|
66
|
+
|
67
|
+
|
data/svc/registry.py
ADDED
@@ -0,0 +1,171 @@
|
|
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
|
+
class AbstractRegistry(object):
|
21
|
+
def __init__(self):
|
22
|
+
super(AbstractRegistry, self).__init__()
|
23
|
+
self._children = set()
|
24
|
+
self._setParent(None)
|
25
|
+
self.setName(None)
|
26
|
+
|
27
|
+
def getPath(self):
|
28
|
+
ret = [self]
|
29
|
+
while True:
|
30
|
+
parent = ret[0].getParent()
|
31
|
+
if parent is None:
|
32
|
+
break
|
33
|
+
else:
|
34
|
+
ret.insert(0, parent)
|
35
|
+
return ret
|
36
|
+
|
37
|
+
def getParent(self):
|
38
|
+
return self.__dict__['_parent']
|
39
|
+
|
40
|
+
def _setParent(self, parent):
|
41
|
+
self.__dict__['_parent'] = parent
|
42
|
+
|
43
|
+
def getName(self):
|
44
|
+
return self._name
|
45
|
+
|
46
|
+
def setName(self, name):
|
47
|
+
parent = self.getParent()
|
48
|
+
if parent is not None:
|
49
|
+
raise ValueError("setName() requires that parent == None")
|
50
|
+
self._name = name
|
51
|
+
|
52
|
+
def getFullName(self):
|
53
|
+
def mapper(obj):
|
54
|
+
name = obj.getName()
|
55
|
+
if name is None: return '<anon>'
|
56
|
+
else: return name
|
57
|
+
return '.'.join(mapper(obj) for obj in self.getPath())
|
58
|
+
|
59
|
+
def addChild(self, child):
|
60
|
+
my_path = self.getPath()
|
61
|
+
if child in my_path:
|
62
|
+
raise ValueError("You cannot create cycles, child %r is parent of %r" % (child, self))
|
63
|
+
old_parent = child.getParent()
|
64
|
+
if old_parent is not None:
|
65
|
+
old_parent.delChild(child)
|
66
|
+
child._setParent(self)
|
67
|
+
self._children.add(child)
|
68
|
+
|
69
|
+
def delChild(self, child):
|
70
|
+
child._setParent(None)
|
71
|
+
self._children.remove(child)
|
72
|
+
|
73
|
+
def getChildren(self):
|
74
|
+
return self._children
|
75
|
+
|
76
|
+
def __setattr__(self, name, obj):
|
77
|
+
if hasattr(obj, '_setParent'):
|
78
|
+
if hasattr(obj, 'setName'):
|
79
|
+
obj.setName(name)
|
80
|
+
self.addChild(obj)
|
81
|
+
self.__dict__[name] = obj
|
82
|
+
|
83
|
+
def __delattr__(self, name):
|
84
|
+
obj = getattr(self, name)
|
85
|
+
if obj in self.getChildren():
|
86
|
+
self.delChild(obj)
|
87
|
+
if hasattr(obj, 'setName'):
|
88
|
+
obj.setName(None)
|
89
|
+
del self.__dict__[name]
|
90
|
+
|
91
|
+
def _createMethod(self, name, pre_func=None, post_func=None):
|
92
|
+
def method(*args, **kwargs):
|
93
|
+
objects = iter(self)
|
94
|
+
if pre_func is not None:
|
95
|
+
objects = pre_func(objects)
|
96
|
+
retvals = (obj(*args, **kwargs) for obj in objects)
|
97
|
+
if post_func is not None:
|
98
|
+
return post_func(retvals)
|
99
|
+
else:
|
100
|
+
return list(retvals)
|
101
|
+
method.__name__ = name
|
102
|
+
setattr(self, name, method)
|
103
|
+
|
104
|
+
def createSequent(self, name, reduce=None, obs_name=None):
|
105
|
+
if obs_name is None:
|
106
|
+
obs_name = name
|
107
|
+
def pre_func(objects):
|
108
|
+
return (getattr(o, obs_name) for o in objects)
|
109
|
+
self._createMethod(name, pre_func=pre_func, post_func=reduce)
|
110
|
+
|
111
|
+
def createDirectSequent(self, name, reduce=None):
|
112
|
+
self._createMethod(name, post_func=reduce)
|
113
|
+
|
114
|
+
def createQuery(self, name, obs_name=None):
|
115
|
+
if obs_name is None:
|
116
|
+
obs_name = name
|
117
|
+
def pre_func(objects):
|
118
|
+
return (getattr(o, obs_name) for o in objects)
|
119
|
+
def post_func(retvals):
|
120
|
+
for o in retvals:
|
121
|
+
if o is not None:
|
122
|
+
return o
|
123
|
+
self._createMethod(name, pre_func=pre_func, post_func=post_func)
|
124
|
+
|
125
|
+
def createDirectQuery(self, name):
|
126
|
+
def post_func(retvals):
|
127
|
+
for o in retvals:
|
128
|
+
if o is not None:
|
129
|
+
return o
|
130
|
+
self._createMethod(name, post_func=post_func)
|
131
|
+
|
132
|
+
def createChain(self, name, obs_name=None):
|
133
|
+
if obs_name is None:
|
134
|
+
obs_name = name
|
135
|
+
def method(args):
|
136
|
+
for o in self:
|
137
|
+
func = getattr(o, obs_name)
|
138
|
+
args = func(args)
|
139
|
+
return args
|
140
|
+
method.__name__ = name
|
141
|
+
setattr(self, name, method)
|
142
|
+
|
143
|
+
def createDirectChain(self, name):
|
144
|
+
def method(args):
|
145
|
+
for o in self:
|
146
|
+
args = o(args)
|
147
|
+
return args
|
148
|
+
method.__name__ = name
|
149
|
+
setattr(self, name, method)
|
150
|
+
|
151
|
+
|
152
|
+
class Registry(AbstractRegistry, list):
|
153
|
+
def __repr__(self):
|
154
|
+
return "<registry %s: [%s]>" % (self.getFullName(), ', '.join(repr(obj) for obj in self))
|
155
|
+
|
156
|
+
def __eq__(self, other):
|
157
|
+
if isinstance(other, Registry):
|
158
|
+
return self is other
|
159
|
+
else:
|
160
|
+
return super(Registry, self).__eq__(other)
|
161
|
+
|
162
|
+
def __hash__(self):
|
163
|
+
return id(self)
|
164
|
+
|
165
|
+
|
166
|
+
def register(registry):
|
167
|
+
def decorator(func):
|
168
|
+
registry.append(func)
|
169
|
+
return func
|
170
|
+
return decorator
|
171
|
+
|