Automatic (de)serialization of arguments and return values for Python functions.
pip install datafunctions
@datafunction
is a decorator which automatically deserializes incoming arguments of the decorated function and
serializes the return value. For example:
from datetime import datetime
from datafunctions import datafunction
@datafunction
def next_year(dt: datetime) -> datetime:
return dt.replace(year=dt.year + 1)
assert next_year("2019-01-02T00:00:00") == "2020-01-02T00:00:00"
@datafunction
automatically converts the string argument to a datetime object, and then
converts the returned datetime back to a string.
This is useful for calling functions over a remote connection or from a different language - see instant_api and instant_client for example.
More generally, the arguments and return value as seen from the outside the function are basic JSON serializable objects - strings, dicts, etc. They are converted to and from the correct types (as indicated by type annotations) by marshmallow. Common Python types as well as dataclasses (which may be nested) are supported. For example:
from dataclasses import dataclass
from datafunctions import datafunction
@dataclass
class Point:
x: int
y: int
@datafunction
def translate(p: Point, dx: int, dy: int) -> Point:
return Point(p.x + dx, p.y + dy)
assert translate({"x": 1, "y": 2}, 3, 4) == {"x": 4, "y": 6}
To decorate a method, pass is_method=True
, e.g:
class MyClass:
@datafunction(is_method=True)
def method(self, x: int) -> int:
...
All parameters and the return value must have a type annotation,
except for the first argument when is_method=True
.
Variadic parameters (e.g. *args
or **kwargs
) and positional-only parameters (before /
)
are not allowed.
If there is an exception deserializing or binding the arguments an ArgumentError
will be raised with the underlying exception attached to __cause__
.
Similarly a ReturnError
may be raised when trying to serialize the return value.
For more manual control, use the methods:
load_arguments
dump_arguments
load_result
dump_result
Under the hood, the type annotations are gathered into a dataclass which is then converted into a marshmallow schema using marshmallow_dataclass. marshmallow handles the (de)serialization.
Instances of this class have attributes params_schemas
and return_schemas
,
each of which have the following attributes:
dataclass
schema_class
: the marshmallow schema classschema_instance
: a no-args instance of schema_class