TreeDict
TreeDict is a hierarchical dictionary that provides dot notation path access to nested data structures.
Basic Usage
from genro_toolbox import TreeDict
# Create from nested dict
td = TreeDict({"user": {"name": "Alice", "prefs": {"theme": "dark"}}})
# Path string access
td["user.name"] # "Alice"
td["user.prefs.theme"] # "dark"
# Missing keys return None (no KeyError)
td["missing"] # None
td["user.missing"] # None
Creating TreeDict
From dict
td = TreeDict({"a": {"b": {"c": 1}}})
From JSON string
td = TreeDict('{"user": {"name": "Alice"}}')
From config file
# Supports JSON, YAML, TOML, INI
td = TreeDict.from_file("config.yaml")
td = TreeDict.from_file("settings.json")
td = TreeDict.from_file("config.toml")
td = TreeDict.from_file("app.ini")
Empty TreeDict
td = TreeDict()
td["settings.theme"] = "dark" # auto-creates intermediate dicts
Writing Values
TreeDict auto-creates intermediate dictionaries when writing:
td = TreeDict()
# This creates {"settings": {"db": {"host": "localhost"}}}
td["settings.db.host"] = "localhost"
td["settings.db.port"] = 5432
td.as_dict()
# {"settings": {"db": {"host": "localhost", "port": 5432}}}
List Access
Use #N syntax to access list elements:
td = TreeDict({
"users": [
{"name": "Alice", "role": "admin"},
{"name": "Bob", "role": "user"}
]
})
td["users.#0.name"] # "Alice"
td["users.#1.role"] # "user"
td["users.#0"] # {"name": "Alice", "role": "admin"}
Deleting Keys
td = TreeDict({"a": {"b": 1, "c": 2}})
del td["a.b"]
td.as_dict() # {"a": {"c": 2}}
# Delete from list
td = TreeDict({"items": [1, 2, 3]})
del td["items.#0"]
td["items"] # [2, 3]
Walking All Paths
Iterate over all paths and values:
td = TreeDict({
"user": {"name": "Alice"},
"settings": {"theme": "dark"}
})
for path, value in td.walk():
print(f"{path} = {value}")
# Output:
# user.name = Alice
# settings.theme = dark
Expanding Lists
td = TreeDict({"items": [{"id": 1}, {"id": 2}]})
for path, value in td.walk(expand_lists=True):
print(f"{path} = {value}")
# Output:
# items.#0.id = 1
# items.#1.id = 2
Thread-Safe Access
TreeDict provides context managers for thread-safe operations:
Synchronous (threading)
td = TreeDict({"counter": 0})
# Thread-safe read-modify-write
with td:
td["counter"] = td["counter"] + 1
Asynchronous (asyncio)
td = TreeDict({"counter": 0})
async with td:
td["counter"] = td["counter"] + 1
The lock protects all operations within the with block. Always use the root TreeDict for locking.
Converting Back to Dict
td = TreeDict({"user": {"name": "Alice"}})
# Get underlying data
data = td.as_dict() # {"user": {"name": "Alice"}}
SmartOptions Relationship
SmartOptions extends TreeDict with additional features for configuration management:
from genro_toolbox import SmartOptions
# SmartOptions IS-A TreeDict
opts = SmartOptions({"server": {"host": "localhost"}})
opts["server.host"] # "localhost" - TreeDict path access works
See SmartOptions Guide for configuration-specific features.
Use Cases
Configuration Access
config = TreeDict.from_file("config.yaml")
db_host = config["database.host"]
db_port = config["database.port"]
debug = config["app.debug"]
Building Nested Structures
response = TreeDict()
response["status"] = "success"
response["data.user.id"] = 123
response["data.user.name"] = "Alice"
response["meta.timestamp"] = "2025-01-01"
response.as_dict()
# {
# "status": "success",
# "data": {"user": {"id": 123, "name": "Alice"}},
# "meta": {"timestamp": "2025-01-01"}
# }