This was mentioned in #1751:
I think this is an indication that Schema needs to be easier to customize, not that we need to bake more custom functionality into the base schema.
OneOfSchema is just one motivating use-case. More generally, what kind of structures are problematic today for customizing Schema?
Some examples of things which could possibly be improved:
- Customizing
_serialize and _deserialize?
#1726 is all about making Schema._serialize and Schema._deserialize open to subclasses as a better place to customize behavior. Whether or not extra={...} is a good idea (#1726), is making these steps friendly to overload a good approach?
- Hook execution (order matters)
Often, users want a schema base class which has some fixed "pre_load" or "post_load" behavior. But if a base schema adds a @pre_load method, it will get mixed with the potential hooks on subclasses and the user's desired ordering is lost.
One approach would be to let users overload hook processing and rely on super() to call the "real" hooks. The signatures for _invoke_schema_validators, _invoke_load_processors, and _invoke_dump_processors are all slightly different. Can they be unified into a method like Schema.run_hook(...)? Or, alternatively, replace these with methods like Schema.run_pre_load_hooks(...)?
- Customizing handling of unknown fields
INCLUDE, EXCLUDE, and RAISE are good out-of-the-box behaviors. Looking at issues like #853 , could this potentially be solved by making the handling of unknown fields settable as a hook?
Mainly, the logic is here:
|
if unknown != EXCLUDE: |
|
fields = { |
|
field_obj.data_key if field_obj.data_key is not None else field_name |
|
for field_name, field_obj in self.load_fields.items() |
|
} |
|
for key in set(data) - fields: |
|
value = data[key] |
|
if unknown == INCLUDE: |
|
ret_d[key] = value |
|
elif unknown == RAISE: |
|
error_store.store_error( |
|
[self.error_messages["unknown"]], |
|
key, |
|
(index if index_errors else None), |
|
) |
What about Schema.handle_unknown_fields(...) or some method like that? So the Schema class implements today's behavior, and users can subclass and override with their own behaviors.
This was mentioned in #1751:
OneOfSchema is just one motivating use-case. More generally, what kind of structures are problematic today for customizing Schema?
Some examples of things which could possibly be improved:
_serializeand_deserialize?#1726 is all about making
Schema._serializeandSchema._deserializeopen to subclasses as a better place to customize behavior. Whether or notextra={...}is a good idea (#1726), is making these steps friendly to overload a good approach?Often, users want a schema base class which has some fixed "pre_load" or "post_load" behavior. But if a base schema adds a
@pre_loadmethod, it will get mixed with the potential hooks on subclasses and the user's desired ordering is lost.One approach would be to let users overload hook processing and rely on
super()to call the "real" hooks. The signatures for_invoke_schema_validators,_invoke_load_processors, and_invoke_dump_processorsare all slightly different. Can they be unified into a method likeSchema.run_hook(...)? Or, alternatively, replace these with methods likeSchema.run_pre_load_hooks(...)?INCLUDE,EXCLUDE, andRAISEare good out-of-the-box behaviors. Looking at issues like #853 , could this potentially be solved by making the handling of unknown fields settable as a hook?Mainly, the logic is here:
marshmallow/src/marshmallow/schema.py
Lines 666 to 680 in 8af34a9
What about
Schema.handle_unknown_fields(...)or some method like that? So theSchemaclass implements today's behavior, and users can subclass and override with their own behaviors.