Skip to content

Commit 14b4416

Browse files
committed
Add partial visitation
1 parent 955cf5b commit 14b4416

6 files changed

Lines changed: 54 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelogs
22

3+
## Version 1.1.0
4+
(Released : April 16, 2021) : tag 1.1.0
5+
* Fix documentation
6+
* Add utility method at node level (get_predecessors/get_successors)
7+
* Add possibility to visitation of the graph from anywhere (starting provided node) as it would have been expected seeing the API
8+
39
## Version 1.0.0
410
(Released : April 2, 2021) : tag 1.0.0
511
* Complete documentation
@@ -29,6 +35,7 @@
2935
## Feature todo
3036

3137
* ~~Delete node~~
38+
* ~~Partial graph traversal~~
3239

3340
## Testing todo
3441

freexgraph/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@
3232

3333

3434
def version() -> str:
35+
"""Retrieve used version of FreExGraph library"""
3536
from freexgraph._version import __version__
36-
3737
return __version__

freexgraph/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2222
# SOFTWARE.
2323

24-
__version__ = "1.0.0"
24+
__version__ = "1.1.0"

freexgraph/visitor.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@ def _get_len(sorted_node_list: List[Tuple], with_progress_bar: bool) -> int:
3535
return len([n for n in sorted_node_list])
3636

3737

38+
def _filter_graph_root_for_visitation(root: FreExNode, is_reversed: bool):
39+
depth: int = root.depth
40+
sorted_node_list = list(nx.lexicographical_topological_sort(root.graph_ref))
41+
if is_reversed:
42+
sorted_node_list = list(reversed(sorted_node_list))
43+
44+
if depth == 0:
45+
return sorted_node_list
46+
node_content = [
47+
root.graph_ref.nodes[node_id]["content"] for node_id in sorted_node_list
48+
]
49+
if is_reversed:
50+
return [n.id for n in node_content if n.depth <= depth and n.id != root.id]
51+
return [n.id for n in node_content if n.depth >= depth and n.id != root.id]
52+
53+
3854
class AbstractVisitor:
3955
"""Base class for Visitor.
4056
@@ -74,10 +90,7 @@ def visit(self, root: FreExNode) -> bool:
7490
def apply_visitation_(self, root: FreExNode) -> bool:
7591
"""do not override / directly use. Internal visitation method, use visit(root) instead"""
7692

77-
sorted_node_list = list(nx.lexicographical_topological_sort(root.graph_ref))
78-
79-
if self.is_reversed:
80-
sorted_node_list = list(reversed(sorted_node_list))
93+
sorted_node_list = _filter_graph_root_for_visitation(root, self.is_reversed)
8194

8295
with tqdm(
8396
total=_get_len(sorted_node_list, self.with_progress_bar),
@@ -185,10 +198,7 @@ def visit(self, root: FreExNode) -> bool:
185198
return to_continue
186199

187200
def _composed_visit(self, root: FreExNode) -> bool:
188-
sorted_node_list = list(nx.lexicographical_topological_sort(root.graph_ref))
189-
190-
if self._is_reversed:
191-
sorted_node_list = list(reversed(sorted_node_list))
201+
sorted_node_list = _filter_graph_root_for_visitation(root, self._is_reversed)
192202

193203
with tqdm(
194204
total=_get_len(sorted_node_list, self._with_progress_bar),

recipe.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
python38.pkgs.buildPythonPackage rec {
55
pname = "freexgraph";
6-
version = "1.0.0";
6+
version = "1.1.0";
77

88
src = if (builtins.isNull use_revision || use_revision == "") then
99
nix-gitignore.gitignoreSource [ ".git" ] ./.

test/basic_freexgraph_test.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
from typing import Optional
2828

29+
from freexgraph.standard_visitor import FindFirstVisitor
2930
from freexgraph import GraphNode, FreExNode, FreExGraph
3031

3132

@@ -348,7 +349,6 @@ def test_delete_node_with_childs(visitor_test):
348349

349350

350351
def test_predecessors_successors(valid_basic_execution_graph):
351-
from freexgraph.standard_visitor import FindFirstVisitor
352352
v = FindFirstVisitor(lambda node: node.id.startswith("id3"))
353353
v.visit(valid_basic_execution_graph.root)
354354

@@ -367,3 +367,28 @@ def test_predecessors_successors(valid_basic_execution_graph):
367367
assert node_predecessors[0].id.startswith("id5")
368368

369369

370+
def test_middle_visitation_start(valid_complex_graph):
371+
v = FindFirstVisitor(lambda node: node.id == "F")
372+
v.visit(valid_complex_graph.root)
373+
374+
f_node = v.result
375+
assert v.found()
376+
assert f_node.id == "F"
377+
378+
# G and F are at the same level and thus are always executed on partial visitation
379+
find_g = FindFirstVisitor(lambda node: node.id == "G")
380+
381+
# start visitation from F node [A, B, C, D, E] should not be visited
382+
v = FindFirstVisitor(lambda node: node.id in ["A", "B", "C", "D", "E"])
383+
v.visit(f_node)
384+
assert not v.found()
385+
find_g.visit(f_node)
386+
assert find_g.found()
387+
388+
# start reverse visitation node [H, I, J, K, L, M] should not be visited
389+
v = FindFirstVisitor(lambda node: node.id in ["H", "I", "J", "K", "L", "M"])
390+
v.is_reversed = True
391+
v.visit(f_node)
392+
assert not v.found()
393+
find_g.visit(f_node)
394+
assert find_g.found()

0 commit comments

Comments
 (0)