Skip to main content

Nougat 🍫

PyPI version License: MIT Python Versions Test and Build

PyPI - Wheel GitHub Release GitHub repo size

logo
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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Made with ❤️ for all Python developers tired of KeyError exceptions and messy data.get('obj', {}).get('key', None) chains

Metadata

Release files for pynougat 0.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pynougat 0.0.2
File Size Uploaded Provenance
pynougat-0.0.2.tar.gz 5.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pynougat 0.0.2
File Interpreter ABI Platform
pynougat-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 11.5 kB

Release files / pynougat-0.0.2.tar.gz

Download URL pynougat-0.0.2.tar.gz
Size 5.5 kB
Tags Source
SHA-256 checksum
How to use checksums
fe1beffca55e92544da91beb310d4ab8286e14bb2e5942e81e8b72812109f636
BLAKE2b-256 checksum
How to use checksums
afd51d3c137b9ace6974be21e5d38ebb251f989f63198a5be9dfe97681f5740d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Release files / pynougat-0.0.2-py3-none-any.whl

Download URL pynougat-0.0.2-py3-none-any.whl
Size 6.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f1e21ee973c3dc9c72ba20e65624bed91fd8f39352b1dec4917472247f96c3b0
BLAKE2b-256 checksum
How to use checksums
d07fe24ee00409ec7e13c0d34ac335c8c1b7dc936ac97db9809d76bb4fd7060b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Security for pynougat 0.0.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page