Skip to main content

plucker

Build Status codecov Python Version

Validate and extract JSON-sourced data into type-safe dataclasses

wut

  • Tired of relying on vendor-provided, untyped Python libraries to interface with external APIs?
  • Want to just make a few simple HTTP requests without the weight of extra dependencies?
  • Do you only use a small subset of the data you get from external sources, picking out five fields when you are given thirty?
  • Are you more than slightly worried that the API might change under you and you wouldn't know?
  • Want to avoid just reaching into dictionaries to get the data you want?
  • Do you want to parse the JSON you get into something type-safe so that mypy will complain when you do wrong things?
  • Is writing fakes a bit too heavyweight for the APIs you're calling? Would producing an error on unexpected input work OK for now?

Enter plucker.

plucker is designed to validate, map and reduce regularly structured data into dataclasses. That data would typically be JSON from APIs but could be anything that mostly consists of Python dicts and lists when parsed.

plucker will either give you type-verified data, or it will fail with helpful error messages:

Data not in expected format; expected fred to be 'list' but it was 'dict':
.fred[].v
 ^^^^

Just pick the data you want using jq-style paths, map it so that it's the right type if you need to, and you have well-typed validated data to feed into the rest of your system.

Installation (soon...)

pip install plucker

Example

from typing import List
from dataclasses import dataclass
from enum import Enum, auto
from datetime import date

from plucker import pluck, Path


class Status(Enum):
    """A cintact's status."""
    CURRENT = auto()
    EXPIRED = auto()


@dataclass
class Contact:
    """A contact record."""
    name: str
    email: str


@dataclass
class Struct:
    """The typed dataclass we want our data collected into."""
    date: date
    id: int
    state: Status
    affected_records: List[int]
    contacts: List[Contact]


TO_STATUS = {"CUR": Status.CURRENT, "EXP": Status.EXPIRED}

input_ = {
    "date": "2021-01-01",
    "id": "1242",
    "payload": {
        "from": "CURRENT",
        "who": [
            {"name": "DM", "id": 1, "email": "dangermouse@example.com"},
            {"name": "Stiletto", "id": 23, "email": "baroni@example.com"},
        ]
    }
}

plucked = pluck(
    input_,
    Struct,
    date=Path(".date"),
    id=Path(".id").map(int),
    state=Path(".payload.from").map(TO_STATUS),
    affected_records=Path(".payload.who[].id"),
    people=Path(".payload.who[]").into(
        Contact,
        name=Path(".name"),
        email=Path(".email"),
    ),
)

expected = Struct(
    date=date(2021, 1, 1),
    id=1242,
    state=Status.CURRENT,
    affected_records=[1, 23],
    contacts=[
        Contact("DM", "dangermouse@example.com"),
        Contact("Stiletto", "baroni@example.com")
    ]
)

assert plucked == expected
# ^ it's True

Prior art

  1. dataclasses_json -> require the same structure between JSON and serialization, which means you have to specify an intermediate structure
  2. DRF serializers -> heavyweight and not type safe, destructure into dictionaries
  3. Elm's JSON decoders -> this design isn't really based on anything in there but ever since using them I wanted similar functionality in Python
  4. jq, an amazing commandline tool for querying JSON data
  5. Parse, don't validate
  6. Elm's error messages

License

MIT

Credits

A bunch of the tooling was taken from wemake-python-package but then heavily modified.

Metadata

Release files for plucker 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for plucker 0.1.0
File Size Uploaded
plucker-0.1.0.tar.gz 10.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for plucker 0.1.0
File Interpreter ABI Platform
plucker-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 19.6 kB

Release files / plucker-0.1.0.tar.gz

Download URL plucker-0.1.0.tar.gz
Size 10.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5064cf08a333bf637706117516101f50819f410aa64d50856811446744330071
BLAKE2b-256 checksum
How to use checksums
3b4c06a00dff95acd59fcbb57350423984ccf969c48935aaf0f376bf0e178c92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.5 CPython/3.9.0 Darwin/18.7.0

Release files / plucker-0.1.0-py3-none-any.whl

Download URL plucker-0.1.0-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3272ac2e6601df8519c73261b8bb05eb11c9bc29e6f17c840743e1c3b74daf70
BLAKE2b-256 checksum
How to use checksums
c2c1f9c3085c7b5d12db0c66a8c3cff298178d1defa6349519c9d18e42fba8de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.5 CPython/3.9.0 Darwin/18.7.0

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page