Last active
December 8, 2017 03:57
-
-
Save tonnydourado/0ac11c518d5331d182d3ef62563d649c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from functools import wraps | |
from typing import Dict | |
from attr import attrs | |
from attr.validators import in_ | |
from cattr import typed, structure, unstructure | |
# Don't at me, I like methods: | |
def to_dict(self): | |
return unstructure(self) | |
def to_json(self): | |
return json.dumps(self.to_dict()) | |
# Not so sure about the name, but it's 1 AM, so go away: | |
def validated(maybe_cls=None, *attrs_args, **attrs_kwargs): | |
""" | |
Adds type checking on instantiation to attrs-enabled classes | |
:param maybe_cls: maybe the class being decorated, maybe not, depending on | |
how the decorator is used | |
""" | |
def wrapper(cls): | |
attrs_cls = attrs(**attrs_kwargs)(cls) | |
attrs_cls.to_dict = to_dict | |
attrs_cls.to_json = to_json | |
@wraps(attrs_cls) | |
def new(**kwargs): | |
# Dealing with defaults because cattrs doesn't =/ | |
for attribute in attrs_cls.__attrs_attrs__: | |
if attribute.name not in kwargs.keys(): | |
kwargs[attribute.name] = attribute.default | |
return structure(kwargs, attrs_cls) | |
# Setting the class being used, just in case we need it: | |
new.cls = attrs_cls | |
return new | |
# maybe_cls's type depends on the usage of the decorator. It's a class | |
# if it's used as `@validated` but ``None`` if used as `@validated()`. | |
if maybe_cls is None: | |
return wrapper | |
else: | |
return wrapper(maybe_cls) | |
@validated | |
class Stuff(object): | |
integer = typed(int, validator=in_([1, 2])) | |
mapping = typed(Dict, default={}) | |
string = typed(str, default='') | |
print(Stuff, Stuff.cls) | |
print(Stuff(integer=1)) | |
print(Stuff(integer='1')) | |
print(Stuff(integer=1, string=234)) | |
try: | |
print(Stuff(integer='asdsd')) | |
except Exception as e: | |
print(type(e), e) | |
# Apparently cattrs deals with mutable defaults, so we don't neet attr.Factory: | |
s1, s2 = Stuff(integer=1), Stuff(integer=2) | |
print(s1, s2) | |
s1.mapping['adasd'] = 1 | |
print(s1, s2, s1.mapping is s2.mapping) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment