A lightweight type-safe Python utility for safely accessing deeply nested dictionary values
Project description
Nougat 🍫
A lightweight type-safe Python utility for safely accessing deeply nested dictionary values.
Overview
Nougat solves the common problem of accessing nested dictionary values without raising KeyError exceptions. It provides high-performance nested dictionary access with a clean, type-safe interface for traversing nested dictionaries, returning a default value when any key in the path doesn't exist. Stop worrying about KeyError exceptions and messy null checks!
Problem
Working with nested dictionaries in Python often leads to verbose, error-prone code:
# Deeply nested access without Nougat
data = {...}
user_city = None
if 'user' in data and data['user'] and 'profile' in data['user'] \
and data['user']['profile'] and 'address' in data['user']['profile']:
if 'city' in data['user']['profile']['address']:
user_city = data['user']['profile']['address']['city']
Or risky code that might raise exceptions:
# Error-prone approach
data = {...}
try:
user_city = data['user']['profile']['address']['city']
except (KeyError, TypeError):
user_city = None
Solution
Nougat provides a clean, performant way to safely access nested values:
# With Nougat
from src import nougat
data = {...}
user_city = nougat(data, "user", "profile", "address", "city", default="Unknown")
Installation
via pip:
pip install pynougat
via git+pip:
# Clone the repository
git clone https://github.com/sphireinc/pynougat.git
# Install directly with pip
pip install git+https://github.com/sphireinc/pynougat.git
Usage
Basic Usage
from src.pynougat import nougat
# Sample nested data
data = {
"user": {
"profile": {
"name": "Alice",
"address": {
"city": "Seattle",
"zip": "98101"
}
},
"preferences": {
"theme": "dark"
},
"scores": [85, 92, 78]
}
}
# Simple path traversal
name = nougat(data, "user", "profile", "name") # "Alice"
# Default values for missing paths
country = nougat(data, "user", "profile", "address", "country", default="USA") # "USA"
# Access list items
second_score = nougat(data, "user", "scores", 1) # 92
# Path doesn't exist? No problem!
missing = nougat(data, "user", "profile", "age", default=0) # 0
Advanced Features
Dot Notation
from src.pynougat import nougat
# Use dot strings for cleaner access
theme = nougat(data, "user.preferences.theme", separator=".") # "dark"
Alternative Keys
from src.pynougat import nougat
# Try multiple keys at each level and use first match
theme = nougat(data, ("users", "user"), "preferences", ("appearance", "theme"))
Value Transformation
from src.pynougat import nougat
# Transform the returned value
scores_sum = nougat(data, "user", "scores", transform=sum) # 255 (85+92+78)
Path Caching for High Performance
from src.pynougat import nougat_cached
# Create a reusable, cached accessor function for a specific path
data1 = {}
data2 = {}
get_user_city = nougat_cached(["user", "profile", "address", "city"])
# Use it repeatedly for high performance
city1 = get_user_city(data1)
city2 = get_user_city(data2)
Strict Type Checking
from src.pynougat import nougat
# Enable strict type checking for better error identification
nougat(data, "user", "profile", "address", strict_types=True)
Features
- Zero dependencies - just pure Python
- ⚡ Highly optimized for performance
- 🛡️ Type-safe with full mypy support
- 🧠 Smart traversal of dicts, lists, tuples, and custom objects
- 🔄 Alternative paths to try multiple access routes
- 🔍 Dot notation support for concise access patterns
- 🚀 Path caching for repeated high-performance lookups
- 🪄 Value transformation to process retrieved values
- 🔒 Never raises exceptions for a clean, predictable API
- Customizable default values
- Handles any depth of nesting
- Lightweight and fast
When to Use Nougat
- Accessing configuration values that might not exist
- Processing API responses with varying structures
- Handling user input or preferences with optional fields
- Any situation where you need to safely navigate nested dictionaries
Performance
Nougat is optimized for high performance:
- Fast paths for common data types
- Minimal overhead for common operations
- Path caching for repeated access
- Exception-free operation
License
MIT License - See LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Made with ❤️ for all Python developers tired of KeyError exceptions and messy data.get('obj', {}).get('key', None) chains
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pynougat-0.0.2.tar.gz.
File metadata
- Download URL: pynougat-0.0.2.tar.gz
- Upload date:
- Size: 5.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe1beffca55e92544da91beb310d4ab8286e14bb2e5942e81e8b72812109f636
|
|
| MD5 |
a7bf5d96851f632f76df224388560d6b
|
|
| BLAKE2b-256 |
afd51d3c137b9ace6974be21e5d38ebb251f989f63198a5be9dfe97681f5740d
|
File details
Details for the file pynougat-0.0.2-py3-none-any.whl.
File metadata
- Download URL: pynougat-0.0.2-py3-none-any.whl
- Upload date:
- Size: 6.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1e21ee973c3dc9c72ba20e65624bed91fd8f39352b1dec4917472247f96c3b0
|
|
| MD5 |
52945f602140e066d77b2f8849a0f673
|
|
| BLAKE2b-256 |
d07fe24ee00409ec7e13c0d34ac335c8c1b7dc936ac97db9809d76bb4fd7060b
|