In Python development, we often default to using basic data structures like dict and list to move data around. They are flexible, JSON-compatible, and require no special setup. With the recent advancements in TypedDict and Annotated, the Python type system has become powerful enough to describe these structures with high precision.
baredtype is a library built to bridge the gap between these native structures and formal validation. It allows you to enforce strict rules on your data without ever forcing that data to change its shape or type.
The Strength of Basic Data Structures
The main draw of baredtype is that it works directly with the data structures you already use. There is no custom class instantiation or "wrapping" of data into library-specific objects.
Serialization and Deserialization
Because your data remains a standard list or dict, you don't need special methods to get your data in or out of a system. You use the standard tools you already know:
-
To JSON:
json.dumps(my_data) -
From JSON:
json.loads(input_string) -
Validation:
validate(MySchema, my_data)
Handling Keys and None Values
Working with native structures means using standard Python idioms. baredtype respects TypedDict definitions for required fields and Annotated for value constraints, allowing you to handle None values and missing keys naturally.
from typing_extensions import TypedDict, NotRequired, Annotated
from baredtype import validate
class UserData(TypedDict):
username: str
email: Annotated[str | None, {"pattern": r"^[\w.-]+@[\w.-]+\.\w+$"}]
age: NotRequired[int]
# Use standard Python to check your data:
data = {"username": "tech_lead", "email": None}
if data.get("email") is None:
print("No email provided.")
if "age" not in data:
print("Age is an optional key.")
# Validation checks the types and the constraints
is_valid = validate(UserData, data)
Mapping to JSON Schema and OpenAPI
A core objective of baredtype is making it easy to map Python types to external standards like JSON Schema and OpenAPI. It handles the "quantifiers" that define how different types can be combined.
Quantifier Logic
-
oneOf: By usingAnnotatedmetadata, you can specify that data must match exactly one type in a Union. This is crucial for precise API definitions where ambiguity can lead to bugs. -
allOf: This is naturally supported throughTypedDictinheritance. When oneTypedDictinherits from others,baredtypegenerates a schema representing the union of those requirements, staying consistent with OpenAPI standards.
Two Ways to Verify the Spec
When we define our data structures, we are writing a specification for our code. There are two primary ways to ensure our code follows this spec, both of which are supported by baredtype.
1. Static Type Checking
Because the library is built on TypedDict, you get the full benefit of tools like Mypy or Pyright. Your IDE can catch missing keys or type mismatches while you are writing the code. This finds errors before the code ever runs.
2. Property-Based Checking
While static types prove what should happen, property-based checking proves what can happen under stress. baredtype integrates with Hypothesis to automatically generate data that fits your TypedDict definitions, including constraints like min_length or regex patterns.
from baredtype import given_from_annotations
@given_from_annotations
def test_process_payload(payload: UserData):
# Hypothesis generates a wide variety of valid UserData dicts
# to find edge cases in your logic.
result = my_function(payload)
assert result is not None
Validation: The Constant Requirement
Regardless of whether you use static checking, property-based checking, or both, runtime validation is a must. External data is inherently untrusted. Static checking verifies your internal logic, and property-based testing verifies your code's resilience during development. At the moment data enters your system, baredtype provides the final, essential check to ensure the data actually matches your specification.
Explore the Project
baredtype offers a lightweight validation layer that stays out of your data's way, leveraging the emerging strengths of the Python type system.
Check out the project on Codeberg:
👉 https://codeberg.org/veer66/baredtype
Top comments (0)