drb 2.3.8__tar.gz → 2.3.9__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.3.8/drb.egg-info → drb-2.3.9}/PKG-INFO +1 -1
- {drb-2.3.8 → drb-2.3.9}/drb/core/_version.py +3 -3
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/rdf_dao.py +7 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/resolver.py +18 -8
- {drb-2.3.8 → drb-2.3.9}/drb/topics/topic.py +1 -0
- {drb-2.3.8 → drb-2.3.9/drb.egg-info}/PKG-INFO +1 -1
- {drb-2.3.8 → drb-2.3.9}/drb.egg-info/SOURCES.txt +1 -2
- {drb-2.3.8 → drb-2.3.9}/setup.cfg +0 -1
- drb-2.3.9/tests/test_protocol_dispatch.py +102 -0
- drb-2.3.9/tests/test_rdf_dao_scheme.py +34 -0
- drb-2.3.8/drb/core/protocol.py +0 -58
- drb-2.3.8/tests/test_protocol_dispatch.py +0 -115
- drb-2.3.8/tests/test_protocol_loader.py +0 -29
- {drb-2.3.8 → drb-2.3.9}/LICENCE.txt +0 -0
- {drb-2.3.8 → drb-2.3.9}/MANIFEST.in +0 -0
- {drb-2.3.8 → drb-2.3.9}/README.md +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/addons/addon.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/context.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/cortex_validator.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/events.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/factory.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/impls.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/item.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/path.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/predicate.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/core/signature.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/drivers/file/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/drivers/file/file.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/drivers/xml/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/drivers/xml/factory.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/drivers/xml/node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/exceptions/core.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/exceptions/file.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/keyring/bitwarden/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/keyring/bitwarden/bitwarden.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/nodes/abstract_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/nodes/logical_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/nodes/mutable_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/nodes/url_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/signatures/core.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/signatures/hierarchy.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/signatures/xquery.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/manager_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/topic_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/topic_schema.yml +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/xml_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/dao/yaml_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/file/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/file/cortex.yml +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/xml/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/topics/xml/cortex.yml +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/utils/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/utils/drb_python_script.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/utils/plugins.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/utils/url_security.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/utils/utils.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/XQueryLexer.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/XQueryParser.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/XQueryParserListener.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/XQueryParserVisitor.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/__init__.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_cmd.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_context.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_func.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_item.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_res_to_string.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_utils.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_variable.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/drb_xquery_visitor.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb/xquery/exceptions.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb.egg-info/dependency_links.txt +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb.egg-info/entry_points.txt +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb.egg-info/not-zip-safe +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb.egg-info/requires.txt +0 -0
- {drb-2.3.8 → drb-2.3.9}/drb.egg-info/top_level.txt +0 -0
- {drb-2.3.8 → drb-2.3.9}/pyproject.toml +0 -0
- {drb-2.3.8 → drb-2.3.9}/requirements.txt +0 -0
- {drb-2.3.8 → drb-2.3.9}/setup.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_abstract_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_addon.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_children_unresolved.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_drb_node_list.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_drb_python_script.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_event.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_factory.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_factory_resolver.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_implementation_coupling.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_implementation_manager.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_keyring_bitwarden.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_logical_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_manager_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_manager_get_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_node_context.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_node_descendant.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_path.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_rdf_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_rdf_dao_multi_url.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_rdf_dao_signatures.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_signature_exact.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_signature_hierarchy.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_signatures.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_topic.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_topic_descriptor_discovery.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_url_node.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_url_security.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_xml_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/tests/test_yaml_dao.py +0 -0
- {drb-2.3.8 → drb-2.3.9}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2026-06-
|
|
11
|
+
"date": "2026-06-25T22:03:16+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.3.
|
|
14
|
+
"full-revisionid": "e77eb7f024e245d4ecab611276e4c247ccdd516a",
|
|
15
|
+
"version": "2.3.9"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -91,6 +91,9 @@ class RDFDao(DrbTopicDao):
|
|
|
91
91
|
(GROUP_CONCAT(DISTINCT IF(BOUND(?parentClassId),
|
|
92
92
|
STR(?parentClassId),
|
|
93
93
|
?parentClass); separator="§ ") AS ?parentClasses)
|
|
94
|
+
(GROUP_CONCAT(DISTINCT IF(BOUND(?scheme),
|
|
95
|
+
STR(?scheme), ""); separator=" ")
|
|
96
|
+
AS ?schemes)
|
|
94
97
|
WHERE {
|
|
95
98
|
{
|
|
96
99
|
?Class rdfs:subClassOf+ <http://www.gael.fr/drb#item> .
|
|
@@ -101,6 +104,7 @@ class RDFDao(DrbTopicDao):
|
|
|
101
104
|
OPTIONAL { ?Class drb:id ?id .}
|
|
102
105
|
OPTIONAL { ?Class drb:category ?category .}
|
|
103
106
|
OPTIONAL { ?Class drb:implementationIdentifier ?factory .}
|
|
107
|
+
OPTIONAL { ?Class drb:scheme ?scheme .}
|
|
104
108
|
OPTIONAL {
|
|
105
109
|
?Class rdfs:subClassOf ?parentClass .
|
|
106
110
|
OPTIONAL { ?parentClass drb:id ?parentClassId .}
|
|
@@ -190,6 +194,9 @@ class RDFDao(DrbTopicDao):
|
|
|
190
194
|
if row.factory is not None:
|
|
191
195
|
data['factory'] = row.factory.toPython()
|
|
192
196
|
|
|
197
|
+
schemes = str(row.schemes) if row.schemes is not None else ''
|
|
198
|
+
data['scheme'] = schemes.split() if schemes else []
|
|
199
|
+
|
|
193
200
|
data['subClassOf'] = None
|
|
194
201
|
|
|
195
202
|
if uri_parents is not None:
|
|
@@ -10,7 +10,6 @@ from typing import List, Optional, Tuple, Union
|
|
|
10
10
|
|
|
11
11
|
from drb.core.node import DrbNode
|
|
12
12
|
from drb.core.factory import DrbFactory, FactoryLoader
|
|
13
|
-
from drb.core.protocol import ProtocolLoader
|
|
14
13
|
from drb.topics.topic import DrbTopic, TopicCategory
|
|
15
14
|
from drb.exceptions.core import DrbFactoryException, DrbException
|
|
16
15
|
from drb.nodes.url_node import UrlNode
|
|
@@ -55,7 +54,6 @@ def _create_via_factory(topic: DrbTopic, node: DrbNode) -> DrbNode:
|
|
|
55
54
|
|
|
56
55
|
def _topic_by_factory(name: str):
|
|
57
56
|
"""The PROTOCOL topic whose implementationIdentifier == name, or None."""
|
|
58
|
-
from drb.topics.dao import ManagerDao
|
|
59
57
|
for topic in ManagerDao().get_drb_topics_by_category(
|
|
60
58
|
TopicCategory.PROTOCOL):
|
|
61
59
|
if topic.factory == name:
|
|
@@ -63,6 +61,15 @@ def _topic_by_factory(name: str):
|
|
|
63
61
|
return None
|
|
64
62
|
|
|
65
63
|
|
|
64
|
+
def _topic_by_scheme(scheme: str):
|
|
65
|
+
"""The PROTOCOL topic declaring this scheme (drb:scheme), or None."""
|
|
66
|
+
for topic in ManagerDao().get_drb_topics_by_category(
|
|
67
|
+
TopicCategory.PROTOCOL):
|
|
68
|
+
if scheme in (topic.scheme or []):
|
|
69
|
+
return topic
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
|
|
66
73
|
class _DrbFactoryResolver(DrbFactory):
|
|
67
74
|
""" The factory resolver
|
|
68
75
|
|
|
@@ -100,22 +107,25 @@ class _DrbFactoryResolver(DrbFactory):
|
|
|
100
107
|
return None
|
|
101
108
|
|
|
102
109
|
def __dispatch_scheme(self, node):
|
|
103
|
-
"""Dispatch a root URL by
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
signature matching)."""
|
|
110
|
+
"""Dispatch a root URL by drb:scheme, then apply a +<name> forced
|
|
111
|
+
driver if present. Returns (topic, node), or None when no PROTOCOL
|
|
112
|
+
topic declares the base scheme or its factory is not installed
|
|
113
|
+
(caller falls back to signature matching)."""
|
|
107
114
|
scheme = node.path.scheme
|
|
108
115
|
if not scheme:
|
|
109
116
|
return None
|
|
110
117
|
parts = scheme.split('+', 1)
|
|
111
118
|
base = parts[0]
|
|
112
119
|
forced = parts[1] if len(parts) > 1 else None
|
|
113
|
-
|
|
120
|
+
base_topic = _topic_by_scheme(base)
|
|
121
|
+
if base_topic is None:
|
|
122
|
+
return None
|
|
123
|
+
base_factory = FactoryLoader().get_factory(base_topic.factory)
|
|
114
124
|
if base_factory is None:
|
|
115
125
|
return None
|
|
116
126
|
created = base_factory.create(node)
|
|
117
127
|
if forced is None:
|
|
118
|
-
return
|
|
128
|
+
return base_topic, created
|
|
119
129
|
forced_factory = FactoryLoader().get_factory(forced)
|
|
120
130
|
if forced_factory is None:
|
|
121
131
|
raise DrbFactoryException(
|
|
@@ -31,6 +31,7 @@ class DrbTopic:
|
|
|
31
31
|
factory: str = field(default=None, repr=False)
|
|
32
32
|
description: str = field(default=None, repr=False)
|
|
33
33
|
forced: bool = field(default=False, repr=False)
|
|
34
|
+
scheme: List[str] = field(default_factory=list, repr=False)
|
|
34
35
|
signatures: List[Signature] = field(default=None, repr=False)
|
|
35
36
|
override: bool = field(default=False, repr=False)
|
|
36
37
|
|
|
@@ -25,7 +25,6 @@ drb/core/item.py
|
|
|
25
25
|
drb/core/node.py
|
|
26
26
|
drb/core/path.py
|
|
27
27
|
drb/core/predicate.py
|
|
28
|
-
drb/core/protocol.py
|
|
29
28
|
drb/core/signature.py
|
|
30
29
|
drb/drivers/file/__init__.py
|
|
31
30
|
drb/drivers/file/file.py
|
|
@@ -94,9 +93,9 @@ tests/test_node_context.py
|
|
|
94
93
|
tests/test_node_descendant.py
|
|
95
94
|
tests/test_path.py
|
|
96
95
|
tests/test_protocol_dispatch.py
|
|
97
|
-
tests/test_protocol_loader.py
|
|
98
96
|
tests/test_rdf_dao.py
|
|
99
97
|
tests/test_rdf_dao_multi_url.py
|
|
98
|
+
tests/test_rdf_dao_scheme.py
|
|
100
99
|
tests/test_rdf_dao_signatures.py
|
|
101
100
|
tests/test_signature_exact.py
|
|
102
101
|
tests/test_signature_hierarchy.py
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import patch, MagicMock
|
|
3
|
+
from drb.core.factory import DrbFactory
|
|
4
|
+
from drb.core.node import DrbNode
|
|
5
|
+
from drb.nodes.logical_node import DrbLogicalNode
|
|
6
|
+
import drb.topics.resolver as resolver_mod
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class _Node(DrbLogicalNode):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _BaseFactory(DrbFactory):
|
|
14
|
+
def _create(self, node: DrbNode) -> DrbNode:
|
|
15
|
+
return _Node('dispatched')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class _ForcedNode(DrbLogicalNode):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class _ForcedFactory(DrbFactory):
|
|
23
|
+
received = None
|
|
24
|
+
|
|
25
|
+
def _create(self, node: DrbNode) -> DrbNode:
|
|
26
|
+
_ForcedFactory.received = node
|
|
27
|
+
return _ForcedNode('forced')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _topic(factory, scheme):
|
|
31
|
+
t = MagicMock()
|
|
32
|
+
t.factory = factory
|
|
33
|
+
t.scheme = scheme
|
|
34
|
+
return t
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TestSchemeDispatch(unittest.TestCase):
|
|
38
|
+
def _resolve(self, url, protocol_topics, factories):
|
|
39
|
+
r = resolver_mod._DrbFactoryResolver()
|
|
40
|
+
with patch.object(resolver_mod, 'ManagerDao') as md, \
|
|
41
|
+
patch.object(resolver_mod.FactoryLoader, 'get_factory') as gf:
|
|
42
|
+
md.return_value.get_drb_topics_by_category.return_value = \
|
|
43
|
+
protocol_topics
|
|
44
|
+
gf.side_effect = lambda name: factories.get(name)
|
|
45
|
+
return r._DrbFactoryResolver__dispatch_scheme(DrbLogicalNode(url))
|
|
46
|
+
|
|
47
|
+
def test_scheme_decoupled_from_factory(self):
|
|
48
|
+
topic = _topic('aws3', ['s3'])
|
|
49
|
+
result = self._resolve('s3://bucket/key', [topic],
|
|
50
|
+
{'aws3': _BaseFactory()})
|
|
51
|
+
self.assertIsNotNone(result)
|
|
52
|
+
t, n = result
|
|
53
|
+
self.assertIs(t, topic)
|
|
54
|
+
self.assertIsInstance(n, _Node)
|
|
55
|
+
|
|
56
|
+
def test_two_topics_one_factory_pick_right(self):
|
|
57
|
+
http = _topic('http', ['http'])
|
|
58
|
+
https = _topic('http', ['https'])
|
|
59
|
+
result = self._resolve('https://host', [http, https],
|
|
60
|
+
{'http': _BaseFactory()})
|
|
61
|
+
t, _ = result
|
|
62
|
+
self.assertIs(t, https)
|
|
63
|
+
|
|
64
|
+
def test_unknown_scheme_returns_none(self):
|
|
65
|
+
topic = _topic('aws3', ['s3'])
|
|
66
|
+
self.assertIsNone(
|
|
67
|
+
self._resolve('ftp://h', [topic], {'aws3': _BaseFactory()}))
|
|
68
|
+
|
|
69
|
+
def test_factory_absent_returns_none(self):
|
|
70
|
+
topic = _topic('aws3', ['s3'])
|
|
71
|
+
self.assertIsNone(
|
|
72
|
+
self._resolve('s3://b', [topic], {})) # aws3 not installed
|
|
73
|
+
|
|
74
|
+
def test_force_by_name(self):
|
|
75
|
+
base = _topic('http', ['https'])
|
|
76
|
+
forced = _topic('odata', [])
|
|
77
|
+
r = resolver_mod._DrbFactoryResolver()
|
|
78
|
+
with patch.object(resolver_mod, 'ManagerDao') as md, \
|
|
79
|
+
patch.object(resolver_mod.FactoryLoader, 'get_factory') as gf, \
|
|
80
|
+
patch.object(resolver_mod, '_topic_by_factory',
|
|
81
|
+
return_value=forced):
|
|
82
|
+
md.return_value.get_drb_topics_by_category.return_value = [base]
|
|
83
|
+
facs = {'http': _BaseFactory(), 'odata': _ForcedFactory()}
|
|
84
|
+
gf.side_effect = lambda name: facs.get(name)
|
|
85
|
+
t, n = r._DrbFactoryResolver__dispatch_scheme(
|
|
86
|
+
DrbLogicalNode('https+odata://host'))
|
|
87
|
+
self.assertIs(t, forced)
|
|
88
|
+
self.assertIsInstance(n, _ForcedNode)
|
|
89
|
+
self.assertIsInstance(_ForcedFactory.received, _Node)
|
|
90
|
+
|
|
91
|
+
def test_unknown_forced_raises(self):
|
|
92
|
+
base = _topic('http', ['https'])
|
|
93
|
+
from drb.exceptions.core import DrbFactoryException
|
|
94
|
+
r = resolver_mod._DrbFactoryResolver()
|
|
95
|
+
with patch.object(resolver_mod, 'ManagerDao') as md, \
|
|
96
|
+
patch.object(resolver_mod.FactoryLoader, 'get_factory') as gf:
|
|
97
|
+
md.return_value.get_drb_topics_by_category.return_value = [base]
|
|
98
|
+
gf.side_effect = lambda name: (
|
|
99
|
+
{'http': _BaseFactory()}).get(name)
|
|
100
|
+
with self.assertRaises(DrbFactoryException):
|
|
101
|
+
r._DrbFactoryResolver__dispatch_scheme(
|
|
102
|
+
DrbLogicalNode('https+nosuch://host'))
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
import unittest
|
|
4
|
+
from drb.topics.dao.rdf_dao import RDFDao
|
|
5
|
+
|
|
6
|
+
_TTL = '''
|
|
7
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
8
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
9
|
+
@prefix drb: <http://www.gael.fr/drb#> .
|
|
10
|
+
<http://www.gael.fr/drb#> a owl:Ontology .
|
|
11
|
+
|
|
12
|
+
drb:s3demo a owl:Class ;
|
|
13
|
+
drb:id "66666666-6666-6666-6666-666666666666" ;
|
|
14
|
+
drb:category "PROTOCOL" ;
|
|
15
|
+
rdfs:subClassOf drb:item ;
|
|
16
|
+
rdfs:label "s3demo" ;
|
|
17
|
+
drb:scheme "s3" ;
|
|
18
|
+
drb:implementationIdentifier "aws3" .
|
|
19
|
+
'''
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestRdfDaoScheme(unittest.TestCase):
|
|
23
|
+
def test_scheme_parsed_into_topic(self):
|
|
24
|
+
fd, path = tempfile.mkstemp(suffix='.ttl')
|
|
25
|
+
os.close(fd)
|
|
26
|
+
with open(path, 'w') as f:
|
|
27
|
+
f.write(_TTL)
|
|
28
|
+
try:
|
|
29
|
+
dao = RDFDao(path)
|
|
30
|
+
topic = next(t for t in dao.read_all() if t.label == 's3demo')
|
|
31
|
+
self.assertEqual(['s3'], topic.scheme)
|
|
32
|
+
self.assertEqual('aws3', topic.factory)
|
|
33
|
+
finally:
|
|
34
|
+
os.remove(path)
|
drb-2.3.8/drb/core/protocol.py
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import importlib
|
|
4
|
-
import inspect
|
|
5
|
-
import logging
|
|
6
|
-
from typing import Optional
|
|
7
|
-
|
|
8
|
-
import drb.utils.plugins
|
|
9
|
-
from drb.core.factory import DrbFactory
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ProtocolLoader:
|
|
13
|
-
"""Loads ``drb.protocol`` entry points into a scheme -> factory map.
|
|
14
|
-
|
|
15
|
-
Each entry point's name is a URL scheme (e.g. ``s3``, ``https``) and its
|
|
16
|
-
value is ``module:FactoryClass`` (a ``DrbFactory`` subclass). Mirrors
|
|
17
|
-
:class:`drb.core.factory.FactoryLoader`.
|
|
18
|
-
"""
|
|
19
|
-
__instance = None
|
|
20
|
-
__factories = None
|
|
21
|
-
|
|
22
|
-
def __new__(cls, *args, **kwargs):
|
|
23
|
-
if cls.__instance is None:
|
|
24
|
-
cls.__instance = super(ProtocolLoader, cls).__new__(cls)
|
|
25
|
-
cls.__factories = cls.__load()
|
|
26
|
-
return cls.__instance
|
|
27
|
-
|
|
28
|
-
@classmethod
|
|
29
|
-
def __is_class(cls, class_name: str):
|
|
30
|
-
return lambda obj: inspect.isclass(obj) and class_name == obj.__name__
|
|
31
|
-
|
|
32
|
-
@classmethod
|
|
33
|
-
def __load(cls) -> dict:
|
|
34
|
-
factories = {}
|
|
35
|
-
for ep in drb.utils.plugins.get_entry_points('drb.protocol'):
|
|
36
|
-
if ep.name in factories:
|
|
37
|
-
continue
|
|
38
|
-
m, c = ep.value.split(':')
|
|
39
|
-
try:
|
|
40
|
-
module = importlib.import_module(m)
|
|
41
|
-
for _, obj in inspect.getmembers(module, cls.__is_class(c)):
|
|
42
|
-
if obj != DrbFactory and issubclass(obj, DrbFactory):
|
|
43
|
-
factories[ep.name] = obj()
|
|
44
|
-
else:
|
|
45
|
-
logging.getLogger().warning(
|
|
46
|
-
f'Failed to load protocol "{ep.name}": '
|
|
47
|
-
f'invalid factory: {ep.value}')
|
|
48
|
-
except ModuleNotFoundError:
|
|
49
|
-
logging.getLogger().warning(
|
|
50
|
-
f'Failed to load protocol "{ep.name}": module {m} '
|
|
51
|
-
f'not found')
|
|
52
|
-
return factories
|
|
53
|
-
|
|
54
|
-
def get_schemes(self) -> set:
|
|
55
|
-
return set(self.__factories.keys())
|
|
56
|
-
|
|
57
|
-
def get_factory(self, scheme: str) -> Optional[DrbFactory]:
|
|
58
|
-
return self.__factories.get(scheme, None)
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from unittest.mock import patch, MagicMock
|
|
3
|
-
import drb.core.protocol as protocol_mod
|
|
4
|
-
from drb.core.factory import DrbFactory
|
|
5
|
-
from drb.core.node import DrbNode
|
|
6
|
-
from drb.nodes.logical_node import DrbLogicalNode
|
|
7
|
-
import drb.topics.resolver as resolver_mod
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class _SchemeNode(DrbLogicalNode):
|
|
11
|
-
pass
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class _BaseFactory(DrbFactory):
|
|
15
|
-
def _create(self, node: DrbNode) -> DrbNode:
|
|
16
|
-
n = _SchemeNode('dispatched')
|
|
17
|
-
return n
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class TestProtocolDispatch(unittest.TestCase):
|
|
21
|
-
def setUp(self):
|
|
22
|
-
protocol_mod.ProtocolLoader._ProtocolLoader__instance = None
|
|
23
|
-
protocol_mod.ProtocolLoader._ProtocolLoader__factories = None
|
|
24
|
-
|
|
25
|
-
def _loader_with(self, scheme, factory):
|
|
26
|
-
ep = MagicMock()
|
|
27
|
-
ep.name = scheme
|
|
28
|
-
ep.value = f'{__name__}:{type(factory).__name__}'
|
|
29
|
-
with patch.object(protocol_mod.drb.utils.plugins, 'get_entry_points',
|
|
30
|
-
return_value=[ep]):
|
|
31
|
-
return protocol_mod.ProtocolLoader()
|
|
32
|
-
|
|
33
|
-
def test_base_scheme_dispatch_creates_node(self):
|
|
34
|
-
loader = self._loader_with('foo', _BaseFactory())
|
|
35
|
-
topic = MagicMock()
|
|
36
|
-
topic.factory = 'foo'
|
|
37
|
-
with patch.object(
|
|
38
|
-
resolver_mod, 'ProtocolLoader', return_value=loader), \
|
|
39
|
-
patch.object(
|
|
40
|
-
resolver_mod, '_topic_by_factory', return_value=topic):
|
|
41
|
-
r = resolver_mod._DrbFactoryResolver()
|
|
42
|
-
result = r._DrbFactoryResolver__dispatch_scheme(
|
|
43
|
-
DrbLogicalNode('foo://host/x'))
|
|
44
|
-
self.assertIsNotNone(result)
|
|
45
|
-
t, n = result
|
|
46
|
-
self.assertIs(t, topic)
|
|
47
|
-
self.assertIsInstance(n, _SchemeNode)
|
|
48
|
-
|
|
49
|
-
def test_unknown_scheme_returns_none(self):
|
|
50
|
-
loader = self._loader_with('foo', _BaseFactory())
|
|
51
|
-
with patch.object(resolver_mod, 'ProtocolLoader',
|
|
52
|
-
return_value=loader):
|
|
53
|
-
r = resolver_mod._DrbFactoryResolver()
|
|
54
|
-
result = r._DrbFactoryResolver__dispatch_scheme(
|
|
55
|
-
DrbLogicalNode('bar://host/x'))
|
|
56
|
-
self.assertIsNone(result)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class _ForcedNode(DrbLogicalNode):
|
|
60
|
-
pass
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class _ForcedFactory(DrbFactory):
|
|
64
|
-
received = None
|
|
65
|
-
|
|
66
|
-
def _create(self, node: DrbNode) -> DrbNode:
|
|
67
|
-
_ForcedFactory.received = node
|
|
68
|
-
return _ForcedNode('forced')
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class TestForceByName(unittest.TestCase):
|
|
72
|
-
def setUp(self):
|
|
73
|
-
protocol_mod.ProtocolLoader._ProtocolLoader__instance = None
|
|
74
|
-
protocol_mod.ProtocolLoader._ProtocolLoader__factories = None
|
|
75
|
-
_ForcedFactory.received = None
|
|
76
|
-
|
|
77
|
-
def test_force_applies_named_factory(self):
|
|
78
|
-
ep = MagicMock()
|
|
79
|
-
ep.name = 'foo'
|
|
80
|
-
ep.value = f'{__name__}:_BaseFactory'
|
|
81
|
-
with patch.object(protocol_mod.drb.utils.plugins, 'get_entry_points',
|
|
82
|
-
return_value=[ep]):
|
|
83
|
-
loader = protocol_mod.ProtocolLoader()
|
|
84
|
-
forced = _ForcedFactory()
|
|
85
|
-
forced_topic = MagicMock()
|
|
86
|
-
forced_topic.factory = 'bar'
|
|
87
|
-
with patch.object(
|
|
88
|
-
resolver_mod, 'ProtocolLoader', return_value=loader), \
|
|
89
|
-
patch.object(resolver_mod.FactoryLoader, 'get_factory',
|
|
90
|
-
return_value=forced), \
|
|
91
|
-
patch.object(resolver_mod, '_topic_by_factory',
|
|
92
|
-
return_value=forced_topic):
|
|
93
|
-
r = resolver_mod._DrbFactoryResolver()
|
|
94
|
-
t, n = r._DrbFactoryResolver__dispatch_scheme(
|
|
95
|
-
DrbLogicalNode('foo+bar://host/x'))
|
|
96
|
-
self.assertIs(t, forced_topic)
|
|
97
|
-
self.assertIsInstance(n, _ForcedNode)
|
|
98
|
-
self.assertIsInstance(_ForcedFactory.received, _SchemeNode)
|
|
99
|
-
|
|
100
|
-
def test_unknown_forced_name_raises(self):
|
|
101
|
-
ep = MagicMock()
|
|
102
|
-
ep.name = 'foo'
|
|
103
|
-
ep.value = f'{__name__}:_BaseFactory'
|
|
104
|
-
with patch.object(protocol_mod.drb.utils.plugins, 'get_entry_points',
|
|
105
|
-
return_value=[ep]):
|
|
106
|
-
loader = protocol_mod.ProtocolLoader()
|
|
107
|
-
from drb.exceptions.core import DrbFactoryException
|
|
108
|
-
with patch.object(
|
|
109
|
-
resolver_mod, 'ProtocolLoader', return_value=loader), \
|
|
110
|
-
patch.object(resolver_mod.FactoryLoader, 'get_factory',
|
|
111
|
-
return_value=None):
|
|
112
|
-
r = resolver_mod._DrbFactoryResolver()
|
|
113
|
-
with self.assertRaises(DrbFactoryException):
|
|
114
|
-
r._DrbFactoryResolver__dispatch_scheme(
|
|
115
|
-
DrbLogicalNode('foo+nosuch://host/x'))
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from unittest.mock import patch, MagicMock
|
|
3
|
-
import drb.core.protocol as protocol_mod
|
|
4
|
-
from drb.core.factory import DrbFactory
|
|
5
|
-
from drb.core.node import DrbNode
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class _FakeProtoFactory(DrbFactory):
|
|
9
|
-
def _create(self, node: DrbNode) -> DrbNode:
|
|
10
|
-
return node
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestProtocolLoader(unittest.TestCase):
|
|
14
|
-
def setUp(self):
|
|
15
|
-
# reset the singleton so each test loads its own entry points
|
|
16
|
-
protocol_mod.ProtocolLoader._ProtocolLoader__instance = None
|
|
17
|
-
protocol_mod.ProtocolLoader._ProtocolLoader__factories = None
|
|
18
|
-
|
|
19
|
-
def test_loads_scheme_to_factory(self):
|
|
20
|
-
ep = MagicMock()
|
|
21
|
-
ep.name = 'testscheme'
|
|
22
|
-
ep.value = f'{__name__}:_FakeProtoFactory'
|
|
23
|
-
with patch.object(protocol_mod.drb.utils.plugins, 'get_entry_points',
|
|
24
|
-
return_value=[ep]):
|
|
25
|
-
loader = protocol_mod.ProtocolLoader()
|
|
26
|
-
self.assertIn('testscheme', loader.get_schemes())
|
|
27
|
-
self.assertIsInstance(loader.get_factory('testscheme'),
|
|
28
|
-
_FakeProtoFactory)
|
|
29
|
-
self.assertIsNone(loader.get_factory('absent'))
|
|
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.3.8 → drb-2.3.9}/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
|