marshmallow
marshmallow copied to clipboard
Generate a TypedDict or dataclass from Schema
It would be nice to be able to use Schema
ta with mypy or similar, e.g.
class User(Schema):
name = fields.String()
age = fields.Integer()
def have_a_birthday(user: User.type) -> User.type:
user['age'] += '1' # will fail type check
return user # typechecks OK
I started an inline implementation with Schema._declared_fields
, but since there's nothing like a Field.deser_type
it was going to be quite a hacky map by cases - isinstance(cls, fields.String)
etc. - and then I realised I had nested fields to contend with and jumped out of the rabbit hole before I got too deep.
I do think this would be very nice to have though, or perhaps even go further and have a @deser_to_dataclass
decorator (that's the route I was going) that re-writes the Schema
so that the type is User
(or whatever) itself, and User.name
is annotated automatically as : str
.
I've been considering something like this. It's a neat idea.
A few half-baked thoughts:
- You would need to generate types from schema instances rather than classes. Conceptually, a schema instance represents a set of known inputs/outputs, whereas a schema class is more like a blueprint or factory.
- There need to be different
TypedDict
s generated for load vs dump. So you could have an API like
def user_detail(user: LoadType(UserSchema())) -> DumpType(UserSchema()):
# ...
- This is pretty tricky given that
post_load
andpost_dump
methods can return any type.
I probably won't pursue this myself for a while, and I don't think we should put this into marshmallow core at least until PEP 589 lands. If you end up experimenting with this in a 3rd-party repo, though, please let us know.
I do think this would be very nice to have though, or perhaps even go further and have a @deser_to_dataclass
You might want to look into https://github.com/lovasoa/marshmallow_dataclass . It generates a schema from dataclass that also deserializes to the same dataclass.
+1 for marshmallow_dataclass
. It would be cool to eventually see this kind of functionality included in Marshmallow by default now that it's Python 3-only!
Well, we'll be supporting Python 3.5 and 3.6 for a while, so probably won't be added to marshmallow core any time soon. That said, it seems to be actively maintained, and I might even help out with it.
Maybe marshmallow 4 could go PY3.7+ and include marshmallow-dataclass?
Maybe marshmallow 4 could go PY3.7+ and include marshmallow-dataclass?
@lafrech I'm open to that. We could even do it in marshmallow 3 if we keep it in an isolated module.
How about building a schema based on an existing TypedDict class? There's a plenty of information that can be inferred from the type definition, similar to marshmallow-dataclass
.
Maybe adding a field that allows the dev to state the type to cast the dump into?
Schema().dump(schema_obj, cast=my_typed_dict)
Currently @post_load
and @post_dump
do not pass along their type hints to the load
and dump
functions. If they could then that would be even better :)