Skip to main content

A lightweight type-safe Python utility for safely accessing deeply nested dictionary values

Project description

Nougat 🍫

PyPI version License: MIT Python Versions Test and Build

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pynougat-0.0.1.tar.gz (5.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pynougat-0.0.1-py3-none-any.whl (5.9 kB view details)

Uploaded Python 3

File details

Details for the file pynougat-0.0.1.tar.gz.

File metadata

  • Download URL: pynougat-0.0.1.tar.gz
  • Upload date:
  • Size: 5.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for pynougat-0.0.1.tar.gz
Algorithm Hash digest
SHA256 dee1f83bcfd9c967d460eb40a8123821afc3089f8673c1e4047f642c8bb2c4d5
MD5 b5cdfe2ae172994f56788e5512184ed6
BLAKE2b-256 e5d11326ea0324e2660cf054ba932cb03d1b3575adf92ad6e538cc8235c7a177

See more details on using hashes here.

File details

Details for the file pynougat-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: pynougat-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 5.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for pynougat-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5f71bb63eead3c668f6edb841d85baec33565ec799fc4201bee9c8bea9e00fac
MD5 eace0ad88a5061cd214825938233ef85
BLAKE2b-256 79e7241965759c74bcba84ad68d6b95fe8e6a5162d6f428c0deab9c201d1b112

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page