Immutable object modifications with the Result pattern - inspired by C# records
Project description
validate-with-resolute
Immutable object modifications with the Result pattern, inspired by C# records.
Wraps dataclass and Pydantic model construction/modification in resolute so validation errors are returned, never raised.
Installation
pip install validate-with-resolute
Requires Python 3.13+.
Usage
Record base class (recommended)
Inherit from Record to get .from_() and .with_() with full type checking and IDE autocomplete.
from dataclasses import dataclass
from validate_with_resolute import Record
@dataclass
class User(Record):
name: str
age: int
# Safe construction
result = User.from_(name="Bob", age=25)
if result.is_success:
user = result.value
# Safe modification — original unchanged
result = user.with_(name="Alice", age=30)
if result.is_success:
print(result.value.name) # "Alice"
print(user.name) # "Bob"
Works with Pydantic:
from pydantic import BaseModel, field_validator
from validate_with_resolute import Record
class User(BaseModel, Record):
name: str
age: int
@field_validator('age')
@classmethod
def validate_age(cls, v: int) -> int:
if v < 0:
raise ValueError('age must be positive')
return v
result = User.from_(name="Bob", age=-5)
if result.has_errors:
print(result.errors) # validation errors captured, not raised
user = User(name="Bob", age=25)
result = user.with_(age=-5) # same — errors captured
modify() standalone function
No inheritance required:
from dataclasses import dataclass
from validate_with_resolute import modify
@dataclass
class User:
name: str
age: int
user = User(name="Bob", age=25)
result = modify(user, name="Alice", age=30)
if result.is_success:
print(result.value.name) # "Alice"
@with_modify decorator
Adds .with_() to an existing class without inheritance. Type checkers require # type: ignore[attr-defined] on call sites.
from validate_with_resolute import with_modify
@with_modify
@dataclass
class User:
name: str
age: int
result = user.with_(name="Alice") # type: ignore[attr-defined]
Prefer Record or modify() instead.
Result API
All functions return Resolute[T] from the resolute package:
result.is_success # True on success
result.has_errors # True on failure
result.value # Modified object (success only)
result.errors # List of captured errors (failure only)
Supported types
| Type | Strategy |
|---|---|
| Pydantic v2 model | model_validate |
| Dataclass | dataclasses.replace |
| Other (Python 3.13+) | copy.replace() |
| Unsupported | TypeError in result.errors |
Type checking
The package ships a py.typed marker and full generic annotations. result.value is typed as T.
| Approach | mypy | Autocomplete |
|---|---|---|
Record base class |
full | full |
modify() function |
full | full |
@with_modify decorator |
needs ignore | none |
Nested objects
new_address = modify(address, city="LA").value
result = modify(person, address=new_address)
License
MIT
Project details
Release history Release notifications | RSS feed
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 validate_with_resolute-0.9.1.tar.gz.
File metadata
- Download URL: validate_with_resolute-0.9.1.tar.gz
- Upload date:
- Size: 14.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2cdd3973896b6a901ae882be3fb4d745fc56219725e58c444be242b6fd4e0103
|
|
| MD5 |
d040c721ffd2ada4d417bc4906a54e97
|
|
| BLAKE2b-256 |
05e27f3a57af3ed76ed0c281e03ca55f7693b3b43d9242cd025ba9e1c927a346
|
File details
Details for the file validate_with_resolute-0.9.1-py3-none-any.whl.
File metadata
- Download URL: validate_with_resolute-0.9.1-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35e6de30d7d79d26a59b2a6c8a1d5064aa153afd30aea2de951e4ab8c725e4a2
|
|
| MD5 |
79b1799a5fcdc9541f59a1812157f667
|
|
| BLAKE2b-256 |
793faa2078af98e406847e9d6f09d37378be6ea7cfafdcd5f388c88732377d2e
|