Skip to main content

A Python package containing rich-object utilities

Project description

rich-object

A powerful dictionary wrapper subclass that enables dot-notation attribute access, automatic nested path creation (autovivification), recursive locking, template rendering, JSONPath query resolution, and deep structure diffing.

Installation

pip install rich-object

Features & Examples

1. Basic Usage & Dot Access

Create an Object from mappings or keyword arguments and access properties with standard dot notation.

from rich_object import Object

# Initialize using keywords or raw dictionaries
obj = Object(name="John", address={"city": "New York"})

print(obj.name)          # -> "John"
print(obj.address.city)  # -> "New York"

2. Autovivification

Missing nested directories/attributes are automatically initialized when accessed, resolving nested paths on the fly.

obj = Object()
obj.user.profile.settings.theme = "dark"

print(obj.to_dict())
# -> {'user': {'profile': {'settings': {'theme': 'dark'}}}}

3. Structural Locks

Prevent mutations (creation, updates, deletes) recursively across all nested dictionaries and lists by passing lock=True.

frozen = Object({"items": [1, 2], "user": {"id": 42}}, lock=True)

# Any mutation throws a TypeError
try:
    frozen.user.id = 99
except TypeError as e:
    print(e)  # -> 'Object' is locked and cannot be modified

try:
    frozen.items.append(3)
except TypeError as e:
    print(e)  # -> 'ObjectList' is locked and cannot be modified

4. Advanced Property Setting (set)

Assign values safely to deeply nested paths using dot notation and bracket indices. Intermediary dictionary keys and list slots expand automatically.

obj = Object()
obj.set("store.books[1].title", "Moby Dick")

print(obj.store.books[1].title)  # -> "Moby Dick"
print(obj.store.books[0])        # -> None (automatically padded slot)

5. JSONPath Querying (get)

Query the data structure dynamically by passing JSONPath queries starting with $.

data = Object({
    "store": {
        "book": [
            {"category": "fiction", "price": 8.95},
            {"category": "reference", "price": 12.00}
        ]
    }
})

# Retrieve a single value
print(data.get("$.store.book[0].category"))  # -> "fiction"

# Retrieve matching node value list
print(data.get("$..price"))                  # -> [8.95, 12.0]

6. Deep Merging (+)

Perform clean, recursive merges of two structures using the + operator. Nested lists are automatically concatenated, and conflicting keys default to the right-hand value.

obj1 = Object({"a": {"x": 1}, "b": [1, 2]})
obj2 = Object({"a": {"y": 2}, "b": [3, 4]})

res = obj1 + obj2
print(res.to_dict())
# -> {'a': {'x': 1, 'y': 2}, 'b': [1, 2, 3, 4]}

7. Template Rendering (render)

Render Jinja2 templates in all string values recursively across the entire structure (including nested dictionaries and lists).

obj = Object({
    "first_name": "Jane",
    "greeting": "Hello {{ first_name }}!",
    "matrix": [["Welcome {{ first_name }}"]]
})

rendered = obj.render()
print(rendered.greeting)  # -> "Hello Jane!"
print(rendered.matrix)    # -> [["Welcome Jane"]]

You can also pass entire modules or objects to the render method to use them inside your templates:

import datetime

obj = Object({
    "year": "{{ dt.datetime(2026, 7, 6).year }}",
    "future_date": "{{ (dt.datetime(2026, 7, 6) + dt.timedelta(days=5)).strftime('%Y-%m-%d') }}"
})

res = obj.render(dt=datetime)
print(res.year)         # -> 2026
print(res.future_date)  # -> "2026-07-11"

8. Structural Diffing (diff)

Identify differences between two objects using the built-in DeepDiff interface.

obj1 = Object({"a": 1, "b": 2})
obj2 = Object({"a": 1, "b": 3})

difference = obj1.diff(obj2)
print(difference)
# -> {'values_changed': {"root['b']": {'new_value': 3, 'old_value': 2}}}

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

rich_object-0.1.0.tar.gz (10.6 kB view details)

Uploaded Source

Built Distribution

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

rich_object-0.1.0-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file rich_object-0.1.0.tar.gz.

File metadata

  • Download URL: rich_object-0.1.0.tar.gz
  • Upload date:
  • Size: 10.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for rich_object-0.1.0.tar.gz
Algorithm Hash digest
SHA256 32bd2eca1bc9bf8f4324eb8fad6b81ed4e2f3ea9c8e09442cea6976c2536d809
MD5 15371af9530115907994bec8f54a68a6
BLAKE2b-256 8368cfb40eae2e3ab655105c412e831a5d7e838e8c7661b44dded9f599dcc2a8

See more details on using hashes here.

File details

Details for the file rich_object-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: rich_object-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for rich_object-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6066410c384c34d6e2c3f3ea4ea6cfc5d0870f57885c175b56cdb380c9fcafa7
MD5 a483167ec7ce7e029574636b41deb9d0
BLAKE2b-256 d3f289a1f2c59764cca8a06efac57aa692db4a296b64c68e7a89a99e168bc969

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