Skip to main content

A Python library for powerful dictionary and list manipulation with support for nested structures, wildcards, and complex path expressions

Project description

Magiccionary

A Python library for powerful dictionary and list manipulation with support for nested structures, wildcards, and complex path expressions.

Features

  • Remove keys from nested dictionaries and lists using dot notation or path arrays
  • Keep specific keys while removing everything else
  • Wildcard support (*) for operating on all dictionary keys
  • List traversal ([]) for operating on all list items
  • Nested updates for merging dictionary structures
  • Empty key removal for cleaning up data structures

Installation

pip install magiccionary

Or using uv:

uv add magiccionary

Quick Start

from magiccionary import remove_keys, keep_keys

# Sample data
data = {
    "user": {
        "profile": {
            "name": "John",
            "email": "john@example.com",
            "settings": {
                "theme": "dark",
                "notifications": True
            }
        },
        "posts": [
            {"title": "Post 1", "content": "Hello", "draft": True},
            {"title": "Post 2", "content": "World", "draft": False}
        ]
    }
}

# Remove specific keys
cleaned = remove_keys(data, [
    "user.profile.email",
    ["user", "posts", "[]", "draft"]
])

# Keep only specific keys
filtered = keep_keys(data, [
    "user.profile.name",
    ["user", "posts", "[]", "title"]
])

API Reference

remove_keys(data, keys_to_remove, separator=".")

Removes specified keys from a nested dictionary/list structure.

Parameters:

  • data (dict/list): The data structure to filter
  • keys_to_remove (list): List of keys to remove (strings or path arrays)
  • separator (str): Separator for dot notation (default: ".")

Returns:

  • A new data structure with specified keys removed

Examples:

# Simple key removal
data = {"a": 1, "b": 2, "c": 3}
result = remove_keys(data, ["b", "c"])
# Result: {"a": 1}
# Original data unchanged: {"a": 1, "b": 2, "c": 3}

# Nested key removal
data = {"user": {"profile": {"name": "John", "email": "john@example.com"}}}
result = remove_keys(data, ["user.profile.email"])
# Result: {"user": {"profile": {"name": "John"}}}
# Original data unchanged

# Remove from all list items
data = {
    "posts": [
        {"title": "Post 1", "draft": True, "content": "Hello"},
        {"title": "Post 2", "draft": False, "content": "World"}
    ]
}
result = remove_keys(data, [["posts", "[]", "draft"]])
# Result: {"posts": [{"title": "Post 1", "content": "Hello"}, {"title": "Post 2", "content": "World"}]}
# Original data unchanged

# Wildcard removal (remove from all dictionary keys)
data = {
    "user1": {"name": "John", "email": "john@example.com"},
    "user2": {"name": "Jane", "email": "jane@example.com"}
}
result = remove_keys(data, [["*", "email"]])
# Result: {"user1": {"name": "John"}, "user2": {"name": "Jane"}}
# Original data unchanged

keep_keys(data, keys_to_keep, separator=".")

Keeps only specified keys from a nested dictionary/list structure.

Parameters:

  • data (dict/list): The data structure to filter
  • keys_to_keep (list): List of keys to keep (strings or path arrays)
  • separator (str): Separator for dot notation (default: ".")

Returns:

  • New data structure with only specified keys

Examples:

# Keep specific keys
data = {"a": 1, "b": 2, "c": 3}
result = keep_keys(data, ["a", "b"])
# Result: {"a": 1, "b": 2}

# Keep nested keys
data = {"user": {"profile": {"name": "John", "email": "john@example.com"}}}
result = keep_keys(data, ["user.profile.name"])
# Result: {"user": {"profile": {"name": "John"}}}

# Keep from all list items
data = {
    "posts": [
        {"title": "Post 1", "draft": True, "content": "Hello"},
        {"title": "Post 2", "draft": False, "content": "World"}
    ]
}
result = keep_keys(data, [["posts", "[]", "title"]])
# Result: {"posts": [{"title": "Post 1"}, {"title": "Post 2"}]}

# Wildcard keeping
data = {
    "user1": {"name": "John", "email": "john@example.com", "age": 30},
    "user2": {"name": "Jane", "email": "jane@example.com", "age": 25}
}
result = keep_keys(data, [["*", "name"]])
# Result: {"user1": {"name": "John"}, "user2": {"name": "Jane"}}

remove_empty_keys(data)

Removes keys with empty values (None, empty dicts, empty strings) from a nested structure.

Parameters:

  • data (dict): The dictionary to clean

Returns:

  • A new dictionary with empty keys removed

Examples:

data = {
    "name": "John",
    "email": None,
    "settings": {},
    "posts": [
        {"title": "Post 1", "content": ""},
        {"title": "Post 2", "content": "Hello"}
    ]
}
result = remove_empty_keys(data)
# Result: {
#     "name": "John",
#     "posts": [
#         {"title": "Post 1"},
#         {"title": "Post 2", "content": "Hello"}
#     ]
# }
# Original data unchanged

nested_update(original, update)

Updates a nested dictionary with another dictionary, merging nested structures.

Parameters:

  • original (dict): The original dictionary to update
  • update (dict): The dictionary with updates to apply

Returns:

  • A new dictionary with the merged data

Examples:

original = {"user": {"name": "John", "settings": {"theme": "light"}}}
update = {"user": {"email": "john@example.com", "settings": {"notifications": True}}}
result = nested_update(original, update)
# Result: {
#     "user": {
#         "name": "John",
#         "email": "john@example.com",
#         "settings": {"theme": "light", "notifications": True}
#     }
# }
# Original data unchanged

Path Syntax

Magiccionary supports two path formats:

1. Dot Notation (String)

Use dots to separate nested keys:

"user.profile.name"  # Access user -> profile -> name

2. Path Arrays (List)

Use arrays for more complex operations:

["user", "posts", "[]", "title"]  # Access user -> posts -> all items -> title

Special Tokens

  • "*" - Wildcard for all dictionary keys
  • "[]" - Wildcard for all list items

Complex Examples

# Remove 'draft' field from all posts in all users
data = {
    "users": [
        {
            "name": "John",
            "posts": [{"title": "Post 1", "draft": True}, {"title": "Post 2", "draft": False}]
        },
        {
            "name": "Jane", 
            "posts": [{"title": "Post 3", "draft": True}]
        }
    ]
}

# Remove draft field from all posts in all users
result = remove_keys(data, [["users", "[]", "posts", "[]", "draft"]])

# Keep only names and post titles
result = keep_keys(data, [
    ["users", "[]", "name"],
    ["users", "[]", "posts", "[]", "title"]
])

Advanced Usage

Working with API Responses

# Clean API response by removing unnecessary fields
api_response = {
    "data": {
        "users": [
            {
                "id": 1,
                "name": "John",
                "email": "john@example.com",
                "created_at": "2023-01-01",
                "updated_at": "2023-01-02",
                "internal_notes": "Some notes"
            }
        ]
    },
    "meta": {
        "pagination": {"page": 1, "total": 100},
        "debug_info": {"request_id": "abc123"}
    }
}

# Remove internal fields and keep only essential data
cleaned = remove_keys(api_response, [
    ["data", "users", "[]", "internal_notes"],
    ["data", "users", "[]", "created_at"],
    ["data", "users", "[]", "updated_at"],
    ["meta", "debug_info"]
])

# Or keep only specific fields
filtered = keep_keys(api_response, [
    ["data", "users", "[]", "name"],
    ["data", "users", "[]", "email"]
])

Data Transformation

# Transform complex nested data
complex_data = {
    "departments": {
        "engineering": {
            "employees": [
                {"name": "Alice", "role": "developer", "salary": 80000, "manager": "Bob"},
                {"name": "Charlie", "role": "designer", "salary": 75000, "manager": "Bob"}
            ]
        },
        "marketing": {
            "employees": [
                {"name": "Diana", "role": "manager", "salary": 90000, "manager": None}
            ]
        }
    }
}

# Create a flat list of employees with only name and role
employees = keep_keys(complex_data, [
    ["departments", "*", "employees", "[]", "name"],
    ["departments", "*", "employees", "[]", "role"]
])

# Remove salary information from all employees
result = remove_keys(complex_data, [
    ["departments", "*", "employees", "[]", "salary"]
])

Development

Setup

  1. Clone the repository

  2. Install dependencies:

    uv sync
    

Running Tests

uv run pytest

Code Quality

uv run ruff check .
uv run ruff format .

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

License

This project is licensed under the MIT License - see the license file for details.

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

magiccionary-1.1.0.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

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

magiccionary-1.1.0-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

Details for the file magiccionary-1.1.0.tar.gz.

File metadata

  • Download URL: magiccionary-1.1.0.tar.gz
  • Upload date:
  • Size: 8.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for magiccionary-1.1.0.tar.gz
Algorithm Hash digest
SHA256 d107bd99bddcbd6647b4f2acdba7f2e1407ae6d6f862b70c095dd4c4e8fe063c
MD5 d2ac55439340d031fb1d26b7a44e4446
BLAKE2b-256 4ea2ead780d0bbacca167e0bb2346ecf8c827bcc7758bfbbecb3151a681cd070

See more details on using hashes here.

File details

Details for the file magiccionary-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: magiccionary-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for magiccionary-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8eb17ff3362a4debf2fa783307b7b3202a9fddc242bc9d128be6202011f6f01f
MD5 dfd2982f966fada5fe7ba2bb46efcbeb
BLAKE2b-256 ee54788b0f1421ba68448929a312553aadc878ce88ca11c4e42b554ea0e42858

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