Skip to content

Commit aa9df81

Browse files
committed
Siva | enhance docstring in the library
1 parent ed685f9 commit aa9df81

5 files changed

Lines changed: 149 additions & 87 deletions

File tree

docs/api-reference.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ keywords:
1818
- error codes
1919
---
2020

21-
## Core Functions
21+
<!-- ### Core Functions -->
2222

2323
::: nestedutils.access
2424
options:
25-
show_root_heading: false
25+
show_root_heading: true
2626
show_root_toc_entry: false
2727
members:
2828
- get_at
@@ -31,4 +31,32 @@ keywords:
3131
- exists_at
3232
heading_level: 3
3333

34+
::: nestedutils.constants
35+
options:
36+
show_root_heading: true
37+
show_source: false
38+
heading_level: 3
39+
members:
40+
- MAX_DEPTH
41+
- MAX_LIST_SIZE
42+
members_order: source
43+
44+
::: nestedutils.enums
45+
options:
46+
show_root_heading: true
47+
show_source: false
48+
heading_level: 3
49+
members:
50+
- PathErrorCode
51+
- FillStrategy
52+
members_order: source
53+
54+
::: nestedutils.exceptions
55+
options:
56+
show_root_heading: true
57+
show_source: false
58+
heading_level: 3
59+
members:
60+
- PathError
61+
members_order: source
3462

nestedutils/access.py

Lines changed: 55 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,22 @@ def get_at(data: Any, path: Union[str, List[Any]], default: Any = None) -> Any:
2727
PathError: If the path is malformed, empty, or contains empty keys.
2828
2929
Examples:
30-
>>> data = {"a": {"b": {"c": 5}}}
31-
>>> get_at(data, "a.b.c")
32-
5
30+
```python
31+
data = {"a": {"b": {"c": 5}}}
32+
get_at(data, "a.b.c") # Returns: 5
3333
34-
>>> get_at(data, "a.b.d", default=99)
35-
99
34+
get_at(data, "a.b.d", default=99) # Returns: 99
3635
37-
>>> data = {"items": [{"name": "apple"}, {"name": "banana"}]}
38-
>>> get_at(data, "items.1.name")
39-
'banana'
36+
data = {"items": [{"name": "apple"}, {"name": "banana"}]}
37+
get_at(data, "items.1.name") # Returns: 'banana'
4038
41-
>>> get_at(data, "items.-1.name")
42-
'banana'
39+
get_at(data, "items.-1.name") # Returns: 'banana'
4340
44-
>>> get_at(data, "items.-5.name", default="not found")
45-
'not found'
41+
get_at(data, "items.-5.name", default="not found") # Returns: 'not found'
4642
47-
>>> data = (10, 20, 30)
48-
>>> get_at(data, "-1")
49-
30
43+
data = (10, 20, 30)
44+
get_at(data, "-1") # Returns: 30
45+
```
5046
"""
5147
keys = normalize_path(path)
5248
current = data
@@ -79,32 +75,21 @@ def exists_at(data: Any, path: Union[str, List[Any]]) -> bool:
7975
PathError: If the path is malformed, empty, or contains empty keys.
8076
8177
Examples:
82-
>>> data = {"a": {"b": {"c": 5}}}
83-
>>> exists_at(data, "a.b.c")
84-
True
78+
```python
79+
data = {"a": {"b": {"c": 5}}}
80+
exists_at(data, "a.b.c") # Returns: True
81+
exists_at(data, "a.b.d") # Returns: False
8582
86-
>>> exists_at(data, "a.b.d")
87-
False
83+
data = {"items": [{"name": "apple"}, {"name": "banana"}]}
84+
exists_at(data, "items.1.name") # Returns: True
85+
exists_at(data, "items.-1.name") # Returns: True
86+
exists_at(data, "items.-5.name") # Returns: False
87+
exists_at(data, "items.10.name") # Returns: False
8888
89-
>>> data = {"items": [{"name": "apple"}, {"name": "banana"}]}
90-
>>> exists_at(data, "items.1.name")
91-
True
92-
93-
>>> exists_at(data, "items.-1.name")
94-
True
95-
96-
>>> exists_at(data, "items.-5.name")
97-
False
98-
99-
>>> exists_at(data, "items.10.name")
100-
False
101-
102-
>>> data = (10, 20, 30)
103-
>>> exists_at(data, "2")
104-
True
105-
106-
>>> exists_at(data, "5")
107-
False
89+
data = (10, 20, 30)
90+
exists_at(data, "2") # Returns: True
91+
exists_at(data, "5") # Returns: False
92+
```
10893
"""
10994
keys = normalize_path(path)
11095
current = data
@@ -160,34 +145,30 @@ def set_at(
160145
'dict' uses {}; 'list' uses []).
161146
162147
Examples:
163-
>>> data = {}
164-
>>> set_at(data, "user.profile.name", "Alice")
165-
>>> data
166-
{'user': {'profile': {'name': 'Alice'}}}
148+
```python
149+
data = {}
150+
set_at(data, "user.profile.name", "Alice")
151+
# data is now: {'user': {'profile': {'name': 'Alice'}}}
167152
168-
>>> data = {}
169-
>>> set_at(data, "items.0.name", "Item 1")
170-
>>> data
171-
{'items': [{'name': 'Item 1'}]}
153+
data = {}
154+
set_at(data, "items.0.name", "Item 1")
155+
# data is now: {'items': [{'name': 'Item 1'}]}
172156
173-
>>> data = {}
174-
>>> set_at(data, "items.5", "last", fill_strategy="none")
175-
>>> data
176-
{'items': [None, None, None, None, None, 'last']}
157+
data = {}
158+
set_at(data, "items.5", "last", fill_strategy="none")
159+
# data is now: {'items': [None, None, None, None, None, 'last']}
177160
178-
>>> data = {}
179-
>>> set_at(data, "items.2.sub.value", 42) # 'auto' creates dict at target index, None for gaps
180-
>>> data
181-
{'items': [None, None, {'sub': {'value': 42}}]}
161+
data = {}
162+
set_at(data, "items.2.sub.value", 42) # 'auto' creates dict at target index, None for gaps
163+
# data is now: {'items': [None, None, {'sub': {'value': 42}}]}
182164
183-
>>> data = [1, 2, 3]
184-
>>> set_at(data, "5", 99) # extends with None gaps
185-
>>> data
186-
[1, 2, 3, None, None, 99]
165+
data = [1, 2, 3]
166+
set_at(data, "5", 99) # extends with None gaps
167+
# data is now: [1, 2, 3, None, None, 99]
187168
188-
>>> set_at(data, "-1", 100) # modifies existing last element
189-
>>> data
190-
[1, 2, 3, None, None, 100]
169+
set_at(data, "-1", 100) # modifies existing last element
170+
# data is now: [1, 2, 3, None, None, 100]
171+
```
191172
"""
192173
try:
193174
strategy = FillStrategy(fill_strategy)
@@ -295,27 +276,21 @@ def delete_at(
295276
index.
296277
297278
Examples:
298-
>>> data = {"a": {"b": 1, "c": 2}}
299-
>>> delete_at(data, "a.b")
300-
1
301-
>>> data
302-
{'a': {'c': 2}}
279+
```python
280+
data = {"a": {"b": 1, "c": 2}}
281+
delete_at(data, "a.b") # Returns: 1
282+
# data is now: {'a': {'c': 2}}
303283
304-
>>> data = {"items": [1, 2, 3]}
305-
>>> delete_at(data, "items.1", allow_list_mutation=True)
306-
2
307-
>>> data
308-
{'items': [1, 3]}
284+
data = {"items": [1, 2, 3]}
285+
delete_at(data, "items.1", allow_list_mutation=True) # Returns: 2
286+
# data is now: {'items': [1, 3]}
309287
310-
>>> delete_at(data, "items.-1", allow_list_mutation=True)
311-
3
312-
>>> data
313-
{'items': [1]}
288+
delete_at(data, "items.-1", allow_list_mutation=True) # Returns: 3
289+
# data is now: {'items': [1]}
314290
315-
>>> delete_at(data, "items.0") # without allow_list_mutation=True
316-
Traceback (most recent call last):
317-
...
318-
PathError: List deletion disabled. Set allow_list_mutation=True
291+
# Without allow_list_mutation=True, list deletion raises PathError
292+
delete_at(data, "items.0") # Raises: PathError: List deletion disabled...
293+
```
319294
"""
320295
keys = normalize_path(path)
321296
current = data

nestedutils/constants.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
MAX_DEPTH = 100 # Maximum allowed depth for nested paths
2-
MAX_LIST_SIZE = 10000 # Maximum allowed list index to prevent memory exhaustion
1+
"""Constants for nestedutils library."""
2+
3+
MAX_DEPTH = 100
4+
"""Maximum allowed depth for nested paths. Paths exceeding this depth will raise a PathError."""
5+
6+
MAX_LIST_SIZE = 10000
7+
"""Maximum allowed list index. List indices exceeding this value will raise a PathError."""
38

nestedutils/enums.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1+
"""Enumerations for nestedutils library.
2+
3+
This module defines error codes and configuration enums used throughout
4+
the nestedutils library for consistent error handling and behavior control.
5+
"""
6+
17
from enum import Enum
28

9+
310
class PathErrorCode(Enum):
4-
"""Error codes for path-related exceptions."""
11+
"""Error codes for path-related exceptions.
12+
13+
Example:
14+
```python
15+
from nestedutils import get_at, PathError, PathErrorCode
16+
17+
data = {"a": {"b": 1}}
18+
try:
19+
get_at(data, "a.c.d")
20+
except PathError as e:
21+
if e.code == PathErrorCode.MISSING_KEY:
22+
print("Key not found")
23+
```
24+
"""
525
INVALID_INDEX = "INVALID_INDEX"
626
MISSING_KEY = "MISSING_KEY"
727
EMPTY_PATH = "EMPTY_PATH"
@@ -11,7 +31,16 @@ class PathErrorCode(Enum):
1131

1232

1333
class FillStrategy(Enum):
14-
"""Strategy for filling missing containers when setting nested paths."""
34+
"""Strategy for filling missing containers when setting nested paths.
35+
36+
Example:
37+
```python
38+
from nestedutils import set_at, FillStrategy
39+
40+
data = {}
41+
set_at(data, "items.0.name", "apple", fill_strategy=FillStrategy.AUTO)
42+
```
43+
"""
1544
AUTO = "auto"
1645
NONE = "none"
1746
DICT = "dict"

nestedutils/exceptions.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
1+
"""Custom exceptions for the nestedutils library.
2+
3+
This module defines all custom exceptions used throughout the nestedutils
4+
library. The main exception class is PathError, which includes error codes
5+
for detailed error handling.
6+
"""
7+
18
from typing import Optional
29
from .enums import PathErrorCode
310

11+
412
class PathError(Exception):
5-
"""Raised when a nested path cannot be navigated or modified."""
13+
"""Raised when a nested path cannot be navigated or modified.
14+
15+
Attributes:
16+
message: Human-readable error message.
17+
code: Optional PathErrorCode for programmatic error handling.
18+
19+
Example:
20+
```python
21+
from nestedutils import get_at, PathError, PathErrorCode
22+
23+
data = {"a": {"b": 1}}
24+
try:
25+
get_at(data, "a.c.d")
26+
except PathError as e:
27+
if e.code == PathErrorCode.MISSING_KEY:
28+
print("Key not found")
29+
```
30+
"""
631

732
def __init__(self, message: str, code: Optional[PathErrorCode] = None) -> None:
833
super().__init__(message)

0 commit comments

Comments
 (0)