A functional data navigation tool for Python
Project description
DataDot (DD) 🔍
中文文档 | English
DataDot (DD) is a Python library designed to simplify data access. It provides a chain-style calling method to safely access nested data structures without cumbersome null checks.
Key Features
- 🔗 Chain-style API
- 🛡️ Safe attribute and index access
- 🔒 Null-safe handling (using
._modifier) - 🔄 Data structure expansion operations
- 📝 Friendly error messages
Examples
# Assume we have the following nested data structure
data = {
"users": [
{"name": "Zhang San", "details": {"age": 30, "email": "zhangsan@example.com"}},
{"name": "Li Si", "details": {"age": 25, "email": "lisi@example.com"}}
]
}
# Using DD to access data ✨
from dd import dd
# Get the email of the first user 📧
email = dd(data).users[0].details.email()
print(email) # Output: zhangsan@example.com
# Null-safe handling 🛡️
missing = dd(data)._.users[3].details.email()
print(missing) # Output: None instead of raising an exception
# Expansion operation to get all user names 👥
names = dd(data).users[...].name()
print(names) # Output: ['Zhang San', 'Li Si']
✨ Features
- 🔗 Chainable API: Easy navigation through nested data with dot notation
- 🛡️ Error Handling: Beautiful error messages with path information
- 🔒 Null Safety: Optional null-safe operations with
._(applies to all subsequent operations) - 🔄 List/Dict Expansion: Process all items in a collection with
[...] - ⏳ Lazy Evaluation: Operations are recorded and only executed when the final value is needed
📦 Installation
pip install datadot
🚀 Quick Start
🔰 Basic Usage
from dd import dd
# Simple data access
data = {"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}
alice_age = dd(data).users[0].age() # Returns 30
# With conversion function
is_adult = dd(data).users[0].age(lambda x: x >= 18) # Returns True
🛡️ Null Safety
# Traditional way - will raise AttributeError 💥
data = {"users": None}
try:
users = data["users"][0].name
except AttributeError:
print("Error accessing attribute")
# With dd - safe navigation ✅
# Once ._ is used, all subsequent operations become null-safe automatically
result = dd(data)._.users[0].name() # Returns None without error
🔄 List/Dict Expansion
# Get all user names
data = {"users": [{"name": "Alice"}, {"name": "Bob"}, {"name": "Charlie"}]}
names = dd(data).users[...].name() # Returns ["Alice", "Bob", "Charlie"]
# Get all values from a dictionary
config = {"server": {"ports": {"http": 80, "https": 443}}}
ports = dd(config).server.ports[...]() # Returns [80, 443]
🔀 Combining Features
# Safely get all user ages from potentially null data
data = {"groups": [{"users": None}, {"users": [{"name": "Alice", "age": 30}]}]}
# No need to repeat ._ as it applies to all subsequent operations
ages = dd(data).groups[...]._.users[...].age() # Returns [[], [30, 15]]
# Filter adult users
adult_names = dd(data).groups[...]._.users[...](
lambda users_groups: [
[user["name"] for user in (users or []) if user.get("age", 0) >= 18]
for users in users_groups
]
) # Returns [[], ["Alice"]]
⚠️ Error Handling
# Accessing a non-existent key with descriptive error
data = {"users": [{"name": "Alice"}]}
try:
dd(data).users[0].email()
except Exception as e:
print(e) # Prints: "Failed to get attribute 'email': 'dict' object has no attribute 'email'
# at path: dd.users[0].email, value: {'name': 'Alice'}"
🧙♂️ Advanced Usage
🧮 Custom Transformations
# Apply transformations to extracted data
data = {"items": [{"price": 10}, {"price": 20}, {"price": 30}]}
total = dd(data).items[...].price(lambda prices: sum(prices)) # Returns 60
# Format all names to uppercase
data = {"users": [{"name": "alice"}, {"name": "bob"}]}
upper_names = dd(data).users[...].name(lambda names: [n.upper() for n in names])
# Returns ["ALICE", "BOB"]
🌐 Working with APIs
import requests
from dd import dd
# Safely navigate through API response with a single ._ for the entire chain
response = requests.get("https://api.example.com/data").json()
first_tag = dd(response)._.data.items[0].tags[0]() # Safely get the first tag, even if any part is None
# Process all items safely
all_prices = dd(response)._.data.items[...].price() # Get all prices, handling nulls
📄 License
MIT
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 datadot-1.0.0.tar.gz.
File metadata
- Download URL: datadot-1.0.0.tar.gz
- Upload date:
- Size: 13.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10d44a4277813d1f8ce7fd49dacf05c61bfc61ea8f50066279bfe2977ff0b208
|
|
| MD5 |
44e2cc49c61222259372adc3c462fc84
|
|
| BLAKE2b-256 |
405db3c7ae20b9095004ec8e5a5ac1c85f2483189950c4554d9e7f136777bb19
|
Provenance
The following attestation bundles were made for datadot-1.0.0.tar.gz:
Publisher:
workflow.yml on zqqqqz2000/datadot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datadot-1.0.0.tar.gz -
Subject digest:
10d44a4277813d1f8ce7fd49dacf05c61bfc61ea8f50066279bfe2977ff0b208 - Sigstore transparency entry: 208477338
- Sigstore integration time:
-
Permalink:
zqqqqz2000/datadot@942da4ef977d15e1569f5a4b48d5486e630b02f5 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/zqqqqz2000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@942da4ef977d15e1569f5a4b48d5486e630b02f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file datadot-1.0.0-py3-none-any.whl.
File metadata
- Download URL: datadot-1.0.0-py3-none-any.whl
- Upload date:
- Size: 5.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65cda58f57d2b9c4172d193f6c9e7952bfea033b0fb0237985133496a08c980f
|
|
| MD5 |
ab65c823ea5c641dd67cfef5162f1fa1
|
|
| BLAKE2b-256 |
7e8707617b02d3a989977ebf6bbcf0bc81b1b4196ac68af53e5db5aa99ae6c4b
|
Provenance
The following attestation bundles were made for datadot-1.0.0-py3-none-any.whl:
Publisher:
workflow.yml on zqqqqz2000/datadot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datadot-1.0.0-py3-none-any.whl -
Subject digest:
65cda58f57d2b9c4172d193f6c9e7952bfea033b0fb0237985133496a08c980f - Sigstore transparency entry: 208477339
- Sigstore integration time:
-
Permalink:
zqqqqz2000/datadot@942da4ef977d15e1569f5a4b48d5486e630b02f5 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/zqqqqz2000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@942da4ef977d15e1569f5a4b48d5486e630b02f5 -
Trigger Event:
release
-
Statement type: