Skip to content

Releases: binary-butterfly/validataclass

0.11.0

12 Aug 12:15
eb5f934

Choose a tag to compare

Full changelog

This release makes the library PEP 561 compatible by adding a py.typed file. It also fixes some mypy issues that were previously ignored.

While there is still some work necessary to make the library fully compatible with mypy (see #116), this release enables mypy to detect the type annotations in the library without the need for stub files.

Important note / breaking changes

This update was originally released as patch version 0.10.1, but was then yanked and later re-released as a new minor version instead.

The update does not introduce any breaking changes in the code. However, it may result in mypy errors in your project which have previously not been discovered by mypy, thus leading to failing CI pipelines. Keep this in mind when updating the library.

Some of the issues found by mypy currently need to be ignored using # type: ignore comments, until the library is fully compatible with mypy (#116). Examples:

  • Return type "X" of "validate" incompatible with return type "Y" in supertype "SomeBaseValidator" [override]:
    This can happen when you subclass a validator and change the return type of the validate method, which technically violates the Liskov substitution principle. However, in the case of validators, that's intentional.
  • Item "UnsetValueType" of "X | UnsetValueType" has no attribute "Y":
    This can happen despite of conditions like if some_field is not UnsetValue:, because mypy doesn't know that UnsetValue is a sentinel object, thus not being able to narrow down the type. A possible workaround that doesn't require # type: ignore would be to define a Type Guard](https://mypy.readthedocs.io/en/stable/type_narrowing.html#user-defined-type-guards) and use that instead of the bare condition.

We will hopefully find better solutions for these problems in the future.

Added

  • Add py.typed file to make the package PEP 561 compatible. #125

Fixed

  • Explicitly re-export imports in __init__.py by defining __all__ to fix mypy issues. #125

0.10.0

07 May 12:49
1459630

Choose a tag to compare

Full changelog

This release features custom pre-validation in dataclasses using the __pre_validate__() method and a change to the accepted format of datetimes in the DateTimeValidator to accept arbitrary decimal places after seconds.

This also is a "spring cleaning" release that contains a lot of miscellaneous refactorings and code cleanup, as well as some preparation for full mypy support (#116).

It also drops support for Python 3.7 and adds support for Python 3.12.

Added

  • Official support for Python 3.12. #112
  • Custom pre-validation in dataclasses using the __pre_validate__ class method. #115

Changed

  • DateTimeValidator: Accept datetimes with arbitrary precision (by @flauschzelle). #111, #113
    • This is not a breaking change, unless you specifically want to restrict datetime input strings to exactly 0, 3 or 6 decimal places after the seconds. It does not really matter for the result.
  • Move ValidationError base class to separate module validataclass.exceptions.base_exceptions. #117
    • This should not break any code as long as you import ValidationError from the validataclass.exceptions package instead of the validataclass.exceptions.common_exceptions module. If you do import it from the module, it should still work because the class is imported there as well, but you might get linter warnings.
  • DataclassValidator: Simplify check and error handling for when the specified dataclass is not a dataclass. #120

Removed

  • Breaking change: Drop support for Python 3.7. #118
  • Remove python-dateutil from install requirements. #122
    • This library was previously a dependency of validataclass. However, it was only needed in the unit tests, so it has been moved to the testing extra requirements.

Fixed

  • Fix style of type comparisons in some unit tests (by @flauschzelle). #110
  • Fix various typing issues reported by mypy, add missing type annotations and other related changes. #120, #121

Testing / CI

  • Add mypy to development environment and CI pipeline. #120

Miscellaneous

  • DateTimeValidator: Unify class docstring with Markdown documentation. #113
  • Miscellaneous code reformatting, more consistent docstrings, unit test refactoring. #119

New contributors

0.9.0

24 May 10:22
2ce4dbc

Choose a tag to compare

Full changelog

This release adds official support for Python for Workgroups 3.11, as well as some minor changes.

Added

  • EmailValidator: Add parameter to_lowercase. #106

Changed

  • Allow defining __post_validate__() with specific context arguments without **kwargs. #105

Fixed

  • Fix Python 3.11 incompatibilities due to UnsetValue not being hashable. #102
  • Also fix missing __hash__ methods in the Default classes (for completeness). #102

Testing / CI

  • Update GitHub actions to fix deprecation warnings. #103
  • Update local test environment for tox 4. #104

0.8.1

30 Nov 12:03
aacb57c

Choose a tag to compare

Full changelog

Fixed

  • AnyOfValidator and EnumValidator: Fixed wrong default value. Now the validators are really case-insensitive by default.

0.8.0

30 Nov 10:49
b2a604f

Choose a tag to compare

Full changelog

This release adds two new validators and a handful of new parameters to existing validators.

It also introduces two breaking changes, which in practice shouldn't really affect anyone negatively, and one deprecation of an existing validator parameter. See the changes below.

Added

  • AllowEmptyString: New wrapper validator that accepts empty strings (by @TomasHalgas). #91
  • DiscardValidator: New validator that discards any input and always returns a predefined value. #94
  • EmailValidator and RegexValidator: Add parameter allow_empty to allow empty strings (by @TomasHalgas). #89
  • EmailValidator: Add parameter max_length. #97
  • DecimalValidator: Add parameter rounding to specify rounding mode (with a new default, see "Changed"). #99

Changed

  • Breaking change: AnyOfValidator and EnumValidator are now case-sensitive by default. #98
    • The parameter case_insensitive is replaced with a new parameter case_sensitive which defaults to True.
    • The old parameter is still supported for compatibility, but is now deprecated and will be removed in a future version.
    • If you have set case_insensitive=True before, you can simply remove this parameter now as this is the default now.
  • Breaking change: DecimalValidator (and all subclasses) now uses decimal.ROUND_HALF_UP as default rounding mode. #99
    • Until now, the rounding mode of the current decimal context was used, which defaults to decimal.ROUND_HALF_EVEN.
    • Use the rounding parameter to change this. To restore the old behavior and use the decimal context, set rounding=None.

Deprecated

  • AnyOfValidator and EnumValidator: The parameter case_insensitive is now deprecated and will be removed in a future version. (See "Changed" above.) #98

Testing

  • Fix version incompatibility in test suite. #95
  • AnyOfValidator: Add unit tests with an empty list for allowed values. #96

New contributors

0.7.2

26 Sep 14:54
9027a63

Choose a tag to compare

Full changelog

This patch fix a bug with the type hinting for @validataclass and DataclassValidator introduced in 0.7.1.

Fixed

  • Fixed typehints of @validataclass decorator. Auto-deduction in DataclassValidator should work now. #85

0.7.1

26 Sep 12:50
1fe9d71

Choose a tag to compare

Full changelog

This small patch release improves type hinting for the @validataclass decorator and the DataclassValidation.

Changed

  • DataclassValidator: The exact type of the validator (e.g. DataclassValidator[MyDataclass]) and thus the return type of validate() is now auto-deduced from the constructor arguments without an explicit type annotation. #84
  • The @validataclass decorator has (hopefully correct) type annotations now. #84

0.7.0 - Context-sensitive validation

22 Sep 13:57
45782ff

Choose a tag to compare

Full changelog

This release mainly introduces context-sensitive (post-)validation. There are some more additions planned for this feature (e.g. dependencies between dataclass fields), but for now we have a solid base.

It also features a handful of smaller additions and changes, see below.

There is a potential breaking change (which probably won't affect anybody), and a sort of deprecation that will affect most custom validators in the future, so make sure to upgrade your validators as explained below.

Added

  • Basic support for context-sensitive validation. #77
    • All built-in validators now support arbitrary keyword arguments (so called context arguments) in the validate() method. These can be used to change the behavior of a validator at validation time based on some kind of application context. Most validators don't do anything with them except passing them down to child validators (e.g. to the item validators in a ListValidator, etc.), but you can implement custom validators that use them.
    • To keep compatibility with custom validators that do not accept context arguments yet, a provisional helper method validate_with_context() was added to the base Validator class. This method simply calls the validate() method, but checks whether it supports context arguments. If yes, context arguments are passed to validate(), else validate() is called without any extra arguments. This method will become obsolete and eventually removed in the future, and should only be used in cases where it is unsure whether a validator supports context arguments.
  • Context-sensitive post-validation in dataclasses. #77
    • The DataclassValidator will now call the method __post_validate__() on your dataclass instances if you have defined this method. Additionally, if the method accepts arbitrary keyword arguments (i.e. **kwargs, although the name of this parameter doesn't matter), all context arguments will be passed to it.
    • You can use this to implement context-sensitive post-validation. For example, if you implement a PATCH endpoint in a REST API, you could have fields that are sometimes optional and sometimes required, depending on a property of the object the user wants to update. You can now fetch the object before calling validate(), then pass the object (or just the property) as a context argument to validate(), and then access it in __post_validate__() to implement a context-sensitive field requirement check.
    • The __post_init__() method of regular dataclasses can still be used for post-validation as before. It cannot be used context-sensitively, though, because we cannot pass arbitrary keyword arguments to it.
  • DateTimeValidator: Add parameter discard_milliseconds to discard the milli- and microseconds of datetimes. #79
  • AnyOfValidator and EnumValidator: Add parameter case_insensitive for case-insensitive string matching. #81
  • New helper function unset_to_none() (returns None if value is UnsetValue). #76

Changed

  • All built-in validators now support context arguments in the validate() method. See above. #77
  • The validate() method of the DataclassValidator was restructured a bit for easier extendability. (This may be subject of additional changes in the future, though.) #77
  • The @validataclass decorator is now marked as a "data class transform" using the @dataclass_transform decorator as specified in PEP 681. #78
    • Since this decorator was only introduced in Python 3.11, we use the typing-extensions library which backports new typing features like this.
  • ListValidator and EnumValidator are now defined as generic classes for better type hinting. #80
  • AnyOfValidator and EnumValidator now accept allowed_values and allowed_types as any iterable. #80
  • AnyOfValidator and EnumValidator: The ValueNotAllowedError now lists all allowed values (unless they are more than 20). #81

Deprecated

  • Validator classes that do not accept context arguments are now deprecated. #77
    • When defining a Validator subclass, the __init_subclass__() method will check whether your validate() method accepts arbitrary keyword arguments. If not, a DeprecationWarning will be issued.
    • Existing custom validators will keep working for now, but this compatibility will be removed in version 1.0.
    • To update your custom validators, simply add **kwargs to the parameter list of validate(). If your validator class is based on an existing validator, make sure to pass the context arguments down to the validate() of your base class as well, i.e. super().validate(input_data, **kwargs).

Removed

  • Breaking change: The post_validate() method of the DataclassValidator was removed. #77
    • (This should not to be confused with the new __post_validate__(), however, which is a method of dataclasses, not of the validator itself.)
    • This method was removed because a) post-validation using either __post_init__() or the new __post_validate__() method in the dataclass should be preferred, b) the validator was restructured in a way that makes this method redundant, and c) it was probably never used anyway.
    • If you do need post-validation as part of a subclassed DataclassValidator, you can extend either validate() or the new _post_validate() private method (but make sure to extend, not override it, since it also handles the call of the dataclass's __post_validate__() method).

0.6.2 - Fix bug with multiple inheritance

11 Jul 09:12
a5adfb3

Choose a tag to compare

Full changelog

This release fixes a bug with multiple inheritance in validataclasses.

Fixed

  • Fix overriding of existing field properties in validataclasses with multiple inheritance. #71

0.6.1 - Important bugfix

16 Jun 15:42
d4a03fc

Choose a tag to compare

Full changelog

This release fixes a critical bug introduced in 0.6.0.

Added

  • Default objects now support equality comparison (implemented __eq__). #69

Fixed

  • Fix Default objects with mutable values (e.g. lists). #69