1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
'''
Generic Hierarchic Objects Module
Hierobj's store their children (which can be anything) in their
__childlist__ attribute, and provide methods for walking the
hierarchy, either collecting results or not.
The index function returns an index of the objects (effectively a
flattened copy of the hierarchy)
97-03-17 Added ability to pass arguments to hier_rapply and hier_rreturn.
97-10-31 Removed dependencies on mcf.store
'''
import copy,types
import singletonlist, hier_rx
class Hierobj:
'''
An abstract class which handles hierarchic functions and information
# remade as a DAG 97-04-02, also reduced memory overhead for
hier-r* functions by using while-del-IndexError construct versus
for loop (probably makes it slower though)
If you require a true hierarchy, use the TrueHierobj class below...
'''
def __init__(self, parent=None, childlist=None):
if parent is None: # passed no parents
self.__dict__['__parent__'] = []
elif type(parent) == types.ListType: # passed a list of parents
self.__dict__['__parent__'] = parent
else: # passed a single parent
self.__dict__['__parent__'] = [parent]
self.__dict__['__childlist__'] = childlist or []
for child in self.__childlist__:
try:
child.__parent__.append(self)
except:
pass
# import simple hierarchic processing methods
hier_rapply = hier_rx.hier_rapply
hier_rreturn = hier_rx.hier_rreturn
hier_rgetattr = hier_rx.hier_rgetattr
hier_rmethod = hier_rx.hier_rmethod
def hier_addchild(self, child):
'''
Add a single child to the childlist
'''
self.__childlist__.append(child)
try:
# Hierobj-aware child
child.__parent__.append(self) # raises error if not hier_obj aware
except (TypeError, AttributeError):
# Non Hierobj-aware child
pass
append = hier_addchild
def hier_remchild(self, child):
'''
Breaks the child relationship with child, including the
reciprocal parent relationship
'''
try:
self.__childlist__.remove(child)
try:
child.hier_remparent(self) # if this fails, no problem
except AttributeError: pass
except (AttributeError,ValueError):
return 0 # didn't manage to remove the child
return 1 # succeeded
def hier_remparent(self, parent):
'''
Normally only called by hier_remchild of the parent,
just removes the parent from the child's parent list,
but leaves child in parent's childlist
'''
try:
self.__parent__.remove(parent)
except (AttributeError,ValueError):
return 0
return 1
def hier_replacewith(self,newel):
'''
As far as the hierarchy is concerned, the new element
is exactly the same as the old element, it has all
the same children, all the same parents. The old
element becomes completely disconnected from the hierarchy,
but it still retains all of its references
For every parent, replace this as a child
For every child, replace this as the parent
'''
for parent in self.__parent__:
try:
parent.hier_replacechild(self, newel)
except AttributeError:
pass
for child in self.__childlist__:
try:
child.hier_replaceparent(self,parent)
except AttributeError:
pass
def hier_replaceparent(self, oldparent, newparent):
ind = self.__parent__.index(oldparent)
self.__parent__[ind] = newparent
def hier_replacechild(self, oldchild, newchild):
ind = self.__childlist__.index(oldchild)
self.__childlist__[ind] = newchild
class TrueHierobj(Hierobj):
'''
An inefficient implementation of an Hierobj which limits the
__parent__ attribute to a single element. This will likely be
_slower_ than an equivalent Hierobj. That will have to be fixed
eventually.
'''
def __init__(self, parent=None, childlist=[]):
if parent is None: # passed no parents
self.__dict__['__parent__'] = singletonlist.SingletonList()
else: # passed a single parent
self.__dict__['__parent__'] = singletonlist.SingletonList(parent)
self.__dict__['__childlist__'] = copy.copy(childlist)
for child in self.__childlist__:
try:
child.__parent__.append(self)
except:
pass
def index(grove):
'''
Returns a flattened version of the grove
'''
return grove.hier_rreturn(lambda x: x)
|