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
43
44 @staticmethod
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
65 """A node representing a single element of the tree traversed by the
66 crawler"""
67
69 """
70 @return: condition object related to the children of this node
71 @rtype: L{threading.Condition}
72 """
73 raise NotImplementedError
74
76 """
77 @return: name of the node. It should be unique among children of
78 this node's parent"""
79 raise NotImplementedError
80
82 """
83 @return: state of the node
84 @rtype: L{NodeState}
85 """
86 raise NotImplementedError
87
89 """
90 @param new_state: new state of the node
91 @type new_state: L{NodeState}
92 """
93 raise NotImplementedError
94
96 """
97 @rtype: L{AbstractNode}, it is C{None} if the node is the sentinel node
98 """
99 raise NotImplementedError
100
101
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
124 """
125 @return: True if node has child with given name
126 """
127 raise NotImplementedError
128
130 """
131 @rtype: L{AbstractNode}
132 """
133 raise NotImplementedError
134
136 """
137 @rtype: list of L{AbstractNode}s
138 """
139 raise NotImplementedError
140
142 """
143 @type state: L{NodeState}
144 @return: added child node
145 @rtype: L{AbstractNode}
146 """
147 raise NotImplementedError
148
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
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
178