Skip to main content

Python safe navigation for complex objects

Project description

Daisies

Daisies is a Python library that provides easy, safe navigation for complex objects.

from daisies import Chain

raw = {
    "never": {
        "gonna": {
            "give": {
                "you": {
                    "up": "never gonna let you down"
                }
            }
        }
    },
    "artists": [
        {
            "name": "Rick Astley",
            "genre": "Pop"
        },
        {
            "name": "Michael Jackson",
            "genre": "Pop"
        }
    ]
}
data = Chain(raw)


# Accessing nested dict keys that may or may not exist
print(data.never.gonna.give.you.up)  # "never gonna let you down"
print(data.let.you.down)  # None

# Navigating through lists
print(data.artists[0].name)  # "Rick Astley"
print(data.artists[1].name)  # "Michael Jackson"
print(data.artists[2].name)  # None

Installation and Support

Daisies is available on PyPI, so you can install it like any other Python package, using the packager of your choice.

pip install daisies

Daisies is automatically tested with 100% coverage on Python 3.10 and above for Ubuntu, macOS, and Windows.

Why Daisies?

Daisies makes data navigation easy and safe so you don't have to constantly null-check, coalesce, try/except, and if/else.

You want data? Just go get it.

Simply wrap your raw data in a Chain object, which allows you to access its attributes using the dot notation. If a key, attribute, or list index does not exist, the Chain object will return None instead of raising an exception.

This is particularly useful when dealing with complex data structures, such as JSON responses from APIs, where you can't always guarantee the presence of every key or index.

Usage

Daisies aims to be as simple and intuitive as possible, so you can use it without having to write tons of code for null-checking and type validation.

For the most part, you can just use Daisies and pretend that you're working with the raw data directly. However, there are some important differences to be aware of, especially when working with scalar values, arithmetic operations, and identity comparisons.

Usage: Scalar values

Daisies allows you to seamlessly work with scalar values, such as strings, integers, and Booleans. This allows you to operate on your data naturally.

data = Chain({
    "name": "John Doe",
    "age": 30,
    "is_active": True
})

print(data.name)  # "John Doe"
print(data.age)  # 30
print(data.is_active)  # True

You can operate at any point on the Chain object, and it will return the expected result.

data = Chain({
    "name": "John Doe",
    "age": 30,
    "is_active": True
})

print(data.name.upper())  # "JOHN DOE"
print(data.age + 10)  # 40

Usage: Numeric values and arithmetic operations

Daisies allows you to work with numeric values and perform arithmetic operations on them, but certain operations work differently from usual to ensure that you don't raise errors, such as coercing None values to zero.

data = Chain({
    "price": 100,
    "quantity": 5
})

print(data.price * data.quantity)  # 500
print(data.missing + 10)  # 10
print(data.quantity ** 3)  # 125

# Chain even allows division by zero, returning 0 instead.
# Not even Stephen Hawking could do that.
print(data.missing / 0)  # 0

Usage: Lists and other iterables

Daisies allows you to work with lists, sets, and other iterables in a natural way. You can access items by index and iterate over them. If they don't exist, Daisies will return None.

data = Chain({
    "names": ["Alice", "Bob", "Charlie"]
})

print(data.names[0])  # "Alice"
print(data.names[50])  # None

for index, name in enumerate(data.names):
    print(name)

Working with dicts and nested data

Daisies allows you to work with nested data structures quickly and easily. No more null-checking or catching KeyErrors.

data = Chain({
    "user": {
        "name": "Alice",
        "address": {
            "city": "Wonderland",
            "country": "Fairyland"
        }
    }
})

print(data.user.name)  # "Alice"
print(data.user.address.city)  # "Wonderland"
print(data.this.is.missing)  # None

Usage: Special values and identity comparisons

When you access items through a Chain, it's not directly returning the value, it's returning a Chain wrapping the value. A Chain is a very powerful and dynamic object that allows all sorts of operations on it, but it's not the same as the raw value.

This means there are a few special cases to be aware of. Because values are wrapped in a Chain, you can't use the identity operator is to check if a value is None, True, or False like usual.

But good news! If you want to compare identity, you can call the key like it's a function, and it'll return the raw value.

data = Chain({
    "name": "John Doe",
    "age": 30,
    "is_active": True
})
print(data.is_active is True)  # False :(
print(data.missing.key is None)  # False :(
print(data.is_active() is True)  # True :)
print(data.missing.key() is None)  # True :)

Usage: Navigating reserved words and invalid keys

Certain names are reserved in Python, so if your data contains keys that are reserved words or against the Python grammar, you can still access them by using the square bracket notation. In fact, you never have to use the dot notation if you hate it! Either way Daisies will make sure it's safe navigation.

data = Chain({
    "123": "Hello World!",
    "jeffrey-epstein": "Didn't kill himself"
})

print(data.123)  # SyntaxError :(
print(data["123"])  # "Hello World!"

print(data.jeffrey-epstein)  # SyntaxError :(
print(data["jeffrey-epstein"])  # "Didn't kill himself"

Contributing

Feel free to report bugs and suggest features through GitHub Issues, or open a PR for improvements.

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

daisies-0.1.0.tar.gz (5.1 kB view details)

Uploaded Source

Built Distribution

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

daisies-0.1.0-py3-none-any.whl (5.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: daisies-0.1.0.tar.gz
  • Upload date:
  • Size: 5.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for daisies-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4ec55d9d5df152223f23ca1df50a3b77c8c16776b3747a7fe7807ad72ab4e39e
MD5 beb6a765db90e7b28e38f1f7616e8341
BLAKE2b-256 54cb7a9015f8ad968f16955c456bf68c4bf11c97ace6252155caad95c5ba78c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for daisies-0.1.0.tar.gz:

Publisher: publish.yml on SerenitySoftware/daisies

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: daisies-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 5.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for daisies-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 57ebb9c9c48e9d4950d18e2ec426b319876bfc8da6714caa2eee5b22d4f6ac9e
MD5 02c139575b36268a4c42c393c7b513b5
BLAKE2b-256 9725522cf82bc0a6dbb20442c22e7ea4f94b29940a55527e5b39986927fd5983

See more details on using hashes here.

Provenance

The following attestation bundles were made for daisies-0.1.0-py3-none-any.whl:

Publisher: publish.yml on SerenitySoftware/daisies

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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