pyRegRep 10__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.
- {pyregrep-10/pyRegRep.egg-info → pyregrep-12}/PKG-INFO +52 -5
- pyregrep-10/PKG-INFO → pyregrep-12/README.md +49 -16
- pyregrep-10/README.md → pyregrep-12/pyRegRep.egg-info/PKG-INFO +63 -4
- {pyregrep-10 → pyregrep-12}/pyRegRep.egg-info/SOURCES.txt +4 -1
- pyregrep-12/pyRegRep.egg-info/requires.txt +2 -0
- {pyregrep-10 → pyregrep-12}/pyRegRep4/RIMParsing.py +11 -3
- {pyregrep-10 → pyregrep-12}/pyRegRep4/__init__.py +3 -1
- pyregrep-12/pyRegRep4/utils.py +23 -0
- {pyregrep-10 → pyregrep-12}/pyproject.toml +5 -2
- {pyregrep-10 → pyregrep-12}/setup.py +5 -2
- pyregrep-12/tests/test_utils.py +33 -0
- {pyregrep-10 → pyregrep-12}/LICENSE +0 -0
- {pyregrep-10 → pyregrep-12}/pyRegRep.egg-info/dependency_links.txt +0 -0
- {pyregrep-10 → pyregrep-12}/pyRegRep.egg-info/top_level.txt +0 -0
- {pyregrep-10 → pyregrep-12}/pyRegRep4/NS.py +0 -0
- {pyregrep-10 → pyregrep-12}/pyRegRep4/RIMElement.py +0 -0
- {pyregrep-10 → pyregrep-12}/setup.cfg +0 -0
- {pyregrep-10 → pyregrep-12}/tests/test_get_slot_simple.py +0 -0
- {pyregrep-10 → pyregrep-12}/tests/test_rim_element.py +0 -0
- {pyregrep-10 → pyregrep-12}/tests/test_rim_parsing.py +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyRegRep
|
|
3
|
-
Version:
|
|
3
|
+
Version: 12
|
|
4
4
|
Summary: Your package description
|
|
5
5
|
Author: Andrey Shapovalov
|
|
6
6
|
Author-email: mt.andrey@gmail.com
|
|
7
7
|
Requires-Python: >=3.10
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
|
+
Requires-Dist: lxml>=5.2.1
|
|
11
|
+
Requires-Dist: xmltodict>=0.13.0
|
|
10
12
|
Dynamic: author-email
|
|
11
13
|
Dynamic: license-file
|
|
12
14
|
|
|
@@ -28,6 +30,7 @@ Dynamic: license-file
|
|
|
28
30
|
- ✅ Фабрика слотів `get_slot()` — програмне створення RIM-слотів за типом
|
|
29
31
|
- ✅ Серіалізація `AnyValueType` через `xmltodict` (параметр `any_type=True`)
|
|
30
32
|
- ✅ Підтримка вкладених колекцій та складних структур
|
|
33
|
+
- ✅ Безпечний доступ до вкладених даних через `deep_get()`
|
|
31
34
|
|
|
32
35
|
## Вимоги
|
|
33
36
|
|
|
@@ -44,11 +47,10 @@ pip install pyRegRep
|
|
|
44
47
|
|
|
45
48
|
# З локального джерела (editable)
|
|
46
49
|
pip install -e .
|
|
47
|
-
|
|
48
|
-
# Залежності вручну
|
|
49
|
-
pip install -r requirements.txt
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
Під час встановлення через `pip install pyRegRep` або `pip install -e .` runtime-залежності (`lxml`, `xmltodict`) встановлюються автоматично.
|
|
53
|
+
|
|
52
54
|
## Швидкий старт
|
|
53
55
|
|
|
54
56
|
### Парсування XML документу
|
|
@@ -67,6 +69,12 @@ print(parser.serialize())
|
|
|
67
69
|
|
|
68
70
|
# Серіалізація з обробкою AnyValueType в dict
|
|
69
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)
|
|
70
78
|
```
|
|
71
79
|
|
|
72
80
|
### Програмне створення RIM-слотів
|
|
@@ -190,6 +198,43 @@ except ValueError as e:
|
|
|
190
198
|
|
|
191
199
|
---
|
|
192
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
|
+
|
|
193
238
|
### Клас `NS` (`pyRegRep4.NS`)
|
|
194
239
|
|
|
195
240
|
Базовий клас для управління RIM namespace. Надає метод `_tname(prefix, localname)` для генерування кваліфікованих імен тегів у нотації Clark.
|
|
@@ -208,11 +253,13 @@ pyRegRep/
|
|
|
208
253
|
│ ├── __init__.py # Експорт: get_slot та типи слотів
|
|
209
254
|
│ ├── RIMElement.py # Класи слотів + фабрика get_slot()
|
|
210
255
|
│ ├── RIMParsing.py # Парсер Parsing + serialize()
|
|
256
|
+
│ ├── utils.py # deep_get() для вкладених словників
|
|
211
257
|
│ └── NS.py # Базовий клас для namespace
|
|
212
258
|
├── tests/
|
|
213
259
|
│ ├── conftest.py # sys.path для CI
|
|
214
260
|
│ ├── test_rim_parsing.py # Тести парсера
|
|
215
261
|
│ ├── test_rim_element.py # Тести get_slot() та типів слотів
|
|
262
|
+
│ ├── test_utils.py # Тести deep_get()
|
|
216
263
|
│ ├── EDM_Ferst_Request.xml
|
|
217
264
|
│ ├── EDM_Ferst_Response.xml
|
|
218
265
|
│ ├── EDM_Second_Request.xml
|
|
@@ -290,4 +337,4 @@ MIT License — див. файл [LICENSE](LICENSE)
|
|
|
290
337
|
|
|
291
338
|
---
|
|
292
339
|
|
|
293
|
-
**Версія:**
|
|
340
|
+
**Версія:** 12 · **Оновлено:** 2026-04-12
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pyRegRep
|
|
3
|
-
Version: 10
|
|
4
|
-
Summary: Your package description
|
|
5
|
-
Author: Andrey Shapovalov
|
|
6
|
-
Author-email: mt.andrey@gmail.com
|
|
7
|
-
Requires-Python: >=3.10
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Dynamic: author-email
|
|
11
|
-
Dynamic: license-file
|
|
12
|
-
|
|
13
1
|
# pyRegRep
|
|
14
2
|
|
|
15
3
|
Бібліотека Python для парсування та обробки XML документів у форматі RIM (Registry Information Model) / ebXML.
|
|
@@ -28,6 +16,7 @@ Dynamic: license-file
|
|
|
28
16
|
- ✅ Фабрика слотів `get_slot()` — програмне створення RIM-слотів за типом
|
|
29
17
|
- ✅ Серіалізація `AnyValueType` через `xmltodict` (параметр `any_type=True`)
|
|
30
18
|
- ✅ Підтримка вкладених колекцій та складних структур
|
|
19
|
+
- ✅ Безпечний доступ до вкладених даних через `deep_get()`
|
|
31
20
|
|
|
32
21
|
## Вимоги
|
|
33
22
|
|
|
@@ -44,11 +33,10 @@ pip install pyRegRep
|
|
|
44
33
|
|
|
45
34
|
# З локального джерела (editable)
|
|
46
35
|
pip install -e .
|
|
47
|
-
|
|
48
|
-
# Залежності вручну
|
|
49
|
-
pip install -r requirements.txt
|
|
50
36
|
```
|
|
51
37
|
|
|
38
|
+
Під час встановлення через `pip install pyRegRep` або `pip install -e .` runtime-залежності (`lxml`, `xmltodict`) встановлюються автоматично.
|
|
39
|
+
|
|
52
40
|
## Швидкий старт
|
|
53
41
|
|
|
54
42
|
### Парсування XML документу
|
|
@@ -67,6 +55,12 @@ print(parser.serialize())
|
|
|
67
55
|
|
|
68
56
|
# Серіалізація з обробкою AnyValueType в dict
|
|
69
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)
|
|
70
64
|
```
|
|
71
65
|
|
|
72
66
|
### Програмне створення RIM-слотів
|
|
@@ -190,6 +184,43 @@ except ValueError as e:
|
|
|
190
184
|
|
|
191
185
|
---
|
|
192
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
|
+
|
|
193
224
|
### Клас `NS` (`pyRegRep4.NS`)
|
|
194
225
|
|
|
195
226
|
Базовий клас для управління RIM namespace. Надає метод `_tname(prefix, localname)` для генерування кваліфікованих імен тегів у нотації Clark.
|
|
@@ -208,11 +239,13 @@ pyRegRep/
|
|
|
208
239
|
│ ├── __init__.py # Експорт: get_slot та типи слотів
|
|
209
240
|
│ ├── RIMElement.py # Класи слотів + фабрика get_slot()
|
|
210
241
|
│ ├── RIMParsing.py # Парсер Parsing + serialize()
|
|
242
|
+
│ ├── utils.py # deep_get() для вкладених словників
|
|
211
243
|
│ └── NS.py # Базовий клас для namespace
|
|
212
244
|
├── tests/
|
|
213
245
|
│ ├── conftest.py # sys.path для CI
|
|
214
246
|
│ ├── test_rim_parsing.py # Тести парсера
|
|
215
247
|
│ ├── test_rim_element.py # Тести get_slot() та типів слотів
|
|
248
|
+
│ ├── test_utils.py # Тести deep_get()
|
|
216
249
|
│ ├── EDM_Ferst_Request.xml
|
|
217
250
|
│ ├── EDM_Ferst_Response.xml
|
|
218
251
|
│ ├── EDM_Second_Request.xml
|
|
@@ -290,4 +323,4 @@ MIT License — див. файл [LICENSE](LICENSE)
|
|
|
290
323
|
|
|
291
324
|
---
|
|
292
325
|
|
|
293
|
-
**Версія:**
|
|
326
|
+
**Версія:** 12 · **Оновлено:** 2026-04-12
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyRegRep
|
|
3
|
+
Version: 12
|
|
4
|
+
Summary: Your package description
|
|
5
|
+
Author: Andrey Shapovalov
|
|
6
|
+
Author-email: mt.andrey@gmail.com
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: lxml>=5.2.1
|
|
11
|
+
Requires-Dist: xmltodict>=0.13.0
|
|
12
|
+
Dynamic: author-email
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
1
15
|
# pyRegRep
|
|
2
16
|
|
|
3
17
|
Бібліотека Python для парсування та обробки XML документів у форматі RIM (Registry Information Model) / ebXML.
|
|
@@ -16,6 +30,7 @@
|
|
|
16
30
|
- ✅ Фабрика слотів `get_slot()` — програмне створення RIM-слотів за типом
|
|
17
31
|
- ✅ Серіалізація `AnyValueType` через `xmltodict` (параметр `any_type=True`)
|
|
18
32
|
- ✅ Підтримка вкладених колекцій та складних структур
|
|
33
|
+
- ✅ Безпечний доступ до вкладених даних через `deep_get()`
|
|
19
34
|
|
|
20
35
|
## Вимоги
|
|
21
36
|
|
|
@@ -32,11 +47,10 @@ pip install pyRegRep
|
|
|
32
47
|
|
|
33
48
|
# З локального джерела (editable)
|
|
34
49
|
pip install -e .
|
|
35
|
-
|
|
36
|
-
# Залежності вручну
|
|
37
|
-
pip install -r requirements.txt
|
|
38
50
|
```
|
|
39
51
|
|
|
52
|
+
Під час встановлення через `pip install pyRegRep` або `pip install -e .` runtime-залежності (`lxml`, `xmltodict`) встановлюються автоматично.
|
|
53
|
+
|
|
40
54
|
## Швидкий старт
|
|
41
55
|
|
|
42
56
|
### Парсування XML документу
|
|
@@ -55,6 +69,12 @@ print(parser.serialize())
|
|
|
55
69
|
|
|
56
70
|
# Серіалізація з обробкою AnyValueType в dict
|
|
57
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)
|
|
58
78
|
```
|
|
59
79
|
|
|
60
80
|
### Програмне створення RIM-слотів
|
|
@@ -178,6 +198,43 @@ except ValueError as e:
|
|
|
178
198
|
|
|
179
199
|
---
|
|
180
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
|
+
|
|
181
238
|
### Клас `NS` (`pyRegRep4.NS`)
|
|
182
239
|
|
|
183
240
|
Базовий клас для управління RIM namespace. Надає метод `_tname(prefix, localname)` для генерування кваліфікованих імен тегів у нотації Clark.
|
|
@@ -196,11 +253,13 @@ pyRegRep/
|
|
|
196
253
|
│ ├── __init__.py # Експорт: get_slot та типи слотів
|
|
197
254
|
│ ├── RIMElement.py # Класи слотів + фабрика get_slot()
|
|
198
255
|
│ ├── RIMParsing.py # Парсер Parsing + serialize()
|
|
256
|
+
│ ├── utils.py # deep_get() для вкладених словників
|
|
199
257
|
│ └── NS.py # Базовий клас для namespace
|
|
200
258
|
├── tests/
|
|
201
259
|
│ ├── conftest.py # sys.path для CI
|
|
202
260
|
│ ├── test_rim_parsing.py # Тести парсера
|
|
203
261
|
│ ├── test_rim_element.py # Тести get_slot() та типів слотів
|
|
262
|
+
│ ├── test_utils.py # Тести deep_get()
|
|
204
263
|
│ ├── EDM_Ferst_Request.xml
|
|
205
264
|
│ ├── EDM_Ferst_Response.xml
|
|
206
265
|
│ ├── EDM_Second_Request.xml
|
|
@@ -278,4 +337,4 @@ MIT License — див. файл [LICENSE](LICENSE)
|
|
|
278
337
|
|
|
279
338
|
---
|
|
280
339
|
|
|
281
|
-
**Версія:**
|
|
340
|
+
**Версія:** 12 · **Оновлено:** 2026-04-12
|
|
@@ -5,11 +5,14 @@ setup.py
|
|
|
5
5
|
pyRegRep.egg-info/PKG-INFO
|
|
6
6
|
pyRegRep.egg-info/SOURCES.txt
|
|
7
7
|
pyRegRep.egg-info/dependency_links.txt
|
|
8
|
+
pyRegRep.egg-info/requires.txt
|
|
8
9
|
pyRegRep.egg-info/top_level.txt
|
|
9
10
|
pyRegRep4/NS.py
|
|
10
11
|
pyRegRep4/RIMElement.py
|
|
11
12
|
pyRegRep4/RIMParsing.py
|
|
12
13
|
pyRegRep4/__init__.py
|
|
14
|
+
pyRegRep4/utils.py
|
|
13
15
|
tests/test_get_slot_simple.py
|
|
14
16
|
tests/test_rim_element.py
|
|
15
|
-
tests/test_rim_parsing.py
|
|
17
|
+
tests/test_rim_parsing.py
|
|
18
|
+
tests/test_utils.py
|
|
@@ -73,12 +73,20 @@ class Parsing:
|
|
|
73
73
|
# Витягування основних елементів
|
|
74
74
|
try:
|
|
75
75
|
self.query = self.doc.find(".//query:Query", namespaces=self._ns)
|
|
76
|
-
|
|
77
|
-
self.objects = self.doc.findall(".//rim:RegistryObject", namespaces=self._ns)
|
|
78
|
-
except KeyError as e:
|
|
76
|
+
except Exception as e:
|
|
79
77
|
_logger.warning(f"Namespace не знайдено: {e}")
|
|
80
78
|
self.query = None
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
self.exception = self.doc.find(".//rs:Exception", namespaces=self._ns)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
_logger.warning(f"Namespace не знайдено: {e}")
|
|
81
84
|
self.exception = None
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
self.objects = self.doc.findall(".//rim:RegistryObject", namespaces=self._ns)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
_logger.warning(f"Namespace не знайдено: {e}")
|
|
82
90
|
self.objects = []
|
|
83
91
|
|
|
84
92
|
# Кешований результат
|
|
@@ -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__ = "
|
|
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,12 +4,15 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyRegRep"
|
|
7
|
-
version = "
|
|
7
|
+
version = "12"
|
|
8
8
|
description = "Your package description"
|
|
9
9
|
authors = [{ name="Andrey Shapovalov" }]
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
|
-
dependencies = [
|
|
12
|
+
dependencies = [
|
|
13
|
+
"lxml>=5.2.1",
|
|
14
|
+
"xmltodict>=0.13.0",
|
|
15
|
+
]
|
|
13
16
|
|
|
14
17
|
[tool.pytest.ini_options]
|
|
15
18
|
pythonpath = ["."]
|
|
@@ -2,12 +2,15 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="pyRegRep",
|
|
5
|
-
version="
|
|
5
|
+
version="12",
|
|
6
6
|
description="Бібліотека для роботи з реєстрами та репозитаріями в Україні",
|
|
7
7
|
packages=find_packages(),
|
|
8
8
|
license="MIT",
|
|
9
9
|
author="Andrii Shapovalov",
|
|
10
10
|
author_email="mt.andrey@gmail.com",
|
|
11
11
|
include_package_data=True,
|
|
12
|
-
install_requires=[
|
|
12
|
+
install_requires=[
|
|
13
|
+
"lxml>=5.2.1",
|
|
14
|
+
"xmltodict>=0.13.0",
|
|
15
|
+
],
|
|
13
16
|
)
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|