Skip to content

Run field validation only after conversion #23

@pomponchik

Description

@pomponchik

Problem

Field currently validates assigned values before and after conversion. This is the behavior documented by the current "Converting values" README section, but it is not the behavior we want long-term.

The desired pipeline is:

type check -> conversion -> type check converted value -> validation -> conflicts -> action -> store

In other words, user-defined validation should validate the final converted value only. It should not have to accept both raw input and converted values.

Current behavior

Minimal example:

from skelet import Field, Storage


class Config(Storage):
    value: int = Field(
        1,
        conversion=abs,
        validation=lambda value: value >= 0,
    )


config = Config()
config.value = -5

Today this raises before conversion=abs can fix the value:

ValueError: The value -5 (int) of the "value" field does not match the validation.

That happens because the current pipeline is:

type check raw value -> validation raw value -> conversion -> type check converted value -> validation converted value

So -5 is rejected by validation before abs(-5) can produce 5.

Expected future behavior

The same example should pass:

config.value = -5
assert config.value == 5

Validation should see only the converted value 5.

Notes

This is a breaking semantic change. Existing tests currently lock in the old behavior for assignments, init kwargs, literal defaults, default factories, and sources. Secret fields use the same prepare_value() pipeline, so this change should be made consistently for both regular and secret fields unless we explicitly decide to split their semantics.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions