Generic-based typing for default objects #136
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is part of making validataclass mypy-compatible (#116).
Please note that the target branch is
dev-mypyinstead of main.This PR refactors how validataclass default objects (
Default,DefaultFactory,DefaultUnset,NoDefault) work to make them more typing-compatible.New base class, generic Default and DefaultFactory
I've introduced an abstract base class
BaseDefault[T]which all other default classes inherit from. Previously,Defaultwas the base class, which had several drawbacks.The classes
DefaultandDefaultFactoryboth inherit the type parameter T fromBaseDefault. The type parameter specifies the type of the default values that these objects provide.The attributes
Default.valueandDefaultFactory.factoryhave been changed to be protected attributes instead (_valueand_factory), because they shouldn't be accessed from the outside and definitely should not be changed. This can be considered a minor breaking change, because in practice it's unlikely that user code accessed these attributes.Another breaking change is that using
Default()without arguments is not allowed anymore. Previously, this was equivalent toDefault(None). This was never documented and mostly existed for internal purposes. I don't know of any user code that usedDefault()without arguments, but it should be mentioned in the release notes.DefaultUnset
The value
DefaultUnsetused to be a singleton instance of an unnamed/deleted subclass ofDefault(which customized the__repr__and provided a__call__method). This class has been removed andDefaultUnsetis now a regularDefaultobject, i.e. it was defined asDefaultUnset = Default(UnsetValue).This has the side effect that
repr(DefaultUnset)is now"Default(UnsetValue)"rather than"DefaultUnset". Code shouldn't really rely on how the repr looks though, so I'd consider this a practically irrelevant minor breaking change.For compatibility, it's still possible to use
DefaultUnset()with parentheses. However, this usage has been deprecated with this MR. Please useDefaultUnsetwithout parentheses instead.NoDefault
Usage of
NoDefault()with parentheses has been deprecated likeDefaultUnset(), but contrary to DefaultUnset, I'm not aware of any code that is affected by this change.Misc changes
Several exception texts have been slightly modified.