pyRegRep 11__tar.gz → 12__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyRegRep
3
- Version: 11
3
+ Version: 12
4
4
  Summary: Your package description
5
5
  Author: Andrey Shapovalov
6
6
  Author-email: mt.andrey@gmail.com
@@ -30,6 +30,7 @@ Dynamic: license-file
30
30
  - ✅ Фабрика слотів `get_slot()` — програмне створення RIM-слотів за типом
31
31
  - ✅ Серіалізація `AnyValueType` через `xmltodict` (параметр `any_type=True`)
32
32
  - ✅ Підтримка вкладених колекцій та складних структур
33
+ - ✅ Безпечний доступ до вкладених даних через `deep_get()`
33
34
 
34
35
  ## Вимоги
35
36
 
@@ -68,6 +69,12 @@ print(parser.serialize())
68
69
 
69
70
  # Серіалізація з обробкою AnyValueType в dict
70
71
  print(parser.serialize(any_type=True))
72
+
73
+ from pyRegRep4 import deep_get
74
+
75
+ # Безпечний доступ до вкладених ключів
76
+ spec_id = deep_get(parser.serialize(), "doc", "SpecificationIdentifier", default="unknown")
77
+ print(spec_id)
71
78
  ```
72
79
 
73
80
  ### Програмне створення RIM-слотів
@@ -191,6 +198,43 @@ except ValueError as e:
191
198
 
192
199
  ---
193
200
 
201
+ ### Функція `deep_get()` (`pyRegRep4.utils`)
202
+
203
+ ```python
204
+ deep_get(data: dict, *keys, default=None)
205
+ ```
206
+
207
+ Безпечно дістає значення з вкладеного `dict` за послідовністю ключів.
208
+
209
+ | Параметр | Тип | Опис |
210
+ |----------|-----|------|
211
+ | `data` | `dict` | Джерело даних |
212
+ | `*keys` | `Any` | Шлях ключів для проходу по вкладеному словнику |
213
+ | `default` | `Any` | Значення за замовчуванням, якщо шлях не знайдено |
214
+
215
+ **Поведінка:**
216
+ - якщо на будь-якому кроці значення не є `dict` — повертається `default`
217
+ - якщо кінцеве значення `None` — повертається `default`
218
+ - якщо `keys` не передані — повертається `data`
219
+
220
+ ```python
221
+ from pyRegRep4 import deep_get
222
+
223
+ data = {
224
+ "doc": {
225
+ "Procedure": [{"lang": "en", "value": "GetBirthCertificate"}]
226
+ }
227
+ }
228
+
229
+ value = deep_get(data, "doc", "Procedure", 0, "value", default="n/a")
230
+ print(value) # n/a (бо deep_get працює тільки з dict-ланцюжком)
231
+
232
+ procedure = deep_get(data, "doc", "Procedure", default=[])
233
+ print(procedure) # [{"lang": "en", "value": "GetBirthCertificate"}]
234
+ ```
235
+
236
+ ---
237
+
194
238
  ### Клас `NS` (`pyRegRep4.NS`)
195
239
 
196
240
  Базовий клас для управління RIM namespace. Надає метод `_tname(prefix, localname)` для генерування кваліфікованих імен тегів у нотації Clark.
@@ -209,11 +253,13 @@ pyRegRep/
209
253
  │ ├── __init__.py # Експорт: get_slot та типи слотів
210
254
  │ ├── RIMElement.py # Класи слотів + фабрика get_slot()
211
255
  │ ├── RIMParsing.py # Парсер Parsing + serialize()
256
+ │ ├── utils.py # deep_get() для вкладених словників
212
257
  │ └── NS.py # Базовий клас для namespace
213
258
  ├── tests/
214
259
  │ ├── conftest.py # sys.path для CI
215
260
  │ ├── test_rim_parsing.py # Тести парсера
216
261
  │ ├── test_rim_element.py # Тести get_slot() та типів слотів
262
+ │ ├── test_utils.py # Тести deep_get()
217
263
  │ ├── EDM_Ferst_Request.xml
218
264
  │ ├── EDM_Ferst_Response.xml
219
265
  │ ├── EDM_Second_Request.xml
@@ -291,4 +337,4 @@ MIT License — див. файл [LICENSE](LICENSE)
291
337
 
292
338
  ---
293
339
 
294
- **Версія:** 11 · **Оновлено:** 2026-03-11
340
+ **Версія:** 12 · **Оновлено:** 2026-04-12
@@ -16,6 +16,7 @@
16
16
  - ✅ Фабрика слотів `get_slot()` — програмне створення RIM-слотів за типом
17
17
  - ✅ Серіалізація `AnyValueType` через `xmltodict` (параметр `any_type=True`)
18
18
  - ✅ Підтримка вкладених колекцій та складних структур
19
+ - ✅ Безпечний доступ до вкладених даних через `deep_get()`
19
20
 
20
21
  ## Вимоги
21
22
 
@@ -54,6 +55,12 @@ print(parser.serialize())
54
55
 
55
56
  # Серіалізація з обробкою AnyValueType в dict
56
57
  print(parser.serialize(any_type=True))
58
+
59
+ from pyRegRep4 import deep_get
60
+
61
+ # Безпечний доступ до вкладених ключів
62
+ spec_id = deep_get(parser.serialize(), "doc", "SpecificationIdentifier", default="unknown")
63
+ print(spec_id)
57
64
  ```
58
65
 
59
66
  ### Програмне створення RIM-слотів
@@ -177,6 +184,43 @@ except ValueError as e:
177
184
 
178
185
  ---
179
186
 
187
+ ### Функція `deep_get()` (`pyRegRep4.utils`)
188
+
189
+ ```python
190
+ deep_get(data: dict, *keys, default=None)
191
+ ```
192
+
193
+ Безпечно дістає значення з вкладеного `dict` за послідовністю ключів.
194
+
195
+ | Параметр | Тип | Опис |
196
+ |----------|-----|------|
197
+ | `data` | `dict` | Джерело даних |
198
+ | `*keys` | `Any` | Шлях ключів для проходу по вкладеному словнику |
199
+ | `default` | `Any` | Значення за замовчуванням, якщо шлях не знайдено |
200
+
201
+ **Поведінка:**
202
+ - якщо на будь-якому кроці значення не є `dict` — повертається `default`
203
+ - якщо кінцеве значення `None` — повертається `default`
204
+ - якщо `keys` не передані — повертається `data`
205
+
206
+ ```python
207
+ from pyRegRep4 import deep_get
208
+
209
+ data = {
210
+ "doc": {
211
+ "Procedure": [{"lang": "en", "value": "GetBirthCertificate"}]
212
+ }
213
+ }
214
+
215
+ value = deep_get(data, "doc", "Procedure", 0, "value", default="n/a")
216
+ print(value) # n/a (бо deep_get працює тільки з dict-ланцюжком)
217
+
218
+ procedure = deep_get(data, "doc", "Procedure", default=[])
219
+ print(procedure) # [{"lang": "en", "value": "GetBirthCertificate"}]
220
+ ```
221
+
222
+ ---
223
+
180
224
  ### Клас `NS` (`pyRegRep4.NS`)
181
225
 
182
226
  Базовий клас для управління RIM namespace. Надає метод `_tname(prefix, localname)` для генерування кваліфікованих імен тегів у нотації Clark.
@@ -195,11 +239,13 @@ pyRegRep/
195
239
  │ ├── __init__.py # Експорт: get_slot та типи слотів
196
240
  │ ├── RIMElement.py # Класи слотів + фабрика get_slot()
197
241
  │ ├── RIMParsing.py # Парсер Parsing + serialize()
242
+ │ ├── utils.py # deep_get() для вкладених словників
198
243
  │ └── NS.py # Базовий клас для namespace
199
244
  ├── tests/
200
245
  │ ├── conftest.py # sys.path для CI
201
246
  │ ├── test_rim_parsing.py # Тести парсера
202
247
  │ ├── test_rim_element.py # Тести get_slot() та типів слотів
248
+ │ ├── test_utils.py # Тести deep_get()
203
249
  │ ├── EDM_Ferst_Request.xml
204
250
  │ ├── EDM_Ferst_Response.xml
205
251
  │ ├── EDM_Second_Request.xml
@@ -277,4 +323,4 @@ MIT License — див. файл [LICENSE](LICENSE)
277
323
 
278
324
  ---
279
325
 
280
- **Версія:** 11 · **Оновлено:** 2026-03-11
326
+ **Версія:** 12 · **Оновлено:** 2026-04-12
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyRegRep
3
- Version: 11
3
+ Version: 12
4
4
  Summary: Your package description
5
5
  Author: Andrey Shapovalov
6
6
  Author-email: mt.andrey@gmail.com
@@ -30,6 +30,7 @@ Dynamic: license-file
30
30
  - ✅ Фабрика слотів `get_slot()` — програмне створення RIM-слотів за типом
31
31
  - ✅ Серіалізація `AnyValueType` через `xmltodict` (параметр `any_type=True`)
32
32
  - ✅ Підтримка вкладених колекцій та складних структур
33
+ - ✅ Безпечний доступ до вкладених даних через `deep_get()`
33
34
 
34
35
  ## Вимоги
35
36
 
@@ -68,6 +69,12 @@ print(parser.serialize())
68
69
 
69
70
  # Серіалізація з обробкою AnyValueType в dict
70
71
  print(parser.serialize(any_type=True))
72
+
73
+ from pyRegRep4 import deep_get
74
+
75
+ # Безпечний доступ до вкладених ключів
76
+ spec_id = deep_get(parser.serialize(), "doc", "SpecificationIdentifier", default="unknown")
77
+ print(spec_id)
71
78
  ```
72
79
 
73
80
  ### Програмне створення RIM-слотів
@@ -191,6 +198,43 @@ except ValueError as e:
191
198
 
192
199
  ---
193
200
 
201
+ ### Функція `deep_get()` (`pyRegRep4.utils`)
202
+
203
+ ```python
204
+ deep_get(data: dict, *keys, default=None)
205
+ ```
206
+
207
+ Безпечно дістає значення з вкладеного `dict` за послідовністю ключів.
208
+
209
+ | Параметр | Тип | Опис |
210
+ |----------|-----|------|
211
+ | `data` | `dict` | Джерело даних |
212
+ | `*keys` | `Any` | Шлях ключів для проходу по вкладеному словнику |
213
+ | `default` | `Any` | Значення за замовчуванням, якщо шлях не знайдено |
214
+
215
+ **Поведінка:**
216
+ - якщо на будь-якому кроці значення не є `dict` — повертається `default`
217
+ - якщо кінцеве значення `None` — повертається `default`
218
+ - якщо `keys` не передані — повертається `data`
219
+
220
+ ```python
221
+ from pyRegRep4 import deep_get
222
+
223
+ data = {
224
+ "doc": {
225
+ "Procedure": [{"lang": "en", "value": "GetBirthCertificate"}]
226
+ }
227
+ }
228
+
229
+ value = deep_get(data, "doc", "Procedure", 0, "value", default="n/a")
230
+ print(value) # n/a (бо deep_get працює тільки з dict-ланцюжком)
231
+
232
+ procedure = deep_get(data, "doc", "Procedure", default=[])
233
+ print(procedure) # [{"lang": "en", "value": "GetBirthCertificate"}]
234
+ ```
235
+
236
+ ---
237
+
194
238
  ### Клас `NS` (`pyRegRep4.NS`)
195
239
 
196
240
  Базовий клас для управління RIM namespace. Надає метод `_tname(prefix, localname)` для генерування кваліфікованих імен тегів у нотації Clark.
@@ -209,11 +253,13 @@ pyRegRep/
209
253
  │ ├── __init__.py # Експорт: get_slot та типи слотів
210
254
  │ ├── RIMElement.py # Класи слотів + фабрика get_slot()
211
255
  │ ├── RIMParsing.py # Парсер Parsing + serialize()
256
+ │ ├── utils.py # deep_get() для вкладених словників
212
257
  │ └── NS.py # Базовий клас для namespace
213
258
  ├── tests/
214
259
  │ ├── conftest.py # sys.path для CI
215
260
  │ ├── test_rim_parsing.py # Тести парсера
216
261
  │ ├── test_rim_element.py # Тести get_slot() та типів слотів
262
+ │ ├── test_utils.py # Тести deep_get()
217
263
  │ ├── EDM_Ferst_Request.xml
218
264
  │ ├── EDM_Ferst_Response.xml
219
265
  │ ├── EDM_Second_Request.xml
@@ -291,4 +337,4 @@ MIT License — див. файл [LICENSE](LICENSE)
291
337
 
292
338
  ---
293
339
 
294
- **Версія:** 11 · **Оновлено:** 2026-03-11
340
+ **Версія:** 12 · **Оновлено:** 2026-04-12
@@ -11,6 +11,8 @@ pyRegRep4/NS.py
11
11
  pyRegRep4/RIMElement.py
12
12
  pyRegRep4/RIMParsing.py
13
13
  pyRegRep4/__init__.py
14
+ pyRegRep4/utils.py
14
15
  tests/test_get_slot_simple.py
15
16
  tests/test_rim_element.py
16
- tests/test_rim_parsing.py
17
+ tests/test_rim_parsing.py
18
+ tests/test_utils.py
@@ -19,6 +19,7 @@ from pyRegRep4.RIMElement import (
19
19
  _AnyValueType,
20
20
  _InternationalStringValueType,
21
21
  )
22
+ from pyRegRep4.utils import deep_get
22
23
 
23
24
  __all__ = [
24
25
  "get_slot",
@@ -29,8 +30,9 @@ __all__ = [
29
30
  "_CollectionValueType",
30
31
  "_AnyValueType",
31
32
  "_InternationalStringValueType",
33
+ "deep_get",
32
34
  ]
33
35
 
34
- __version__ = "11"
36
+ __version__ = "12"
35
37
  __author__ = "Andrey Shapovalov"
36
38
 
@@ -0,0 +1,23 @@
1
+ """Utility helpers for working with nested dictionaries."""
2
+
3
+ from typing import Any
4
+
5
+
6
+ def deep_get(data: dict[Any, Any], *keys: str, default: Any = None) -> Any:
7
+ """Safely read nested keys from a dictionary.
8
+
9
+ Args:
10
+ data: Source dictionary.
11
+ *keys: Sequence of keys to traverse.
12
+ default: Value returned when the key path is missing or the intermediate value is not a dict.
13
+
14
+ Returns:
15
+ Value by key path or "default" when the path cannot be resolved.
16
+ """
17
+ current: Any = data
18
+ for key in keys:
19
+ if not isinstance(current, dict):
20
+ return default
21
+ current = current.get(key)
22
+ return current if current is not None else default
23
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyRegRep"
7
- version = "11"
7
+ version = "12"
8
8
  description = "Your package description"
9
9
  authors = [{ name="Andrey Shapovalov" }]
10
10
  readme = "README.md"
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="pyRegRep",
5
- version="11",
5
+ version="12",
6
6
  description="Бібліотека для роботи з реєстрами та репозитаріями в Україні",
7
7
  packages=find_packages(),
8
8
  license="MIT",
@@ -0,0 +1,33 @@
1
+ """Unit tests for helper utilities."""
2
+
3
+ from pyRegRep4 import deep_get
4
+
5
+
6
+ class TestDeepGet:
7
+ """Tests for deep_get utility function."""
8
+
9
+ def test_returns_nested_value(self):
10
+ data = {"doc": {"meta": {"id": "ABC-123"}}}
11
+
12
+ assert deep_get(data, "doc", "meta", "id") == "ABC-123"
13
+
14
+ def test_returns_default_when_key_missing(self):
15
+ data = {"doc": {"meta": {"id": "ABC-123"}}}
16
+
17
+ assert deep_get(data, "doc", "meta", "missing", default="n/a") == "n/a"
18
+
19
+ def test_returns_default_when_intermediate_is_not_dict(self):
20
+ data = {"doc": {"meta": "plain-text"}}
21
+
22
+ assert deep_get(data, "doc", "meta", "id", default=None) is None
23
+
24
+ def test_returns_default_when_value_is_none(self):
25
+ data = {"doc": {"meta": {"id": None}}}
26
+
27
+ assert deep_get(data, "doc", "meta", "id", default="fallback") == "fallback"
28
+
29
+ def test_returns_root_data_when_keys_not_provided(self):
30
+ data = {"doc": {"meta": {"id": "ABC-123"}}}
31
+
32
+ assert deep_get(data) == data
33
+
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes