Package concurrent_tree_crawler :: Module abstract_node
[hide private]
[frames] | no frames]

Source Code for Module concurrent_tree_crawler.abstract_node

1 -class NodeState:
2 """Enumeration describing state of processing of a certain node""" 3 4 OPEN = 0 5 """Node has not been yet traversed/visited by any crawler. 6 This is the initial state of each node.""" 7 8 PROCESSING = 1 9 """Node is currently processed by some crawler.""" 10 11 VISITED = 2 12 """Node has been visited by at least one crawler. It is an internal node. 13 There is at least one child of this node that is in a state of 14 OPEN or VISITED or PROCESSING.""" 15 16 CLOSED = 3 17 """The leaf node has been processed or all the children of 18 the internal node are in a CLOSED state. 19 Traversing children of this node by a new crawler would be pointless.""" 20 21 ERROR = 4 22 """1) A crawler was not able to analyze this node or 2) 23 all children nodes of this node are in a state of CLOSED or ERROR""" 24 25 MAX_ENUM_INDEX = ERROR 26 """A purely technical field indicating the maximal enumeration index""" 27 28 @staticmethod
29 - def to_str(state):
30 """@type state: L{NodeState} enum""" 31 if state == NodeState.OPEN: 32 return "OPEN" 33 elif state == NodeState.PROCESSING: 34 return "PROCESSING" 35 elif state == NodeState.VISITED: 36 return "VISITED" 37 elif state == NodeState.CLOSED: 38 return "CLOSED" 39 elif state == NodeState.ERROR: 40 return "ERROR" 41 else: 42 return None
43 44 @staticmethod
45 - def from_str(string):
46 """ 47 @return: enumeration corresponding to given string, C{None} if 48 we were unable to parse the string 49 @rtype: L{NodeState} enum 50 """ 51 if string == "OPEN": 52 return NodeState.OPEN 53 elif string == "PROCESSING": 54 return NodeState.PROCESSING 55 elif string == "VISITED": 56 return NodeState.VISITED 57 elif string == "CLOSED": 58 return NodeState.CLOSED 59 elif string == "ERROR": 60 return NodeState.ERROR 61 else: 62 return None
63
64 -class AbstractNode:
65 """A node representing a single element of the tree traversed by the 66 crawler""" 67
68 - def get_children_cond(self):
69 """ 70 @return: condition object related to the children of this node 71 @rtype: L{threading.Condition} 72 """ 73 raise NotImplementedError
74
75 - def get_name(self):
76 """ 77 @return: name of the node. It should be unique among children of 78 this node's parent""" 79 raise NotImplementedError
80
81 - def get_state(self):
82 """ 83 @return: state of the node 84 @rtype: L{NodeState} 85 """ 86 raise NotImplementedError
87
88 - def set_state(self, new_state):
89 """ 90 @param new_state: new state of the node 91 @type new_state: L{NodeState} 92 """ 93 raise NotImplementedError
94
95 - def get_parent(self):
96 """ 97 @rtype: L{AbstractNode}, it is C{None} if the node is the sentinel node 98 """ 99 raise NotImplementedError
100 101 ## OPTIMIZE?
102 - def update_and_get_child(self, possible_children_names):
103 """ 104 @rtype: L{AbstractNode} 105 """ 106 accessible_children = {NodeState.OPEN: None, 107 NodeState.VISITED: None, NodeState.PROCESSING: None} 108 for possible_name in possible_children_names: 109 if not self.has_child(possible_name): 110 self.add_child(possible_name, NodeState.OPEN) 111 child = self.get_child(possible_name) 112 state = child.get_state() 113 if state in accessible_children: 114 if accessible_children[state] is None: 115 accessible_children[state] = child 116 accessible_children_state_priority = [NodeState.OPEN, 117 NodeState.VISITED, NodeState.PROCESSING] 118 for state in accessible_children_state_priority: 119 if accessible_children[state] is not None: 120 return accessible_children[state] 121 return None
122
123 - def has_child(self, name):
124 """ 125 @return: True if node has child with given name 126 """ 127 raise NotImplementedError
128
129 - def get_child(self, name):
130 """ 131 @rtype: L{AbstractNode} 132 """ 133 raise NotImplementedError
134
135 - def get_children(self):
136 """ 137 @rtype: list of L{AbstractNode}s 138 """ 139 raise NotImplementedError
140
141 - def add_child(self, child_name, state):
142 """ 143 @type state: L{NodeState} 144 @return: added child node 145 @rtype: L{AbstractNode} 146 """ 147 raise NotImplementedError
148
149 - def all_children_are_in_one_of_states(self, states):
150 """ 151 @type states: set of L{NodeState}s 152 @return: C{True} iff all children are in one of the given states 153 """ 154 no_children_encountered = True 155 for state in xrange(NodeState.MAX_ENUM_INDEX+1): 156 if state not in states: 157 if self._has_children(state): 158 return False 159 else: 160 if self._has_children(state) > 0: 161 no_children_encountered = False 162 assert not no_children_encountered, "The given node has no children" 163 return True
164
165 - def _has_children(self, state):
166 """ 167 An auxiliary method used only by the 168 L{all_children_are_in_one_of_states} method 169 170 @type state: L{NodeState} 171 @return: C{True} iff the node has at least one child in given state 172 """ 173 raise NotImplementedError
174
175 - def __str__(self):
176 return "name=\"{}\", state=\"{}\"".format( 177 self.get_name(), NodeState.to_str(self.get_state()))
178