oj-toolkit 0.1.8__tar.gz → 0.2.0__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.
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/PKG-INFO +111 -19
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/README.md +109 -18
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/__init__.py +4 -2
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/parsing/__init__.py +3 -3
- oj_toolkit-0.2.0/oj_toolkit/parsing/types.py +411 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit.egg-info/PKG-INFO +111 -19
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit.egg-info/requires.txt +1 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/pyproject.toml +4 -2
- oj_toolkit-0.1.8/oj_toolkit/parsing/types.py +0 -244
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/LICENSE +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/asynchronous/__init__.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/asynchronous/async_chunks.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/asynchronous/decorators.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/__init__.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/box.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/colored_text.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/colors.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/status.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/streams.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/table.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/terminal.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/console/text.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/data/__init__.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/data/flex.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/diagnostics.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/logging/__init__.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/logging/config.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/logging/consts.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/logging/decorators.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/logging/formatters.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/logging/handlers.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit/parsing/consts.py +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit.egg-info/SOURCES.txt +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit.egg-info/dependency_links.txt +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/oj_toolkit.egg-info/top_level.txt +0 -0
- {oj_toolkit-0.1.8 → oj_toolkit-0.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oj-toolkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Centralized shared utilities for ownjoo-org projects: standardized logging config, type validation, data parsing, console output, and async utilities
|
|
5
5
|
Author-email: Speedy <speedy@ownjoo.org>
|
|
6
6
|
License: MIT
|
|
@@ -22,6 +22,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
+
Requires-Dist: jmespath>=1.0
|
|
25
26
|
Provides-Extra: dev
|
|
26
27
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
27
28
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
@@ -152,7 +153,7 @@ print(text) # Rendered with ANSI codes
|
|
|
152
153
|
### Parsing & Validation
|
|
153
154
|
|
|
154
155
|
```python
|
|
155
|
-
from oj_toolkit import validate, get_datetime, str_to_list, dig
|
|
156
|
+
from oj_toolkit import validate, get_datetime, str_to_list, dig, dig_many, Digger
|
|
156
157
|
|
|
157
158
|
# Validate and convert types
|
|
158
159
|
result = validate('123', exp=int, converter=int) # Returns: 123
|
|
@@ -167,12 +168,31 @@ dt = get_datetime('2024-01-15T10:30:00') # ISO 8601
|
|
|
167
168
|
dt = get_datetime(1705318200) # Unix timestamp
|
|
168
169
|
dt = get_datetime('Mon, 15 Jan 2024 10:30:00 GMT') # HTTP date
|
|
169
170
|
|
|
170
|
-
# Extract and validate nested values
|
|
171
|
+
# Extract and validate nested values using a jmespath expression
|
|
171
172
|
data = {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}
|
|
172
|
-
name = dig(data, path=
|
|
173
|
-
|
|
173
|
+
name = dig(data, path='users[0].name', exp=str) # Returns: 'Alice'
|
|
174
|
+
names = dig(data, path='users[*].name', exp=list) # Returns: ['Alice', 'Bob']
|
|
175
|
+
|
|
176
|
+
# Fallback chain: first matching path wins (handy for optional/renamed fields)
|
|
177
|
+
name = dig(data, path=['users[0].nickname', 'users[0].name'], exp=str) # Returns: 'Alice'
|
|
178
|
+
|
|
179
|
+
# Extract several fields in one call
|
|
180
|
+
fields = dig_many(
|
|
181
|
+
data,
|
|
182
|
+
paths={'first_name': 'users[0].name', 'second_name': 'users[1].name'},
|
|
183
|
+
post_processor=None, # skip validate() and return raw matches
|
|
184
|
+
)
|
|
185
|
+
# Returns: {'first_name': 'Alice', 'second_name': 'Bob'}
|
|
186
|
+
|
|
187
|
+
# Bind a path once, reuse it against many objects
|
|
188
|
+
get_name = Digger(path='name', exp=str, default='')
|
|
189
|
+
[get_name(user) for user in data['users']] # Returns: ['Alice', 'Bob']
|
|
174
190
|
```
|
|
175
191
|
|
|
192
|
+
> **Note:** `dig()`'s default `post_processor` (`validate()`) only accepts a value if you pass
|
|
193
|
+
> `exp=<type>` -- without it, validation always fails and you get `default` back (`None` unless set).
|
|
194
|
+
> Pass `exp=` for a real value, or `post_processor=None` to skip validation and get the raw match.
|
|
195
|
+
|
|
176
196
|
### Logging Setup
|
|
177
197
|
|
|
178
198
|
Call `configure_logging` once at application startup (Lambda handler, CLI `main()`, FastAPI lifespan). Libraries should never call it — they only use `logging.getLogger(__name__)`.
|
|
@@ -770,19 +790,37 @@ get_datetime('Mon, 15 Jan 2024 10:30:00 GMT') # HTTP date
|
|
|
770
790
|
get_datetime('01/15/2024 10:30:00', format_str='%m/%d/%Y %H:%M:%S') # Custom
|
|
771
791
|
```
|
|
772
792
|
|
|
773
|
-
#### `dig(src, path=None, post_processor=validate, **kwargs)`
|
|
774
|
-
|
|
775
|
-
Extract and post-process a value from a nested data structure.
|
|
793
|
+
#### `dig(src, path=None, pop=False, post_processor=validate, **kwargs)`
|
|
776
794
|
|
|
777
|
-
|
|
795
|
+
Extract and post-process a value from a nested data structure, using [jmespath](https://jmespath.org/)
|
|
796
|
+
under the hood (`jmespath` is a required dependency).
|
|
778
797
|
|
|
779
798
|
- **Parameters:**
|
|
780
|
-
- `src` (
|
|
781
|
-
- `path` (
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
799
|
+
- `src` (Mapping | Sequence): Data structure to navigate
|
|
800
|
+
- `path` (int | str | list | None):
|
|
801
|
+
- `str` — a jmespath expression, e.g. `'users[0].name'`, `'users[*].name'`, `'users[?id==\`2\`].name'`
|
|
802
|
+
- `int` — shorthand for a single top-level index, e.g. `1` is equivalent to `'[1]'`
|
|
803
|
+
- `list[int | str]` — a fallback chain: each candidate is tried in order and the first
|
|
804
|
+
one whose result isn't `None` wins (handy for optional/renamed fields)
|
|
805
|
+
- `None` — treat `src` itself as the value to post-process
|
|
806
|
+
- `pop` (bool): If `True`, delete the terminal key/index of the *winning* expression from
|
|
807
|
+
its container after extracting the value (mutates `src` in place). Only honored when that
|
|
808
|
+
expression's terminal segment is unambiguous (no wildcards, filters, or projections) --
|
|
809
|
+
otherwise it's refused with a logged warning and the value is still returned unpopped.
|
|
810
|
+
- `post_processor` (Callable): Function to post-process the found value. Default: `validate()`.
|
|
811
|
+
Pass `None` to skip post-processing and get the raw match.
|
|
812
|
+
- `**kwargs`: Passed to `post_processor`
|
|
813
|
+
|
|
814
|
+
- **Returns:** Post-processed value, or `None` if extraction fails, no candidate path matches, or
|
|
815
|
+
no post-processor is specified and nothing was found
|
|
816
|
+
|
|
817
|
+
> **Type checkers:** pass `exp=<type>` to get a precise `<type> | None` return type instead of `Any`
|
|
818
|
+
> (`dig(data, path='...', exp=str)` type-checks as `str | None`). Passing `post_processor=None` types
|
|
819
|
+
> as `Any` (raw, unvalidated value). A custom `post_processor` types as that callable's own return type.
|
|
820
|
+
|
|
821
|
+
> **Passing no `exp`:** the default `validate()` post-processor only accepts a value when you give
|
|
822
|
+
> it `exp=<type>` -- without one, validation always fails and you get `default` back (`None` unless
|
|
823
|
+
> set). Either pass `exp=`, or `post_processor=None` to bypass validation entirely.
|
|
786
824
|
|
|
787
825
|
**Example:**
|
|
788
826
|
|
|
@@ -797,16 +835,70 @@ data = {
|
|
|
797
835
|
}
|
|
798
836
|
|
|
799
837
|
# Extract nested value
|
|
800
|
-
name = dig(data, path=
|
|
838
|
+
name = dig(data, path='response.users[0].name', exp=str)
|
|
801
839
|
# Returns: 'Alice'
|
|
802
840
|
|
|
803
841
|
# Extract with validation
|
|
804
|
-
user = dig(data, path=
|
|
842
|
+
user = dig(data, path='response.users[1]', exp=dict)
|
|
805
843
|
# Returns: {'id': 2, 'name': 'Bob'}
|
|
806
844
|
|
|
807
|
-
# Extract with custom post-processor
|
|
808
|
-
count = dig(data, path=
|
|
845
|
+
# Extract with custom post-processor (no exp needed -- len() isn't validate())
|
|
846
|
+
count = dig(data, path='response.users', post_processor=len)
|
|
809
847
|
# Returns: 2
|
|
848
|
+
|
|
849
|
+
# jmespath's full expression syntax is available -- wildcards, filters, functions, etc.
|
|
850
|
+
names = dig(data, path='response.users[*].name', exp=list)
|
|
851
|
+
# Returns: ['Alice', 'Bob']
|
|
852
|
+
|
|
853
|
+
# Fallback chain: try a renamed/optional field first, fall back to the old one
|
|
854
|
+
name = dig(data, path=['response.users[0].display_name', 'response.users[0].name'], exp=str)
|
|
855
|
+
# Returns: 'Alice'
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
#### `dig_many(src, paths, **common_kwargs)`
|
|
859
|
+
|
|
860
|
+
Extract several named fields from `src` in one call.
|
|
861
|
+
|
|
862
|
+
- **Parameters:**
|
|
863
|
+
- `src` (Mapping | Sequence): Data structure to navigate
|
|
864
|
+
- `paths` (Mapping[str, Any]): Maps an output key to either a `dig()` path (uses
|
|
865
|
+
`common_kwargs`) or a dict of `dig()` kwargs (must include `'path'`) overriding
|
|
866
|
+
`common_kwargs` for just that key
|
|
867
|
+
- `**common_kwargs`: Default `dig()` kwargs (`exp`, `default`, `converter`, `validator`,
|
|
868
|
+
`post_processor`, `pop`) applied to every key that doesn't override them
|
|
869
|
+
|
|
870
|
+
- **Returns:** A dict with the same keys as `paths`, each value produced by the corresponding `dig()` call
|
|
871
|
+
|
|
872
|
+
**Example:**
|
|
873
|
+
|
|
874
|
+
```python
|
|
875
|
+
data = {'user': {'name': 'Alice', 'age': '30'}}
|
|
876
|
+
|
|
877
|
+
fields = dig_many(
|
|
878
|
+
data,
|
|
879
|
+
paths={
|
|
880
|
+
'name': 'user.name',
|
|
881
|
+
'age': {'path': 'user.age', 'exp': int, 'converter': int},
|
|
882
|
+
},
|
|
883
|
+
exp=str,
|
|
884
|
+
)
|
|
885
|
+
# Returns: {'name': 'Alice', 'age': 30}
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
#### `Digger(path=None, pop=False, post_processor=validate, **kwargs)`
|
|
889
|
+
|
|
890
|
+
A pre-bound, reusable `dig()` call. Validates/compiles the jmespath expression once at
|
|
891
|
+
construction (failing fast on a bad expression instead of on first use), then can be called
|
|
892
|
+
like a function against any number of `src` objects without repeating `path`/`exp`/kwargs.
|
|
893
|
+
|
|
894
|
+
**Example:**
|
|
895
|
+
|
|
896
|
+
```python
|
|
897
|
+
records = [{'user': {'name': 'Alice'}}, {'user': {'name': 'Bob'}}]
|
|
898
|
+
|
|
899
|
+
get_name = Digger(path='user.name', exp=str, default='')
|
|
900
|
+
[get_name(record) for record in records]
|
|
901
|
+
# Returns: ['Alice', 'Bob']
|
|
810
902
|
```
|
|
811
903
|
|
|
812
904
|
### `data` Module
|
|
@@ -118,7 +118,7 @@ print(text) # Rendered with ANSI codes
|
|
|
118
118
|
### Parsing & Validation
|
|
119
119
|
|
|
120
120
|
```python
|
|
121
|
-
from oj_toolkit import validate, get_datetime, str_to_list, dig
|
|
121
|
+
from oj_toolkit import validate, get_datetime, str_to_list, dig, dig_many, Digger
|
|
122
122
|
|
|
123
123
|
# Validate and convert types
|
|
124
124
|
result = validate('123', exp=int, converter=int) # Returns: 123
|
|
@@ -133,12 +133,31 @@ dt = get_datetime('2024-01-15T10:30:00') # ISO 8601
|
|
|
133
133
|
dt = get_datetime(1705318200) # Unix timestamp
|
|
134
134
|
dt = get_datetime('Mon, 15 Jan 2024 10:30:00 GMT') # HTTP date
|
|
135
135
|
|
|
136
|
-
# Extract and validate nested values
|
|
136
|
+
# Extract and validate nested values using a jmespath expression
|
|
137
137
|
data = {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}
|
|
138
|
-
name = dig(data, path=
|
|
139
|
-
|
|
138
|
+
name = dig(data, path='users[0].name', exp=str) # Returns: 'Alice'
|
|
139
|
+
names = dig(data, path='users[*].name', exp=list) # Returns: ['Alice', 'Bob']
|
|
140
|
+
|
|
141
|
+
# Fallback chain: first matching path wins (handy for optional/renamed fields)
|
|
142
|
+
name = dig(data, path=['users[0].nickname', 'users[0].name'], exp=str) # Returns: 'Alice'
|
|
143
|
+
|
|
144
|
+
# Extract several fields in one call
|
|
145
|
+
fields = dig_many(
|
|
146
|
+
data,
|
|
147
|
+
paths={'first_name': 'users[0].name', 'second_name': 'users[1].name'},
|
|
148
|
+
post_processor=None, # skip validate() and return raw matches
|
|
149
|
+
)
|
|
150
|
+
# Returns: {'first_name': 'Alice', 'second_name': 'Bob'}
|
|
151
|
+
|
|
152
|
+
# Bind a path once, reuse it against many objects
|
|
153
|
+
get_name = Digger(path='name', exp=str, default='')
|
|
154
|
+
[get_name(user) for user in data['users']] # Returns: ['Alice', 'Bob']
|
|
140
155
|
```
|
|
141
156
|
|
|
157
|
+
> **Note:** `dig()`'s default `post_processor` (`validate()`) only accepts a value if you pass
|
|
158
|
+
> `exp=<type>` -- without it, validation always fails and you get `default` back (`None` unless set).
|
|
159
|
+
> Pass `exp=` for a real value, or `post_processor=None` to skip validation and get the raw match.
|
|
160
|
+
|
|
142
161
|
### Logging Setup
|
|
143
162
|
|
|
144
163
|
Call `configure_logging` once at application startup (Lambda handler, CLI `main()`, FastAPI lifespan). Libraries should never call it — they only use `logging.getLogger(__name__)`.
|
|
@@ -736,19 +755,37 @@ get_datetime('Mon, 15 Jan 2024 10:30:00 GMT') # HTTP date
|
|
|
736
755
|
get_datetime('01/15/2024 10:30:00', format_str='%m/%d/%Y %H:%M:%S') # Custom
|
|
737
756
|
```
|
|
738
757
|
|
|
739
|
-
#### `dig(src, path=None, post_processor=validate, **kwargs)`
|
|
740
|
-
|
|
741
|
-
Extract and post-process a value from a nested data structure.
|
|
758
|
+
#### `dig(src, path=None, pop=False, post_processor=validate, **kwargs)`
|
|
742
759
|
|
|
743
|
-
|
|
760
|
+
Extract and post-process a value from a nested data structure, using [jmespath](https://jmespath.org/)
|
|
761
|
+
under the hood (`jmespath` is a required dependency).
|
|
744
762
|
|
|
745
763
|
- **Parameters:**
|
|
746
|
-
- `src` (
|
|
747
|
-
- `path` (
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
764
|
+
- `src` (Mapping | Sequence): Data structure to navigate
|
|
765
|
+
- `path` (int | str | list | None):
|
|
766
|
+
- `str` — a jmespath expression, e.g. `'users[0].name'`, `'users[*].name'`, `'users[?id==\`2\`].name'`
|
|
767
|
+
- `int` — shorthand for a single top-level index, e.g. `1` is equivalent to `'[1]'`
|
|
768
|
+
- `list[int | str]` — a fallback chain: each candidate is tried in order and the first
|
|
769
|
+
one whose result isn't `None` wins (handy for optional/renamed fields)
|
|
770
|
+
- `None` — treat `src` itself as the value to post-process
|
|
771
|
+
- `pop` (bool): If `True`, delete the terminal key/index of the *winning* expression from
|
|
772
|
+
its container after extracting the value (mutates `src` in place). Only honored when that
|
|
773
|
+
expression's terminal segment is unambiguous (no wildcards, filters, or projections) --
|
|
774
|
+
otherwise it's refused with a logged warning and the value is still returned unpopped.
|
|
775
|
+
- `post_processor` (Callable): Function to post-process the found value. Default: `validate()`.
|
|
776
|
+
Pass `None` to skip post-processing and get the raw match.
|
|
777
|
+
- `**kwargs`: Passed to `post_processor`
|
|
778
|
+
|
|
779
|
+
- **Returns:** Post-processed value, or `None` if extraction fails, no candidate path matches, or
|
|
780
|
+
no post-processor is specified and nothing was found
|
|
781
|
+
|
|
782
|
+
> **Type checkers:** pass `exp=<type>` to get a precise `<type> | None` return type instead of `Any`
|
|
783
|
+
> (`dig(data, path='...', exp=str)` type-checks as `str | None`). Passing `post_processor=None` types
|
|
784
|
+
> as `Any` (raw, unvalidated value). A custom `post_processor` types as that callable's own return type.
|
|
785
|
+
|
|
786
|
+
> **Passing no `exp`:** the default `validate()` post-processor only accepts a value when you give
|
|
787
|
+
> it `exp=<type>` -- without one, validation always fails and you get `default` back (`None` unless
|
|
788
|
+
> set). Either pass `exp=`, or `post_processor=None` to bypass validation entirely.
|
|
752
789
|
|
|
753
790
|
**Example:**
|
|
754
791
|
|
|
@@ -763,16 +800,70 @@ data = {
|
|
|
763
800
|
}
|
|
764
801
|
|
|
765
802
|
# Extract nested value
|
|
766
|
-
name = dig(data, path=
|
|
803
|
+
name = dig(data, path='response.users[0].name', exp=str)
|
|
767
804
|
# Returns: 'Alice'
|
|
768
805
|
|
|
769
806
|
# Extract with validation
|
|
770
|
-
user = dig(data, path=
|
|
807
|
+
user = dig(data, path='response.users[1]', exp=dict)
|
|
771
808
|
# Returns: {'id': 2, 'name': 'Bob'}
|
|
772
809
|
|
|
773
|
-
# Extract with custom post-processor
|
|
774
|
-
count = dig(data, path=
|
|
810
|
+
# Extract with custom post-processor (no exp needed -- len() isn't validate())
|
|
811
|
+
count = dig(data, path='response.users', post_processor=len)
|
|
775
812
|
# Returns: 2
|
|
813
|
+
|
|
814
|
+
# jmespath's full expression syntax is available -- wildcards, filters, functions, etc.
|
|
815
|
+
names = dig(data, path='response.users[*].name', exp=list)
|
|
816
|
+
# Returns: ['Alice', 'Bob']
|
|
817
|
+
|
|
818
|
+
# Fallback chain: try a renamed/optional field first, fall back to the old one
|
|
819
|
+
name = dig(data, path=['response.users[0].display_name', 'response.users[0].name'], exp=str)
|
|
820
|
+
# Returns: 'Alice'
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
#### `dig_many(src, paths, **common_kwargs)`
|
|
824
|
+
|
|
825
|
+
Extract several named fields from `src` in one call.
|
|
826
|
+
|
|
827
|
+
- **Parameters:**
|
|
828
|
+
- `src` (Mapping | Sequence): Data structure to navigate
|
|
829
|
+
- `paths` (Mapping[str, Any]): Maps an output key to either a `dig()` path (uses
|
|
830
|
+
`common_kwargs`) or a dict of `dig()` kwargs (must include `'path'`) overriding
|
|
831
|
+
`common_kwargs` for just that key
|
|
832
|
+
- `**common_kwargs`: Default `dig()` kwargs (`exp`, `default`, `converter`, `validator`,
|
|
833
|
+
`post_processor`, `pop`) applied to every key that doesn't override them
|
|
834
|
+
|
|
835
|
+
- **Returns:** A dict with the same keys as `paths`, each value produced by the corresponding `dig()` call
|
|
836
|
+
|
|
837
|
+
**Example:**
|
|
838
|
+
|
|
839
|
+
```python
|
|
840
|
+
data = {'user': {'name': 'Alice', 'age': '30'}}
|
|
841
|
+
|
|
842
|
+
fields = dig_many(
|
|
843
|
+
data,
|
|
844
|
+
paths={
|
|
845
|
+
'name': 'user.name',
|
|
846
|
+
'age': {'path': 'user.age', 'exp': int, 'converter': int},
|
|
847
|
+
},
|
|
848
|
+
exp=str,
|
|
849
|
+
)
|
|
850
|
+
# Returns: {'name': 'Alice', 'age': 30}
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
#### `Digger(path=None, pop=False, post_processor=validate, **kwargs)`
|
|
854
|
+
|
|
855
|
+
A pre-bound, reusable `dig()` call. Validates/compiles the jmespath expression once at
|
|
856
|
+
construction (failing fast on a bad expression instead of on first use), then can be called
|
|
857
|
+
like a function against any number of `src` objects without repeating `path`/`exp`/kwargs.
|
|
858
|
+
|
|
859
|
+
**Example:**
|
|
860
|
+
|
|
861
|
+
```python
|
|
862
|
+
records = [{'user': {'name': 'Alice'}}, {'user': {'name': 'Bob'}}]
|
|
863
|
+
|
|
864
|
+
get_name = Digger(path='user.name', exp=str, default='')
|
|
865
|
+
[get_name(record) for record in records]
|
|
866
|
+
# Returns: ['Alice', 'Bob']
|
|
776
867
|
```
|
|
777
868
|
|
|
778
869
|
### `data` Module
|
|
@@ -11,7 +11,7 @@ Centralized utilities for all ownjoo-org projects, including:
|
|
|
11
11
|
error can disappear silently (diagnostics module)
|
|
12
12
|
|
|
13
13
|
Usage:
|
|
14
|
-
from oj_toolkit import validate, get_datetime, str_to_list, dig
|
|
14
|
+
from oj_toolkit import validate, get_datetime, str_to_list, dig, dig_many, Digger
|
|
15
15
|
from oj_toolkit import timed_generator, timed_async_generator
|
|
16
16
|
from oj_toolkit import Output, Color, ColoredText
|
|
17
17
|
from oj_toolkit import Table, Box, status_line, progress_bar
|
|
@@ -33,7 +33,7 @@ from oj_toolkit.console import (
|
|
|
33
33
|
)
|
|
34
34
|
from oj_toolkit.diagnostics import install_exception_visibility
|
|
35
35
|
from oj_toolkit.logging import timed_async_generator, timed_generator
|
|
36
|
-
from oj_toolkit.parsing import validate, get_datetime, dig, str_to_list
|
|
36
|
+
from oj_toolkit.parsing import validate, get_datetime, dig, dig_many, Digger, str_to_list
|
|
37
37
|
|
|
38
38
|
__all__ = [
|
|
39
39
|
'timed_async_generator',
|
|
@@ -42,6 +42,8 @@ __all__ = [
|
|
|
42
42
|
'validate',
|
|
43
43
|
'get_datetime',
|
|
44
44
|
'dig',
|
|
45
|
+
'dig_many',
|
|
46
|
+
'Digger',
|
|
45
47
|
'str_to_list',
|
|
46
48
|
'Output',
|
|
47
49
|
'Color',
|
|
@@ -4,9 +4,9 @@ Provides functions for:
|
|
|
4
4
|
- Converting strings to lists with custom separators
|
|
5
5
|
- Parsing datetime values from multiple formats
|
|
6
6
|
- Validating and converting values with custom validators and converters
|
|
7
|
-
- Extracting and validating nested values from dicts/lists
|
|
7
|
+
- Extracting and validating nested values from dicts/lists (jmespath-backed)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
from oj_toolkit.parsing.types import validate, get_datetime, dig, str_to_list
|
|
10
|
+
from oj_toolkit.parsing.types import validate, get_datetime, dig, dig_many, Digger, str_to_list
|
|
11
11
|
|
|
12
|
-
__all__ = ['validate', 'get_datetime', 'dig', 'str_to_list']
|
|
12
|
+
__all__ = ['validate', 'get_datetime', 'dig', 'dig_many', 'Digger', 'str_to_list']
|