Skip to main content

howard

Python datatype marshalling

This library marshalls dictionaries [read json] into instances of defined dataclasses and back.

i.e.

from dataclasses import dataclass

import howard

@dataclass
class Person:
    name: str
    age: int


my_dict = {'name': 'Bob', 'age': 24}
person = howard.from_dict(my_dict, Person)
assert person.name == 'Bob'
assert person.age == 24

The main purpose is to use python dataclasses as a schema definition rather than having to hand-write a schema. Howard does not currently include logic itself for generating json-schema (swagger) object documentation, but that is a long term goal of it.

Howard differs from a standard dataclass because it can recursively marshall and unmarshall. It also supports more types out of the box than dataclasses.asdict does. Some supported types:

  • Enums
  • TypedDict
  • Collections (lists/dictionaries)
  • Datetime
  • all primitives (int/string/boolean/float)

All of the logic for howard is in your dataclass definition, not in howard. Howard just has a to_dict and from_dict method, and it bases all decisions off of your dataclass. There is no inheritance on custom types, everything is standard, built-in python. (3.7+)

Installing

pip install howard

More examples

For more examples, you can go look at the tests at tests/test_howard.py

Here is a basic example of recursive types and how it can work with howard:

from enum import Enum
from dataclasses import dataclass, field
from typing import List

import howard

@dataclass
class Suit(Enum):
    heart = 'h'
    spade = 's'
    diamond = 'd'
    club = 'c'


def validate_rank(i: int) -> int:
    lb, ub = 1, 13
    if lb <= i <= ub:
        return i
    raise ValueError(f'{i} is not between {lb} and {ub}')


@dataclass
class Card:
    rank: int = field(metadata={'howard': {'decoder': validate_rank}})
    suit: Suit


@dataclass
class Hand:
    hand_id: int = 0
    cards: List[Card] = field(default_factory=list)


d = {'hand_id': 2, 'cards': [{'rank': 2, 'suit': 'c'}, {'rank': 10, 'suit': 'h'}]}

# d is a dictionary, now we turn it into the dataclass
obj = howard.from_dict(d, Hand)

assert isinstance(obj, Hand)
assert obj.hand_id == 2
assert len(obj.cards) == 2
assert isinstance(obj.cards[0], Card)
assert obj.cards[0].suit == Suit.club

# and back to a dictionary
json_dict = howard.to_dict(obj)

In the above example, you can see a couple things.

  1. A Hand contains a list of Card.
  2. The sub-object Card also gets unmarshalled correctly.
  3. The Suit object is an enum, which is like a string in json form, but only has 4 possible values.
  4. The Card has a field called rank which has its own custom decoder. In this case, the decoder acts as a validator, but can also be used for custom decode logic.

FAQ

  • Why not just use dataclasses.asdict and MyDataclass(**my_dict)? dataclasses.asdict doesn't work on all types, for example, Enums or datetimes. MyDataclass(**my_dict) will not recursively turn the subobjects into their respective datatype.

  • What about custom types? You can specify custom decoders and encoders in a dataclass field.metadata section. See example above.

Metadata

Release files for howard 1.12.1

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

Source distribution (sdist)

Source distribution for howard 1.12.1
File Size Uploaded Provenance Actions
howard-1.12.1.tar.gz 4.8 kB Without provenance Details for howard-1.12.1.tar.gz

Release files / howard-1.12.1.tar.gz

Download URL howard-1.12.1.tar.gz
Size 4.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b69582b260cd370c6d6799b54ccc8a5a0b8ef85fe98aa6534d3bac54673e0d50
BLAKE2b-256 checksum
How to use checksums
3a979a903689e0742ac44ece26287915aa7379cce455fc27e91bffd7f1802547
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.20.1 setuptools/49.1.0 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.8.3

Security for howard 1.12.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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