Skip to content

Deserialize field by alias instead of name

As per #76 (closed), Typed Settings should deserialize by field alias:

However, I believe the correct behaviour should be deserialising by field alias (which attrs and Pydantic seem to support):

attrs

alias (str | None) – Override this attribute’s parameter name in the generated __init__ method.

Pydantic

An alias is an alternative name for a field, used when serializing and deserializing data.

This PR adds this behavior and also adds tests to verify correctness. Important things to note:

  • Dataclasses do not natively support aliases, so it continues to deserialize by field name.
  • attrs always populates alias, but Pydantic does not.
  • Pydantic aliases also support AliasPath and AliasChoices in addtion to str; this PR takes the easy path of falling back to the field name when the field alias is not a str (otherwise the logic to handle AliasPath and AliasChoices would be quite complex and may even require a refactor).
  • This is technically a breaking change (although I expect most people will not have set aliases for their settings classes given that (a) they did not work previously when loading from a file or environment variables and (b) instantiating a settings class with its __init__ method seems like it would be a rare occurence) and should be noted as such in the changelog.

In addtion, this PR fixes a few type hinting bugs:

  • The type hint for config_file_section (used in load() and default_loaders()) now correctly accepts None (which all FileFormats already accept).
  • The type signature of structure() in the Converter protocol is changed from def structure(self, value: Any, cls: type[T]) -> T: to def structure(self, obj: Any, cl: type[T]) -> T:. This correctly allows the cattrs Converter to implement the protocol as the parameter names need to be identical to do so.

Fixes #76 (closed).

Edited by Seow Alex

Merge request reports

Loading