0
# Path Access Operations
1
2
Core functions for getting and setting values at specific paths in nested dictionaries. These operations support both exact paths and glob patterns, with robust handling of missing keys and type coercion.
3
4
## Capabilities
5
6
### Getting Values
7
8
Retrieve single values from nested dictionaries using path notation with support for default values and error handling.
9
10
```python { .api }
11
def get(obj, glob, separator="/", default=_DEFAULT_SENTINEL):
12
"""
13
Get single value matching glob pattern.
14
15
Parameters:
16
- obj (MutableMapping): Target dictionary to search
17
- glob (Glob): Path pattern as string or sequence of path segments
18
- separator (str): Path separator character (default "/")
19
- default (Any): Default value if not found (raises KeyError if not provided)
20
21
Returns:
22
Any: The matched value
23
24
Raises:
25
- KeyError: If glob not found and no default provided
26
- ValueError: If glob matches multiple values
27
"""
28
```
29
30
#### Usage Examples
31
32
```python
33
import dpath
34
35
data = {
36
"users": {
37
"john": {"age": 30, "profile": {"city": "NYC"}},
38
"jane": {"age": 25, "profile": {"city": "LA"}}
39
}
40
}
41
42
# Get exact path
43
age = dpath.get(data, "users/john/age") # Returns: 30
44
45
# Get with default value
46
phone = dpath.get(data, "users/john/phone", default="N/A") # Returns: "N/A"
47
48
# Get root object
49
root = dpath.get(data, "/") # Returns: entire data dict
50
51
# Use list-based paths (useful for keys containing separators)
52
city = dpath.get(data, ["users", "john", "profile", "city"]) # Returns: "NYC"
53
54
# Custom separator
55
dpath.get(data, "users.john.age", separator=".") # Returns: 30
56
```
57
58
### Creating New Paths
59
60
Create new paths in dictionaries, automatically generating missing intermediate dictionaries or lists as needed.
61
62
```python { .api }
63
def new(obj, path, value, separator="/", creator=None):
64
"""
65
Create new path and set value, creating missing intermediate keys.
66
67
Parameters:
68
- obj (MutableMapping): Target dictionary to modify
69
- path (Path): Path as string or sequence (NOT treated as glob)
70
- value (Any): Value to set at the path
71
- separator (str): Path separator character (default "/")
72
- creator (Creator): Optional function to create missing path components
73
74
Returns:
75
MutableMapping: The modified input object
76
77
Note:
78
Path is treated literally - globbing characters become part of key names.
79
"""
80
```
81
82
#### Usage Examples
83
84
```python
85
import dpath
86
87
data = {}
88
89
# Create nested structure automatically
90
dpath.new(data, "config/database/host", "localhost")
91
# Result: {'config': {'database': {'host': 'localhost'}}}
92
93
# Create with numeric keys (creates lists)
94
dpath.new(data, "items/0/name", "first item")
95
# Result: {'items': [{'name': 'first item'}]}
96
97
# Mix of dict and list creation
98
dpath.new(data, "users/0/contacts/email", "john@example.com")
99
# Result: {'users': [{'contacts': {'email': 'john@example.com'}}]}
100
101
# Custom creator function
102
def list_creator(current, segments, i, hints=()):
103
"""Always create lists instead of dicts"""
104
segment = segments[i]
105
current[segment] = []
106
107
dpath.new(data, "always_list/key", "value", creator=list_creator)
108
109
# Globbing characters become literal keys
110
dpath.new(data, "weird/*/key", "value") # Creates key literally named "*"
111
```
112
113
### Setting Existing Values
114
115
Update values at paths that already exist, with support for glob patterns to update multiple locations simultaneously.
116
117
```python { .api }
118
def set(obj, glob, value, separator="/", afilter=None):
119
"""
120
Set value for all existing elements matching glob.
121
122
Parameters:
123
- obj (MutableMapping): Target dictionary to modify
124
- glob (Glob): Path pattern as string or sequence
125
- value (Any): Value to set at matching paths
126
- separator (str): Path separator character (default "/")
127
- afilter (Filter): Optional function to filter which values to set
128
129
Returns:
130
int: Number of elements changed
131
132
Note:
133
Only modifies existing paths - does not create new ones.
134
"""
135
```
136
137
#### Usage Examples
138
139
```python
140
import dpath
141
142
data = {
143
"users": {
144
"john": {"age": 30, "active": True},
145
"jane": {"age": 25, "active": False},
146
"bob": {"age": 35, "active": True}
147
}
148
}
149
150
# Set all user ages to same value
151
count = dpath.set(data, "users/*/age", 999) # Returns: 3
152
# Result: All users now have age 999
153
154
# Set with filter - only update active users
155
def active_filter(value):
156
return isinstance(value, dict) and value.get("active", False)
157
158
# First search for active users, then update their ages
159
count = dpath.set(data, "users/*", {"age": 100, "active": True},
160
afilter=lambda user: user.get("active", False))
161
162
# Set single exact path
163
count = dpath.set(data, "users/john/age", 31) # Returns: 1
164
165
# Use custom separator
166
count = dpath.set(data, "users.*.active", False, separator=".")
167
168
# Returns 0 if no existing paths match
169
count = dpath.set(data, "nonexistent/*/field", "value") # Returns: 0
170
```
171
172
## Path Format Support
173
174
All path access functions support multiple path formats:
175
176
### String Paths
177
- `"users/john/age"` - Standard slash-separated paths
178
- `"users.john.age"` - Custom separator paths
179
- `"users/*/age"` - Glob patterns with wildcards
180
- `"users/**/age"` - Recursive glob patterns
181
182
### List Paths
183
- `["users", "john", "age"]` - Explicit path segments (separator ignored)
184
- `["users", "*", "age"]` - Glob patterns in list format
185
- Useful when keys contain separator characters
186
187
### Numeric Indices
188
- String indices: `"items/0/name"` - Automatically converted to int for sequences
189
- Integer indices: `["items", 0, "name"]` - Direct integer access
190
- Negative indices: `["items", -1, "name"]` - Supported for sequences
191
192
## Error Handling
193
194
```python
195
# KeyError for missing paths without default
196
try:
197
value = dpath.get(data, "missing/path")
198
except KeyError as e:
199
print(f"Path not found: {e}")
200
201
# ValueError for ambiguous gets
202
try:
203
value = dpath.get(data, "users/*/age") # Multiple matches
204
except ValueError as e:
205
print(f"Ambiguous path: {e}")
206
207
# PathNotFound from dpath.exceptions
208
from dpath.exceptions import PathNotFound
209
try:
210
# Some operations may raise PathNotFound instead of KeyError
211
pass
212
except PathNotFound as e:
213
print(f"Path operation failed: {e}")
214
```