Add your description here
Project description
static-refl
A Python library for static type reflection with full type safety.
Overview
static-refl provides compile-time type introspection and runtime serialization capabilities for Python 3.12.5+. It analyzes type annotations to generate efficient serializers and deserializers without requiring manual schema definitions.
Features
- Type Reflection: Extract structured type information from Python type hints
- JSON Serialization: Type-safe conversion between Python objects and JSON-compatible dictionaries
- Generic Type Support: Full support for generic dataclasses and TypedDicts with type parameters
- Field Renaming: Automatic case conversion (camelCase, kebab-case, snake_case, etc.)
- Complex Types: Support for datetime, UUID, bytes, complex numbers, and nested structures
- Union Types: Handle discriminated unions and optional fields
- Zero Runtime Overhead: Reflection happens at the type level with cached results
Installation
pip install static-refl
Quick Start
from dataclasses import dataclass
import static_refl as sr
@dataclass
class User:
id: int
name: str
email: str | None = None
# Serialize to dict
user = User(id=1, name="Alice", email="alice@example.com")
# to avoid reflection overhead, cache the schema first with:
# user_schema = sr.json.Schema[User]
# user_schema.to_untyped(user)
data = sr.json.Schema[User].to_untyped(user)
# {'id': 1, 'name': 'Alice', 'email': 'alice@example.com'}
# Deserialize from dict
user_copy = sr.json.Schema[User].to_typed(data)
assert user == user_copy
Advanced Usage
Field Renaming
Use @refl_options to automatically convert field names:
from dataclasses import dataclass
import static_refl as sr
@sr.refl_options(rename_all="kebab-case")
@dataclass
class Config:
api_key: str
max_retries: int
config = Config(api_key="secret", max_retries=3)
data = sr.json.Schema[Config].to_untyped(config)
# {'api-key': 'secret', 'max-retries': 3}
Supported case conversions:
kebab-casesnake_casecamelCaselowercaseUPPERCASE
Custom Field Names
Use @refl_rename for specific field mappings:
@sr.refl_rename(user_id="userId", created_at="createdAt")
@dataclass
class Document:
user_id: int
created_at: str
Generic Types
Full support for generic dataclasses:
from dataclasses import dataclass
from typing import Generic, TypeVar
import static_refl as sr
T = TypeVar('T')
@dataclass
class Container[T]:
value: T
items: list[T]
# Works with concrete type parameters
int_container = Container(value=42, items=[1, 2, 3])
data = sr.json.Schema[Container[int]].to_untyped(int_container)
result = sr.json.Schema[Container[int]].to_typed(data)
Complex Nested Structures
from dataclasses import dataclass
import datetime
import static_refl as sr
@dataclass
class Address:
street: str
city: str
@dataclass
class Person:
name: str
born: datetime.date
addresses: dict[str, Address]
person = Person(
name="Bob",
born=datetime.date(1990, 1, 1),
addresses={
"home": Address(street="123 Main St", city="Springfield"),
"work": Address(street="456 Office Rd", city="Shelbyville")
}
)
data = sr.json.Schema[Person].to_untyped(person)
person_copy = sr.json.Schema[Person].to_typed(data)
JSON Serialization Options
Customize serialization behavior with JsonSerdeOptions:
from static_refl.json import JsonSerdeOptions, UUIDEncoding
import uuid
options = JsonSerdeOptions(
keep_bytes=True, # Don't base64-encode bytes
keep_complex=True, # Keep complex numbers as-is
uuid_encoding=UUIDEncoding.hex # Encode UUIDs as hex strings
)
data = sr.json.Schema[MyClass].to_untyped(obj, options=options)
UUID encoding options:
UUIDEncoding.hex- Encode as hex string (default)UUIDEncoding.bytes- Encode as bytesUUIDEncoding.object- Keep as UUID object
Supported Types
Primitive Types
int,float,str,boolbytes,complexdatetime.datetime,datetime.dateuuid.UUID
Collection Types
list[T],tuple[T, ...],set[T]dict[K, V]- Fixed-length tuples:
tuple[int, str, bool] - Variadic tuples:
tuple[int, str, ...]
Structured Types
dataclass(with@dataclassdecorator)TypedDict(with required/optional fields)
Special Types
T | None(Optional types)Union[A, B, C](Discriminated unions)Literal[1, 2, 3](Literal types)Any(Untyped values)- Generic type parameters
API Reference
Core Functions
refl(tp: type) -> TypeId
Reflect on a type and return its type descriptor.
from static_refl import refl
type_id = refl(list[int])
print(type_id) # array[!int]
Decorators
@refl_options(rename_all=None)
Configure serialization options for a class.
@refl_rename(**kwargs)
Map specific field names to serialization keys.
JSON Schema
Schema[T].to_untyped(obj: T, options=None) -> dict | list
Serialize a typed object to JSON-compatible structure.
Schema[T].to_typed(data: dict | list, options=None) -> T
Deserialize JSON-compatible structure to typed object.
Type Reflection
The core refl() function returns a TypeId object representing the structure:
from static_refl import refl
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
type_id = refl(Point)
print(type_id) # Point
print(type_id.structure.fields)
# (FieldDef(name='x', serde_name='x', type=!float, nullable=False),
# FieldDef(name='y', serde_name='y', type=!float, nullable=False))
Requirements
- Python >= 3.12.5
- casefy >= 1.1.0
Development
Running Tests
pytest
License
See 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
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 static_refl-0.3.0.tar.gz.
File metadata
- Download URL: static_refl-0.3.0.tar.gz
- Upload date:
- Size: 22.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
776e4d0acfff98e6c9592ff51cc146d23f4b4dd46a1e9707aa311620d06487ac
|
|
| MD5 |
6c43228387bb786446aa3b4cf330e505
|
|
| BLAKE2b-256 |
ad3676a7bb7c8a51d3057bf1e26b7b3c69524f8ec46d9ae7160dd96035ff9794
|
File details
Details for the file static_refl-0.3.0-py3-none-any.whl.
File metadata
- Download URL: static_refl-0.3.0-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cb11a64e48c6574ad00a302df4d97f983a4114e71268c7072392e499e6f76f8
|
|
| MD5 |
1c79bc2de4df7f77837beed84a5dbc65
|
|
| BLAKE2b-256 |
f2953596875c7cafc669984e2163a639695f045a6eaf0a55635e09bc9c1f959e
|