drb 2.3.0__tar.gz → 2.3.2__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.
Files changed (97) hide show
  1. {drb-2.3.0/drb.egg-info → drb-2.3.2}/PKG-INFO +6 -3
  2. {drb-2.3.0 → drb-2.3.2}/drb/core/_version.py +3 -3
  3. {drb-2.3.0 → drb-2.3.2}/drb/nodes/abstract_node.py +25 -0
  4. {drb-2.3.0 → drb-2.3.2/drb.egg-info}/PKG-INFO +6 -3
  5. {drb-2.3.0 → drb-2.3.2}/drb.egg-info/SOURCES.txt +1 -0
  6. {drb-2.3.0 → drb-2.3.2}/drb.egg-info/requires.txt +5 -2
  7. {drb-2.3.0 → drb-2.3.2}/requirements.txt +5 -2
  8. drb-2.3.2/tests/test_node_descendant.py +52 -0
  9. {drb-2.3.0 → drb-2.3.2}/LICENCE.txt +0 -0
  10. {drb-2.3.0 → drb-2.3.2}/MANIFEST.in +0 -0
  11. {drb-2.3.0 → drb-2.3.2}/README.md +0 -0
  12. {drb-2.3.0 → drb-2.3.2}/drb/addons/addon.py +0 -0
  13. {drb-2.3.0 → drb-2.3.2}/drb/core/__init__.py +0 -0
  14. {drb-2.3.0 → drb-2.3.2}/drb/core/cortex_validator.py +0 -0
  15. {drb-2.3.0 → drb-2.3.2}/drb/core/events.py +0 -0
  16. {drb-2.3.0 → drb-2.3.2}/drb/core/factory.py +0 -0
  17. {drb-2.3.0 → drb-2.3.2}/drb/core/impls.py +0 -0
  18. {drb-2.3.0 → drb-2.3.2}/drb/core/item.py +0 -0
  19. {drb-2.3.0 → drb-2.3.2}/drb/core/node.py +0 -0
  20. {drb-2.3.0 → drb-2.3.2}/drb/core/path.py +0 -0
  21. {drb-2.3.0 → drb-2.3.2}/drb/core/predicate.py +0 -0
  22. {drb-2.3.0 → drb-2.3.2}/drb/core/signature.py +0 -0
  23. {drb-2.3.0 → drb-2.3.2}/drb/drivers/file/__init__.py +0 -0
  24. {drb-2.3.0 → drb-2.3.2}/drb/drivers/file/file.py +0 -0
  25. {drb-2.3.0 → drb-2.3.2}/drb/drivers/xml/__init__.py +0 -0
  26. {drb-2.3.0 → drb-2.3.2}/drb/drivers/xml/factory.py +0 -0
  27. {drb-2.3.0 → drb-2.3.2}/drb/drivers/xml/node.py +0 -0
  28. {drb-2.3.0 → drb-2.3.2}/drb/exceptions/core.py +0 -0
  29. {drb-2.3.0 → drb-2.3.2}/drb/exceptions/file.py +0 -0
  30. {drb-2.3.0 → drb-2.3.2}/drb/keyring/bitwarden/__init__.py +0 -0
  31. {drb-2.3.0 → drb-2.3.2}/drb/keyring/bitwarden/bitwarden.py +0 -0
  32. {drb-2.3.0 → drb-2.3.2}/drb/nodes/logical_node.py +0 -0
  33. {drb-2.3.0 → drb-2.3.2}/drb/nodes/mutable_node.py +0 -0
  34. {drb-2.3.0 → drb-2.3.2}/drb/nodes/url_node.py +0 -0
  35. {drb-2.3.0 → drb-2.3.2}/drb/signatures/core.py +0 -0
  36. {drb-2.3.0 → drb-2.3.2}/drb/signatures/xquery.py +0 -0
  37. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/__init__.py +0 -0
  38. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/manager_dao.py +0 -0
  39. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/rdf_dao.py +0 -0
  40. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/topic_dao.py +0 -0
  41. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/topic_schema.yml +0 -0
  42. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/xml_dao.py +0 -0
  43. {drb-2.3.0 → drb-2.3.2}/drb/topics/dao/yaml_dao.py +0 -0
  44. {drb-2.3.0 → drb-2.3.2}/drb/topics/file/__init__.py +0 -0
  45. {drb-2.3.0 → drb-2.3.2}/drb/topics/file/cortex.yml +0 -0
  46. {drb-2.3.0 → drb-2.3.2}/drb/topics/resolver.py +0 -0
  47. {drb-2.3.0 → drb-2.3.2}/drb/topics/topic.py +0 -0
  48. {drb-2.3.0 → drb-2.3.2}/drb/topics/xml/__init__.py +0 -0
  49. {drb-2.3.0 → drb-2.3.2}/drb/topics/xml/cortex.yml +0 -0
  50. {drb-2.3.0 → drb-2.3.2}/drb/utils/__init__.py +0 -0
  51. {drb-2.3.0 → drb-2.3.2}/drb/utils/drb_python_script.py +0 -0
  52. {drb-2.3.0 → drb-2.3.2}/drb/utils/plugins.py +0 -0
  53. {drb-2.3.0 → drb-2.3.2}/drb/utils/url_security.py +0 -0
  54. {drb-2.3.0 → drb-2.3.2}/drb/utils/utils.py +0 -0
  55. {drb-2.3.0 → drb-2.3.2}/drb/xquery/XQueryLexer.py +0 -0
  56. {drb-2.3.0 → drb-2.3.2}/drb/xquery/XQueryParser.py +0 -0
  57. {drb-2.3.0 → drb-2.3.2}/drb/xquery/XQueryParserListener.py +0 -0
  58. {drb-2.3.0 → drb-2.3.2}/drb/xquery/XQueryParserVisitor.py +0 -0
  59. {drb-2.3.0 → drb-2.3.2}/drb/xquery/__init__.py +0 -0
  60. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery.py +0 -0
  61. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_cmd.py +0 -0
  62. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_context.py +0 -0
  63. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_func.py +0 -0
  64. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_item.py +0 -0
  65. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_res_to_string.py +0 -0
  66. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_utils.py +0 -0
  67. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_variable.py +0 -0
  68. {drb-2.3.0 → drb-2.3.2}/drb/xquery/drb_xquery_visitor.py +0 -0
  69. {drb-2.3.0 → drb-2.3.2}/drb/xquery/exceptions.py +0 -0
  70. {drb-2.3.0 → drb-2.3.2}/drb.egg-info/dependency_links.txt +0 -0
  71. {drb-2.3.0 → drb-2.3.2}/drb.egg-info/entry_points.txt +0 -0
  72. {drb-2.3.0 → drb-2.3.2}/drb.egg-info/not-zip-safe +0 -0
  73. {drb-2.3.0 → drb-2.3.2}/drb.egg-info/top_level.txt +0 -0
  74. {drb-2.3.0 → drb-2.3.2}/pyproject.toml +0 -0
  75. {drb-2.3.0 → drb-2.3.2}/setup.cfg +0 -0
  76. {drb-2.3.0 → drb-2.3.2}/setup.py +0 -0
  77. {drb-2.3.0 → drb-2.3.2}/tests/test_abstract_node.py +0 -0
  78. {drb-2.3.0 → drb-2.3.2}/tests/test_addon.py +0 -0
  79. {drb-2.3.0 → drb-2.3.2}/tests/test_drb_node_list.py +0 -0
  80. {drb-2.3.0 → drb-2.3.2}/tests/test_drb_python_script.py +0 -0
  81. {drb-2.3.0 → drb-2.3.2}/tests/test_event.py +0 -0
  82. {drb-2.3.0 → drb-2.3.2}/tests/test_factory.py +0 -0
  83. {drb-2.3.0 → drb-2.3.2}/tests/test_factory_resolver.py +0 -0
  84. {drb-2.3.0 → drb-2.3.2}/tests/test_implementation_manager.py +0 -0
  85. {drb-2.3.0 → drb-2.3.2}/tests/test_keyring_bitwarden.py +0 -0
  86. {drb-2.3.0 → drb-2.3.2}/tests/test_logical_node.py +0 -0
  87. {drb-2.3.0 → drb-2.3.2}/tests/test_manager_dao.py +0 -0
  88. {drb-2.3.0 → drb-2.3.2}/tests/test_path.py +0 -0
  89. {drb-2.3.0 → drb-2.3.2}/tests/test_rdf_dao.py +0 -0
  90. {drb-2.3.0 → drb-2.3.2}/tests/test_rdf_dao_multi_url.py +0 -0
  91. {drb-2.3.0 → drb-2.3.2}/tests/test_signatures.py +0 -0
  92. {drb-2.3.0 → drb-2.3.2}/tests/test_topic.py +0 -0
  93. {drb-2.3.0 → drb-2.3.2}/tests/test_url_node.py +0 -0
  94. {drb-2.3.0 → drb-2.3.2}/tests/test_url_security.py +0 -0
  95. {drb-2.3.0 → drb-2.3.2}/tests/test_xml_dao.py +0 -0
  96. {drb-2.3.0 → drb-2.3.2}/tests/test_yaml_dao.py +0 -0
  97. {drb-2.3.0 → drb-2.3.2}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drb
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Data Request Broker
5
5
  Author: GAEL Systems
6
6
  Author-email: drb-python@gael.fr
@@ -15,8 +15,11 @@ Requires-Dist: importlib-metadata>=4.11.4
15
15
  Requires-Dist: jsonschema==4.17.0
16
16
  Requires-Dist: PyYaml~=6.0.2
17
17
  Requires-Dist: click==8.1.3
18
- Requires-Dist: keyring~=23.13.1
19
- Requires-Dist: requests~=2.27.1
18
+ Requires-Dist: keyring<26,>=25.7.0
19
+ Requires-Dist: requests<3,>=2.33.0
20
+ Requires-Dist: urllib3<3,>=2.7.0
21
+ Requires-Dist: cryptography<49,>=48.0.1
22
+ Requires-Dist: idna<4,>=3.15
20
23
  Requires-Dist: defusedxml>=0.7.1
21
24
  Requires-Dist: Deprecated>=1.2.13
22
25
  Requires-Dist: antlr4-python3-runtime==4.9.3
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2026-06-17T10:01:32+0000",
11
+ "date": "2026-06-18T15:10:51+0000",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "20877e501f38b60068f2968eece3cdeb931ce694",
15
- "version": "2.3.0"
14
+ "full-revisionid": "02d64d042c4364857ac89ce8e8f6461acfdf9bb8",
15
+ "version": "2.3.2"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -61,6 +61,31 @@ class AbstractNode(DrbNode, abc.ABC):
61
61
  return DrbNodeList(children)
62
62
  raise TypeError(f"{type(item)} type not supported.")
63
63
 
64
+ def descendant(self, path: str) -> DrbNode:
65
+ """Navigate to a descendant node by a relative path.
66
+
67
+ Each non-empty segment of the '/'-separated ``path`` is resolved as
68
+ a direct child by name, equivalent to chaining ``node[segment]``.
69
+ Leading, trailing and repeated separators are ignored, so ``a/b/c``,
70
+ ``/a/b/c`` and ``a//b/c/`` are equivalent; an empty path returns the
71
+ node itself. Names that contain a literal ``/`` cannot be expressed
72
+ here -- use ``__getitem__`` per segment for those.
73
+
74
+ Parameters:
75
+ path: relative path whose segments are direct child names.
76
+
77
+ Returns:
78
+ DrbNode: the node reached after descending every segment.
79
+
80
+ Raises:
81
+ KeyError: if a segment matches no child (from ``__getitem__``).
82
+ """
83
+ node = self
84
+ for segment in path.split('/'):
85
+ if segment:
86
+ node = node[segment]
87
+ return node
88
+
64
89
  def __setitem__(self, key, value):
65
90
  if key is None:
66
91
  self._browse_children().append(value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drb
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Data Request Broker
5
5
  Author: GAEL Systems
6
6
  Author-email: drb-python@gael.fr
@@ -15,8 +15,11 @@ Requires-Dist: importlib-metadata>=4.11.4
15
15
  Requires-Dist: jsonschema==4.17.0
16
16
  Requires-Dist: PyYaml~=6.0.2
17
17
  Requires-Dist: click==8.1.3
18
- Requires-Dist: keyring~=23.13.1
19
- Requires-Dist: requests~=2.27.1
18
+ Requires-Dist: keyring<26,>=25.7.0
19
+ Requires-Dist: requests<3,>=2.33.0
20
+ Requires-Dist: urllib3<3,>=2.7.0
21
+ Requires-Dist: cryptography<49,>=48.0.1
22
+ Requires-Dist: idna<4,>=3.15
20
23
  Requires-Dist: defusedxml>=0.7.1
21
24
  Requires-Dist: Deprecated>=1.2.13
22
25
  Requires-Dist: antlr4-python3-runtime==4.9.3
@@ -84,6 +84,7 @@ tests/test_implementation_manager.py
84
84
  tests/test_keyring_bitwarden.py
85
85
  tests/test_logical_node.py
86
86
  tests/test_manager_dao.py
87
+ tests/test_node_descendant.py
87
88
  tests/test_path.py
88
89
  tests/test_rdf_dao.py
89
90
  tests/test_rdf_dao_multi_url.py
@@ -2,8 +2,11 @@ importlib-metadata>=4.11.4
2
2
  jsonschema==4.17.0
3
3
  PyYaml~=6.0.2
4
4
  click==8.1.3
5
- keyring~=23.13.1
6
- requests~=2.27.1
5
+ keyring<26,>=25.7.0
6
+ requests<3,>=2.33.0
7
+ urllib3<3,>=2.7.0
8
+ cryptography<49,>=48.0.1
9
+ idna<4,>=3.15
7
10
  defusedxml>=0.7.1
8
11
  Deprecated>=1.2.13
9
12
  antlr4-python3-runtime==4.9.3
@@ -2,8 +2,11 @@ importlib-metadata>=4.11.4
2
2
  jsonschema==4.17.0
3
3
  PyYaml~=6.0.2
4
4
  click==8.1.3
5
- keyring~=23.13.1
6
- requests~=2.27.1
5
+ keyring>=25.7.0,<26
6
+ requests>=2.33.0,<3
7
+ urllib3>=2.7.0,<3
8
+ cryptography>=48.0.1,<49
9
+ idna>=3.15,<4
7
10
  defusedxml>=0.7.1
8
11
  Deprecated>=1.2.13
9
12
  antlr4-python3-runtime==4.9.3
@@ -0,0 +1,52 @@
1
+ import unittest
2
+
3
+ from drb.exceptions.core import DrbException
4
+ from drb.nodes.logical_node import DrbLogicalNode
5
+
6
+
7
+ class TestDescendant(unittest.TestCase):
8
+ """Path navigation via DrbNode.descendant (TICKET-005)."""
9
+
10
+ @classmethod
11
+ def setUpClass(cls):
12
+ # root / MSI / L1C / 2026 / S2C.zip
13
+ cls.root = DrbLogicalNode('root')
14
+ msi = DrbLogicalNode('MSI')
15
+ l1c = DrbLogicalNode('L1C')
16
+ year = DrbLogicalNode('2026')
17
+ leaf = DrbLogicalNode('S2C.zip')
18
+ year.append_child(leaf)
19
+ l1c.append_child(year)
20
+ msi.append_child(l1c)
21
+ cls.root.append_child(msi)
22
+
23
+ def test_deep_path(self):
24
+ node = self.root.descendant('MSI/L1C/2026/S2C.zip')
25
+ self.assertEqual('S2C.zip', node.name)
26
+
27
+ def test_equivalent_to_chained_getitem(self):
28
+ # __getitem__ resolves children via the topic resolver, returning a
29
+ # fresh node each call, so compare by name/type, not identity.
30
+ chained = self.root['MSI']['L1C']['2026']['S2C.zip']
31
+ viapath = self.root.descendant('MSI/L1C/2026/S2C.zip')
32
+ self.assertEqual(chained.name, viapath.name)
33
+ self.assertEqual(type(chained), type(viapath))
34
+
35
+ def test_intermediate_node(self):
36
+ self.assertEqual('2026', self.root.descendant('MSI/L1C/2026').name)
37
+
38
+ def test_separators_are_normalised(self):
39
+ for path in ('/MSI/L1C', 'MSI/L1C/', 'MSI//L1C'):
40
+ self.assertEqual('L1C', self.root.descendant(path).name)
41
+
42
+ def test_empty_path_returns_self(self):
43
+ self.assertIs(self.root, self.root.descendant(''))
44
+ self.assertIs(self.root, self.root.descendant('/'))
45
+
46
+ def test_missing_segment_raises(self):
47
+ with self.assertRaises(KeyError):
48
+ self.root.descendant('MSI/NOPE/2026')
49
+
50
+
51
+ if __name__ == '__main__':
52
+ 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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes