Skip to content

Commit 471e5ca

Browse files
committed
graph_database: Add has_link variant to check for specific link
The former GraphDatabase.has_link method checked if a node had any link. Rename it to has_any_link and add a new method to check if there's one specific link between two nodes. The new method is symmetrical to create_link.
1 parent d48030e commit 471e5ca

File tree

8 files changed

+91
-16
lines changed

8 files changed

+91
-16
lines changed

strictdoc/core/graph/abstract_bucket.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88

99
class AbstractBucket(ABC):
1010
@abstractmethod
11-
def has_link(self, *, lhs_node: Any) -> bool:
11+
def has_any_link(self, *, lhs_node: Any) -> bool:
12+
raise NotImplementedError
13+
14+
@abstractmethod
15+
def has_link(
16+
self, *, lhs_node: Any, rhs_node: Any, edge: Optional[str] = None
17+
) -> bool:
1218
raise NotImplementedError
1319

1420
@abstractmethod

strictdoc/core/graph/many_to_many_set.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ def __init__(self, lhs_type: Type[Any], rhs_type: Type[Any]) -> None:
1414
self._lhs_type: type = lhs_type
1515
self._rhs_type: type = rhs_type
1616

17-
def has_link(self, *, lhs_node: Any) -> bool:
17+
def has_any_link(self, *, lhs_node: Any) -> bool:
1818
assert isinstance(lhs_node, self._lhs_type), lhs_node
1919
return lhs_node in self._links and len(self._links[lhs_node]) > 0
2020

21+
def has_link(
22+
self, *, lhs_node: Any, rhs_node: Any, edge: Optional[str] = None
23+
) -> bool:
24+
assert isinstance(rhs_node, self._rhs_type), rhs_node
25+
return rhs_node in self.get_link_values(lhs_node=lhs_node, edge=edge)
26+
2127
def get_count(self, edge: Optional[str] = None) -> int:
2228
total_count = 0
2329
for _, lhs_node_links in self._links.items():

strictdoc/core/graph/one_to_one_dictionary.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ def __init__(
1313
self._lhs_type: Type[Any] = lhs_type
1414
self._rhs_type: Union[Type[Any], Tuple[Type[Any], ...]] = rhs_type
1515

16-
def has_link(self, *, lhs_node: Any) -> bool:
16+
def has_any_link(self, *, lhs_node: Any) -> bool:
1717
assert isinstance(lhs_node, self._lhs_type), (lhs_node, self._lhs_type)
1818
return lhs_node in self._dict
1919

20+
def has_link(
21+
self, *, lhs_node: Any, rhs_node: Any, edge: Optional[str] = None
22+
) -> bool:
23+
assert edge is None
24+
assert isinstance(lhs_node, self._lhs_type), (lhs_node, self._lhs_type)
25+
assert isinstance(rhs_node, self._rhs_type), (rhs_node, self._rhs_type)
26+
return lhs_node in self._dict and rhs_node is self._dict[lhs_node]
27+
2028
def get_count(self) -> int:
2129
return len(self._dict)
2230

strictdoc/core/graph_database.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,20 @@ def __init__(self, buckets: List[Tuple[Any, AbstractBucket]]):
2121
assert bucket_[0] not in self._id_to_bucket
2222
self._id_to_bucket[bucket_[0]] = bucket_[1]
2323

24-
def has_link(self, *, link_type: Hashable, lhs_node: Any) -> bool:
25-
return self._id_to_bucket[link_type].has_link(lhs_node=lhs_node)
24+
def has_any_link(self, *, link_type: Hashable, lhs_node: Any) -> bool:
25+
return self._id_to_bucket[link_type].has_any_link(lhs_node=lhs_node)
26+
27+
def has_link(
28+
self,
29+
*,
30+
link_type: Hashable,
31+
lhs_node: Any,
32+
rhs_node: Any,
33+
edge: Optional[str] = None,
34+
) -> bool:
35+
return self._id_to_bucket[link_type].has_link(
36+
lhs_node=lhs_node, rhs_node=rhs_node, edge=edge
37+
)
2638

2739
def get_count(self, *, link_type: Hashable) -> int:
2840
return self._id_to_bucket[link_type].get_count()

strictdoc/core/traceability_index.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def has_source_file_reqs(self, source_file_rel_path: str) -> bool:
134134

135135
def has_node_connections(self, node_uid: str) -> bool:
136136
assert isinstance(node_uid, str), node_uid
137-
return self.graph_database.has_link(
137+
return self.graph_database.has_any_link(
138138
link_type=GraphLinkType.UID_TO_NODE,
139139
lhs_node=node_uid,
140140
)
@@ -244,7 +244,7 @@ def get_children_requirements(
244244
)
245245

246246
def has_tags(self, document: SDocDocument) -> bool:
247-
return self.graph_database.has_link(
247+
return self.graph_database.has_any_link(
248248
link_type=GraphLinkType.DOCUMENT_TO_TAGS,
249249
lhs_node=document.reserved_mid,
250250
)
@@ -379,7 +379,7 @@ def create_inline_link(self, new_link: InlineLink) -> None:
379379
assert isinstance(new_link, InlineLink)
380380

381381
# InlineLink points to a section, node or to anchor.
382-
assert self.graph_database.has_link(
382+
assert self.graph_database.has_any_link(
383383
link_type=GraphLinkType.UID_TO_NODE, lhs_node=new_link.link
384384
)
385385

@@ -872,7 +872,7 @@ def validate_node_against_anchors(
872872
# by the new anchors.
873873
if node is None:
874874
for anchor_uid in new_anchor_uids:
875-
if self.graph_database.has_link(
875+
if self.graph_database.has_any_link(
876876
link_type=GraphLinkType.UID_TO_NODE, lhs_node=anchor_uid
877877
):
878878
raise SingleValidationError(
@@ -904,7 +904,7 @@ def validate_node_against_anchors(
904904
#
905905
for anchor_uid in new_anchor_uids:
906906
if (
907-
self.graph_database.has_link(
907+
self.graph_database.has_any_link(
908908
link_type=GraphLinkType.UID_TO_NODE, lhs_node=anchor_uid
909909
)
910910
and anchor_uid not in existing_node_anchor_uids

strictdoc/core/traceability_index_builder.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ def create_from_document_tree(
395395
print(exc.to_print_message()) # noqa: T201
396396
sys.exit(1)
397397

398-
if graph_database.has_link(
398+
if graph_database.has_any_link(
399399
link_type=GraphLinkType.MID_TO_NODE,
400400
lhs_node=document.reserved_mid,
401401
):
@@ -452,7 +452,7 @@ def create_from_document_tree(
452452
print(exc.to_print_message()) # noqa: T201
453453
sys.exit(1)
454454

455-
if graph_database.has_link(
455+
if graph_database.has_any_link(
456456
link_type=GraphLinkType.MID_TO_NODE,
457457
lhs_node=node.reserved_mid,
458458
):
@@ -478,7 +478,7 @@ def create_from_document_tree(
478478

479479
if node.reserved_uid is not None:
480480
# @relation(SDOC-SRS-29, scope=range_start)
481-
if traceability_index.graph_database.has_link(
481+
if traceability_index.graph_database.has_any_link(
482482
link_type=GraphLinkType.UID_TO_NODE,
483483
lhs_node=node.reserved_uid,
484484
):
@@ -565,7 +565,7 @@ def create_from_document_tree(
565565
for node_field_ in requirement.enumerate_fields():
566566
for part in node_field_.parts:
567567
if isinstance(part, InlineLink):
568-
if not graph_database.has_link(
568+
if not graph_database.has_any_link(
569569
link_type=GraphLinkType.UID_TO_NODE,
570570
lhs_node=part.link,
571571
):

tests/unit/strictdoc/core/test_graph_database.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,36 @@ def __init__(self, title):
2626
]
2727
)
2828

29+
assert (
30+
graph_database.has_link(
31+
link_type=Relation.INLINE_LINK_TO_ANCHOR,
32+
lhs_node=inline_link,
33+
rhs_node=anchor,
34+
)
35+
is False
36+
)
37+
2938
graph_database.create_link(
3039
link_type=Relation.INLINE_LINK_TO_ANCHOR,
3140
lhs_node=inline_link,
3241
rhs_node=anchor,
3342
)
43+
3444
assert (
3545
graph_database.get_link_value(
3646
link_type=Relation.INLINE_LINK_TO_ANCHOR,
3747
lhs_node=inline_link,
3848
)
3949
== anchor
4050
)
51+
assert (
52+
graph_database.has_link(
53+
link_type=Relation.INLINE_LINK_TO_ANCHOR,
54+
lhs_node=inline_link,
55+
rhs_node=anchor,
56+
)
57+
is True
58+
)
4159

4260
graph_database.delete_link(
4361
link_type=Relation.INLINE_LINK_TO_ANCHOR,
@@ -52,6 +70,14 @@ def __init__(self, title):
5270
)
5371
is None
5472
)
73+
assert (
74+
graph_database.has_link(
75+
link_type=Relation.INLINE_LINK_TO_ANCHOR,
76+
lhs_node=inline_link,
77+
rhs_node=anchor,
78+
)
79+
is False
80+
)
5581

5682

5783
def test_02_basic():
@@ -69,11 +95,28 @@ def __init__(self, title):
6995
buckets=[(Relation.INLINE_LINK_TO_ANCHOR, ManyToManySet(Node, Node))]
7096
)
7197

98+
assert (
99+
graph_database.has_link(
100+
link_type=Relation.INLINE_LINK_TO_ANCHOR,
101+
lhs_node=anchor,
102+
rhs_node=inline_link,
103+
)
104+
is False
105+
)
106+
72107
graph_database.create_link(
73108
link_type=Relation.INLINE_LINK_TO_ANCHOR,
74109
lhs_node=anchor,
75110
rhs_node=inline_link,
76111
)
112+
assert (
113+
graph_database.has_link(
114+
link_type=Relation.INLINE_LINK_TO_ANCHOR,
115+
lhs_node=anchor,
116+
rhs_node=inline_link,
117+
)
118+
is True
119+
)
77120
assert graph_database.get_link_values_reverse(
78121
link_type=Relation.INLINE_LINK_TO_ANCHOR, rhs_node=inline_link
79122
) == {anchor}

tests/unit/strictdoc/core/test_many2many_set.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def test_01_basic():
1414
many2many_set.create_link(lhs_node=1, rhs_node=3)
1515
many2many_set.create_link(lhs_node=1, rhs_node=4)
1616

17-
assert many2many_set.has_link(lhs_node=1)
17+
assert many2many_set.has_any_link(lhs_node=1)
1818

1919
assert many2many_set.get_link_values(lhs_node=1) == {2, 3, 4}
2020
assert many2many_set.get_link_values_reverse(rhs_node=2) == {1}
@@ -31,7 +31,7 @@ def test_01_basic():
3131
assert many2many_set.get_link_values_reverse(rhs_node=3) == OrderedSet()
3232
assert many2many_set.get_link_values_reverse(rhs_node=4) == OrderedSet()
3333

34-
assert not many2many_set.has_link(lhs_node=1)
34+
assert not many2many_set.has_any_link(lhs_node=1)
3535

3636

3737
def test_02_basic():

0 commit comments

Comments
 (0)