drb 2.7.2__tar.gz → 2.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {drb-2.7.2/drb.egg-info → drb-2.7.3}/PKG-INFO +1 -1
- {drb-2.7.2 → drb-2.7.3}/drb/core/_version.py +3 -3
- {drb-2.7.2 → drb-2.7.3}/drb/nodes/abstract_node.py +11 -7
- {drb-2.7.2 → drb-2.7.3}/drb/topics/resolver.py +32 -4
- {drb-2.7.2 → drb-2.7.3/drb.egg-info}/PKG-INFO +1 -1
- {drb-2.7.2 → drb-2.7.3}/drb.egg-info/SOURCES.txt +2 -0
- drb-2.7.3/tests/test_named_child_no_sibling_resolution.py +60 -0
- drb-2.7.3/tests/test_resolver_factoryless_refinement.py +75 -0
- {drb-2.7.2 → drb-2.7.3}/LICENCE.txt +0 -0
- {drb-2.7.2 → drb-2.7.3}/MANIFEST.in +0 -0
- {drb-2.7.2 → drb-2.7.3}/README.md +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/addons/addon.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/auth.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/context.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/cortex_validator.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/events.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/factory.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/impls.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/item.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/path.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/predicate.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/core/signature.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/file/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/file/cortex.ttl +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/file/file.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/xml/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/xml/cortex.ttl +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/xml/factory.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/drivers/xml/node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/exceptions/core.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/exceptions/file.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/keyring/bitwarden/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/keyring/bitwarden/bitwarden.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/nodes/logical_node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/nodes/mutable_node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/nodes/url_node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/signatures/core.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/signatures/hierarchy.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/signatures/xquery.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/dao/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/dao/manager_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/dao/rdf_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/dao/topic_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/dao/topic_schema.yml +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/dao/xml_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/file/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/file/cortex.ttl +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/topic.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/xml/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/topics/xml/cortex.ttl +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/utils/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/utils/drb_python_script.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/utils/io.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/utils/plugins.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/utils/url_security.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/utils/utils.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/XQueryLexer.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/XQueryParser.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/XQueryParserListener.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/XQueryParserVisitor.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/__init__.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_cmd.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_context.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_func.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_item.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_res_to_string.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_utils.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_variable.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/drb_xquery_visitor.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb/xquery/exceptions.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb.egg-info/dependency_links.txt +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb.egg-info/entry_points.txt +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb.egg-info/not-zip-safe +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb.egg-info/requires.txt +0 -0
- {drb-2.7.2 → drb-2.7.3}/drb.egg-info/top_level.txt +0 -0
- {drb-2.7.2 → drb-2.7.3}/pyproject.toml +0 -0
- {drb-2.7.2 → drb-2.7.3}/requirements.txt +0 -0
- {drb-2.7.2 → drb-2.7.3}/setup.cfg +0 -0
- {drb-2.7.2 → drb-2.7.3}/setup.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_abstract_node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_addon.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_auth.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_children_unresolved.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_core_topic_ttl.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_cortex_validator.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_drb_node_list.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_drb_python_script.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_event.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_factory.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_factory_resolver.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_finest_multiparent.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_implementation_coupling.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_implementation_manager.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_keyring_bitwarden.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_logical_node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_manager_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_manager_get_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_node_context.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_node_context_manager.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_node_descendant.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_path.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_protocol_dispatch.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_rdf_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_rdf_dao_multi_url.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_rdf_dao_scheme.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_rdf_dao_signatures.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_resolver_auth.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_resolver_format_alias.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_resolver_implicit_file.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_resolver_recursion_guard.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_scheme_force_impl.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_scheme_force_url.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_signature_duplicate_warning.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_signature_exact.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_signature_hierarchy.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_signature_inline_flags.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_signatures.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_topic.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_topic_descriptor_discovery.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_topic_merge_crosspackage.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_url_node.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_url_security.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_xml_dao.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/tests/test_xml_xquery_import_order.py +0 -0
- {drb-2.7.2 → drb-2.7.3}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2026-07-
|
|
11
|
+
"date": "2026-07-09T07:37:18+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.7.
|
|
14
|
+
"full-revisionid": "db4dbac9d91e0226023e52ccca1fda79506fb923",
|
|
15
|
+
"version": "2.7.3"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -162,14 +162,14 @@ class AbstractNode(DrbNode, abc.ABC):
|
|
|
162
162
|
occ = occurrence
|
|
163
163
|
cpt = 0
|
|
164
164
|
if self.namespace_aware or namespace_uri is not None:
|
|
165
|
-
for x in self.
|
|
165
|
+
for x in self.children_unresolved:
|
|
166
166
|
if x.name == name and x.namespace_uri == namespace_uri:
|
|
167
167
|
if occ <= 0:
|
|
168
168
|
return cpt
|
|
169
169
|
occ -= 1
|
|
170
170
|
cpt += 1
|
|
171
171
|
else:
|
|
172
|
-
for x in self.
|
|
172
|
+
for x in self.children_unresolved:
|
|
173
173
|
if x.name == name:
|
|
174
174
|
return cpt
|
|
175
175
|
cpt += 1
|
|
@@ -199,12 +199,16 @@ class AbstractNode(DrbNode, abc.ABC):
|
|
|
199
199
|
IndexError: if item is out of range of found children
|
|
200
200
|
DrbException: if no child following given criteria is found
|
|
201
201
|
"""
|
|
202
|
+
# Match unresolved children and let the caller resolve only the
|
|
203
|
+
# selected node: a targeted named lookup must not resolve unrelated
|
|
204
|
+
# siblings (contract: the driver owns optimized access; the core
|
|
205
|
+
# resolves only when necessary). drb-testbench#21.
|
|
202
206
|
if self.namespace_aware or namespace_uri is not None:
|
|
203
|
-
named_children = [x for x in self.
|
|
207
|
+
named_children = [x for x in self.children_unresolved
|
|
204
208
|
if x.name == name
|
|
205
209
|
and x.namespace_uri == namespace_uri]
|
|
206
210
|
else:
|
|
207
|
-
named_children = [x for x in self.
|
|
211
|
+
named_children = [x for x in self.children_unresolved
|
|
208
212
|
if x.name == name]
|
|
209
213
|
if len(named_children) <= 0:
|
|
210
214
|
raise DrbException(f'No child found having name: {name} and'
|
|
@@ -225,13 +229,13 @@ class AbstractNode(DrbNode, abc.ABC):
|
|
|
225
229
|
|
|
226
230
|
result = []
|
|
227
231
|
if name is not None and namespace is not None:
|
|
228
|
-
result = [x for x in self.
|
|
232
|
+
result = [x for x in self.children_unresolved
|
|
229
233
|
if x.name == name and x.namespace_uri == namespace]
|
|
230
234
|
if name is None:
|
|
231
|
-
result = [x for x in self.
|
|
235
|
+
result = [x for x in self.children_unresolved
|
|
232
236
|
if x.namespace_uri == namespace]
|
|
233
237
|
if namespace is None:
|
|
234
|
-
result = [x for x in self.
|
|
238
|
+
result = [x for x in self.children_unresolved if x.name == name]
|
|
235
239
|
|
|
236
240
|
return len(result) > 0
|
|
237
241
|
|
|
@@ -94,6 +94,31 @@ def _topic_by_factory(name: str):
|
|
|
94
94
|
return None
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
def _driver_topic(topic: DrbTopic) -> Optional[DrbTopic]:
|
|
98
|
+
"""Nearest topic in the ``subClassOf`` chain (``topic`` first) that
|
|
99
|
+
declares a driver ``factory``.
|
|
100
|
+
|
|
101
|
+
A semantic refinement (e.g. a mission-specific container/formatting topic
|
|
102
|
+
such as ``Sentinel-2 …: Zip``) may declare no ``factory`` of its own; the
|
|
103
|
+
node must still be built by the driver of the nearest ancestor that has
|
|
104
|
+
one -- the refinement only relabels it, it does not rebuild it. Returns
|
|
105
|
+
``None`` when no topic in the chain declares a factory.
|
|
106
|
+
"""
|
|
107
|
+
by_id = {t.id: t for t in ManagerDao().get_all_drb_topics()}
|
|
108
|
+
seen = set()
|
|
109
|
+
queue = [topic]
|
|
110
|
+
while queue:
|
|
111
|
+
current = queue.pop(0)
|
|
112
|
+
if current is None or current.id in seen:
|
|
113
|
+
continue
|
|
114
|
+
seen.add(current.id)
|
|
115
|
+
if current.factory is not None:
|
|
116
|
+
return current
|
|
117
|
+
for parent_id in (current.subClassOf or []):
|
|
118
|
+
queue.append(by_id.get(parent_id))
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
|
|
97
122
|
def _topic_by_scheme_any(scheme: str):
|
|
98
123
|
"""The topic (any category) declaring ``scheme`` in its ``drb:scheme``.
|
|
99
124
|
|
|
@@ -477,13 +502,16 @@ class _DrbFactoryResolver(DrbFactory):
|
|
|
477
502
|
node = _create_via_factory(protocol, node)
|
|
478
503
|
|
|
479
504
|
container, node = self.__retrieve_container(node)
|
|
480
|
-
if container is not None
|
|
481
|
-
|
|
505
|
+
if container is not None:
|
|
506
|
+
driver = _driver_topic(container)
|
|
507
|
+
if driver is not None:
|
|
508
|
+
node = _create_via_factory(driver, node)
|
|
482
509
|
|
|
483
510
|
formatting = self.__retrieve_formatting(node)
|
|
484
511
|
if formatting is not None:
|
|
485
|
-
|
|
486
|
-
|
|
512
|
+
driver = _driver_topic(formatting)
|
|
513
|
+
if driver is not None:
|
|
514
|
+
node = _create_via_factory(driver, node)
|
|
487
515
|
t, n = self.__finest_drb_topic(node, formatting)
|
|
488
516
|
elif container is not None:
|
|
489
517
|
t, n = container, node
|
|
@@ -96,6 +96,7 @@ tests/test_keyring_bitwarden.py
|
|
|
96
96
|
tests/test_logical_node.py
|
|
97
97
|
tests/test_manager_dao.py
|
|
98
98
|
tests/test_manager_get_dao.py
|
|
99
|
+
tests/test_named_child_no_sibling_resolution.py
|
|
99
100
|
tests/test_node_context.py
|
|
100
101
|
tests/test_node_context_manager.py
|
|
101
102
|
tests/test_node_descendant.py
|
|
@@ -106,6 +107,7 @@ tests/test_rdf_dao_multi_url.py
|
|
|
106
107
|
tests/test_rdf_dao_scheme.py
|
|
107
108
|
tests/test_rdf_dao_signatures.py
|
|
108
109
|
tests/test_resolver_auth.py
|
|
110
|
+
tests/test_resolver_factoryless_refinement.py
|
|
109
111
|
tests/test_resolver_format_alias.py
|
|
110
112
|
tests/test_resolver_implicit_file.py
|
|
111
113
|
tests/test_resolver_recursion_guard.py
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""A named-child lookup must not resolve unrelated siblings (drb-testbench#21).
|
|
2
|
+
|
|
3
|
+
``_get_named_child`` served a targeted lookup by iterating the *resolved*
|
|
4
|
+
children list and filtering by name -- so it resolved **every** sibling to
|
|
5
|
+
return one child. That scales as O(N) resolutions on large containers and lets
|
|
6
|
+
an unrelated sibling's factory crash the lookup (e.g. a GRIB signature firing
|
|
7
|
+
``io.FileIO`` on ``~/.gradle``). Per the driver/core contract the core must
|
|
8
|
+
delegate optimized access to the driver and resolve only when necessary: a
|
|
9
|
+
named lookup matches unresolved children and resolves only the selected node.
|
|
10
|
+
"""
|
|
11
|
+
import os
|
|
12
|
+
import tempfile
|
|
13
|
+
import unittest
|
|
14
|
+
from unittest import mock
|
|
15
|
+
|
|
16
|
+
import drb.topics.resolver as resolver
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestNamedChildNoSiblingResolution(unittest.TestCase):
|
|
20
|
+
def setUp(self):
|
|
21
|
+
# A real directory: the file driver's children are resolved on
|
|
22
|
+
# iteration (@resolve_children), which is where sibling resolution
|
|
23
|
+
# leaks in.
|
|
24
|
+
self.dir = tempfile.mkdtemp()
|
|
25
|
+
for name in ('good', 'bad'):
|
|
26
|
+
open(os.path.join(self.dir, name), 'w').close()
|
|
27
|
+
|
|
28
|
+
def test_named_lookup_resolves_only_the_target(self):
|
|
29
|
+
node = resolver.create(self.dir)
|
|
30
|
+
resolved = []
|
|
31
|
+
real = resolver.create
|
|
32
|
+
|
|
33
|
+
def spy(n, *args, **kwargs):
|
|
34
|
+
resolved.append(getattr(n, 'name', None))
|
|
35
|
+
return real(n, *args, **kwargs)
|
|
36
|
+
|
|
37
|
+
with mock.patch.object(resolver, 'create', side_effect=spy):
|
|
38
|
+
child = node['good']
|
|
39
|
+
|
|
40
|
+
self.assertEqual('good', child.name)
|
|
41
|
+
self.assertNotIn('bad', resolved,
|
|
42
|
+
'named lookup must not resolve unrelated siblings')
|
|
43
|
+
|
|
44
|
+
def test_named_lookup_survives_unresolvable_sibling(self):
|
|
45
|
+
node = resolver.create(self.dir)
|
|
46
|
+
real = resolver.create
|
|
47
|
+
|
|
48
|
+
def spy(n, *args, **kwargs):
|
|
49
|
+
if getattr(n, 'name', None) == 'bad':
|
|
50
|
+
raise OSError('sibling factory blew up (must not be touched)')
|
|
51
|
+
return real(n, *args, **kwargs)
|
|
52
|
+
|
|
53
|
+
with mock.patch.object(resolver, 'create', side_effect=spy):
|
|
54
|
+
child = node['good']
|
|
55
|
+
|
|
56
|
+
self.assertEqual('good', child.name)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == '__main__':
|
|
60
|
+
unittest.main()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""A factory-less semantic refinement must not suppress its driver.
|
|
2
|
+
|
|
3
|
+
Regression for drb-python/drb-testbench#20: when a container/formatting topic
|
|
4
|
+
is refined by a sub-topic that declares no driver ``factory`` (e.g. the
|
|
5
|
+
Sentinel-2 KB topic ``… : Zip`` which ``subClassOf`` the generic ``zip``
|
|
6
|
+
topic), resolution used to apply only the *finest* topic's factory -- so the
|
|
7
|
+
generic ``zip`` driver was never applied and the node was left un-navigable.
|
|
8
|
+
|
|
9
|
+
``resolver._driver_topic`` returns the nearest topic in the ``subClassOf``
|
|
10
|
+
chain that actually declares a driver, so the node is built by that driver
|
|
11
|
+
while the finest topic still labels it.
|
|
12
|
+
"""
|
|
13
|
+
import unittest
|
|
14
|
+
import uuid
|
|
15
|
+
from unittest import mock
|
|
16
|
+
|
|
17
|
+
from drb.topics import resolver
|
|
18
|
+
from drb.topics.topic import TopicCategory
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _Topic:
|
|
22
|
+
def __init__(self, factory, sub=None):
|
|
23
|
+
self.id = uuid.uuid4()
|
|
24
|
+
self.factory = factory
|
|
25
|
+
self.subClassOf = sub
|
|
26
|
+
self.label = f'topic-{factory}-{self.id.hex[:6]}'
|
|
27
|
+
self.category = TopicCategory.CONTAINER
|
|
28
|
+
self.signatures = []
|
|
29
|
+
|
|
30
|
+
def matches(self, node): # pragma: no cover - not exercised here
|
|
31
|
+
return True
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestDriverTopic(unittest.TestCase):
|
|
35
|
+
@staticmethod
|
|
36
|
+
def _driver(topic, all_topics):
|
|
37
|
+
with mock.patch.object(resolver.ManagerDao, 'get_all_drb_topics',
|
|
38
|
+
return_value=all_topics):
|
|
39
|
+
return resolver._driver_topic(topic)
|
|
40
|
+
|
|
41
|
+
def test_topic_with_factory_returns_itself(self):
|
|
42
|
+
zip_t = _Topic('zip')
|
|
43
|
+
self.assertIs(zip_t, self._driver(zip_t, [zip_t]))
|
|
44
|
+
|
|
45
|
+
def test_factoryless_refinement_ascends_to_driver(self):
|
|
46
|
+
# zip (driver) <- abstract-zip (no factory) <- product-zip (no factory)
|
|
47
|
+
zip_t = _Topic('zip')
|
|
48
|
+
abstract = _Topic(None, sub=[zip_t.id])
|
|
49
|
+
product = _Topic(None, sub=[abstract.id])
|
|
50
|
+
self.assertIs(
|
|
51
|
+
zip_t, self._driver(product, [zip_t, abstract, product]))
|
|
52
|
+
|
|
53
|
+
def test_returns_nearest_driver_not_the_root(self):
|
|
54
|
+
# inner driver must win over a further ancestor driver
|
|
55
|
+
outer = _Topic('outer')
|
|
56
|
+
inner = _Topic('inner', sub=[outer.id])
|
|
57
|
+
leaf = _Topic(None, sub=[inner.id])
|
|
58
|
+
self.assertIs(inner, self._driver(leaf, [outer, inner, leaf]))
|
|
59
|
+
|
|
60
|
+
def test_no_factory_anywhere_returns_none(self):
|
|
61
|
+
a = _Topic(None)
|
|
62
|
+
b = _Topic(None, sub=[a.id])
|
|
63
|
+
self.assertIsNone(self._driver(b, [a, b]))
|
|
64
|
+
|
|
65
|
+
def test_multi_parent_chain_finds_the_driver_branch(self):
|
|
66
|
+
# a refinement subClassOf a semantic parent AND the zip driver
|
|
67
|
+
semantic = _Topic(None)
|
|
68
|
+
zip_t = _Topic('zip')
|
|
69
|
+
refine = _Topic(None, sub=[semantic.id, zip_t.id])
|
|
70
|
+
self.assertIs(
|
|
71
|
+
zip_t, self._driver(refine, [semantic, zip_t, refine]))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if __name__ == '__main__':
|
|
75
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drb-2.7.2 → drb-2.7.3}/setup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|