Skip to content

Instantly share code, notes, and snippets.

@migonzalvar
Created August 16, 2016 12:09
Show Gist options
  • Save migonzalvar/30172ce9bfe12bfd9e37c58639228af4 to your computer and use it in GitHub Desktop.
Save migonzalvar/30172ce9bfe12bfd9e37c58639228af4 to your computer and use it in GitHub Desktop.
Demostración casos de uso de `PEP 484 -- Type Hints`
import datetime as dt
from collections import OrderedDict as odict
import inspect
import types
from rest_framework import serializers
def function(a: int, b: str):
pass
def serializer_factory(fn):
# Class namespace
cls_name = '{}Serializer'.format(fn.__name__.capitalize())
cls_dict = odict()
for param in inspect.signature(fn).parameters.values():
# Alias
field_name = param.name
type_ = param.annotation
# Build serializer field arguments
args = {}
if issubclass(type_, str):
field_type = serializers.CharField
args['allow_blank'] = True # Every CharFiled could be an empty string
elif issubclass(type_, dt.datetime):
field_type = serializers.DateTimeField
elif issubclass(type_, dt.date):
field_type = serializers.DateField
elif issubclass(type_, int):
field_type = serializers.IntegerField
elif issubclass(type_, dict):
field_type = serializers.DictField
elif issubclass(type_, Decimal):
field_type = serializers.DecimalField
args.update({'max_digits': 15, 'decimal_places': 4})
else:
raise LookupError(
'Mapping of type {type} not found for field {field!r}'
''.format(field=field_name, type=type_)
)
# Add field to class namespace
cls_dict[field_name] = field_type(**args)
# Create serializer programmatically
cls = types.new_class(
cls_name,
(serializers.Serializer, ),
{},
exec_body=lambda ns: ns.update(cls_dict)
)
return cls
if __name__ == '__main__':
FunctionSerializer = serializer_factory(function)
assert len(FunctionSerializer().fields) == 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment