Skip to content

Instantly share code, notes, and snippets.



Last active Aug 29, 2015
What would you like to do?
Naive attempt at porting Oat ( to Python
import warnings
from collections import OrderedDict
from itertools import chain
from inflection import pluralize
class Adapter(object):
def __init__(self): = OrderedDict()
def to_dict(self):
class HAL(Adapter):
def property(self, key, value):[key] = value
def relationship(self, key, value):'_embedded', OrderedDict())[key] = value
def link(self, rel, opts):
if 'href' in opts:'_links', OrderedDict())[rel] = opts
class Siren(Adapter):
def __init__(self):
super(Siren, self).__init__()['links'] = []['entities'] = []['actions'] = []
def type(self, *types):['class'] = types
def property(self, key, value):'properties', OrderedDict())[key] = value
def relationship(self, key, value):
if not isinstance(value, list):
value = [value]['entities'].extend(value)
def link(self, rel, opts):
opts.update({'rel': [rel]})['links'].append(opts)
class JSON_API(Adapter):
def __init__(self):
super(JSON_API, self).__init__()
self.entities = OrderedDict()
def type(self, *types):['__type__'] = pluralize(types[0])
def property(self, key, value):[key] = value
def relationship(self, key, value):
if not isinstance(value, list):
value = [value]
linked_key = pluralize(value[0].keys()[0])
value = list(chain.from_iterable([item.pop(item.keys()[0]) for item in value])), {'href': [i['id'] for i in value]})
self.entities.setdefault(linked_key, []).extend(value)
def link(self, rel, opts):'links', OrderedDict())[rel] = opts['href']
def to_dict(self):
root_name ='__type__', None)
if not root_name:
raise Exception('JSON API schemas must define a type')
return OrderedDict([
(root_name, []),
('linked', self.entities)
def _getattr(obj, attr, coerce=None):
if not coerce:
coerce = lambda v: v
if callable(attr):
rv = attr(obj)
rv = reduce(getattr, attr.split('.'), obj)
return coerce(rv)
def Relationship(name, attr=None, many=False, schema=None):
attr = attr or name
def _Relationship(obj, adapter):
_obj = _getattr(obj, attr)
if many:
val = [schema(o, adapter) for o in _obj]
val = schema(_obj, adapter)
adapter.relationship(name, val)
return _Relationship
def Link(rel, **opts):
def _Link(obj, adapter):
for k, v in opts.iteritems():
if callable(v):
opts[k] = v(obj), opts)
return _Link
def Property(name, attr=None, coerce=None):
attr = attr or name
def _Property(obj, adapter):, _getattr(obj, attr, coerce))
return _Property
def Properties(*properties):
def _Properties(obj, adapter):
for p in properties:
name = attr = p
if isinstance(p, tuple):
name, attr = p, _getattr(obj, attr))
return _Properties
def Type(*types):
def _Type(obj, adapter):
except AttributeError:
msg = '%s adapter does not implement `type`' % adapter.__class__.__name__
warnings.warn(msg, UserWarning)
return _Type
class _Schema(object):
def __init__(self, handlers):
self.handlers = handlers
def __call__(self, obj, adapter):
if isinstance(adapter, type):
adapter = adapter()
elif isinstance(adapter, Adapter):
adapter = adapter.__class__()
for handler in self.handlers:
handler(obj, adapter)
return adapter.to_dict()
def Schema(*handlers):
return _Schema(handlers)
import json
from oat import *
class Obj(object):
def __init__(self, **kwargs):
for k, v in kwargs.iteritems():
setattr(self, k, v)
obj = Obj(
address=Obj(line1='1 Street Rd'),
child=Obj(id='2', name='Matt'),
Obj(id='3', name='Tim'),
Obj(id='4', name='Mike')
schema = Schema(
Link('self', href=''),
Link('derp', href=lambda o: '' %,
Property('id1', lambda o:, coerce=str),
('name', 'first_name'),
('name1', lambda o: o.first_name),
('address', 'address.line1')
Relationship('child', schema=Schema(
Properties('id', 'name')
Relationship('children', many=True, schema=Schema(
Properties('id', 'name')
for a in HAL, Siren, JSON_API:
print json.dumps(schema(obj, a), indent=2)
print '-' * 50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.