Skip to content

Instantly share code, notes, and snippets.

@jmsdnns
Created April 15, 2016 04:16
Show Gist options
  • Save jmsdnns/f4064657eac0173773e2ca162ac802be to your computer and use it in GitHub Desktop.
Save jmsdnns/f4064657eac0173773e2ca162ac802be to your computer and use it in GitHub Desktop.
super bare bones implementation of schematics logic
# TYPES
class TypeError(Exception):
pass
class BaseType(object):
def __get__(self, instance, owner):
return instance._values.get(self.field_name, None)
def __set__(self, instance, value):
instance._values[self.field_name] = value
def validate(self, value):
pass
class StringType(BaseType):
def validate(self, value):
try:
print 'StringType field (%s) validate: %s ' % (self.field_name, value)
value = str(value)
except:
error_msg = "could not coerce .%s value (%s) to string" % (self.field_name, value)
raise TypeError(error_msg)
else:
return value
class IntType(BaseType):
def validate(self, value):
try:
print 'IntType field (%s) validate: %s ' % (self.field_name, value)
value = int(value)
except:
error_msg = "could not coerce .%s value (%s) to int" % (self.field_name, value)
raise TypeError(error_msg)
else:
return value
# MODELS
class ModelError(Exception):
def __init__(self, message, errors):
super(ModelError, self).__init__(message)
self.errors = errors
def __str__(self):
reasons = ['Model errors:']
for i,e in enumerate(self.errors):
reasons.append("- %d. %s" % ((i+1), e.message))
return '\n'.join(reasons)
class BaseMeta(type):
def __new__(mcs, name, bases, attrs):
print 'BaseMeta.__new__'
print '- mcs:', mcs
print '- name:', name
print '- bases:', bases
print '- attrs:', attrs
print ''
klass = type.__new__(mcs, name, bases, attrs)
klass._fields = {}
for field_name, field_type in attrs.iteritems():
if isinstance(field_type, BaseType):
# field instances know their name
field_type.field_name = field_name
# fields are instances of types
klass._fields[field_name] = field_type
return klass
class BaseModel(object):
__metaclass__ = BaseMeta
def __init__(self):
print 'BaseModel.__init__'
self._values = {}
def validate(self):
errors = []
for field_name, field_type in self._fields.iteritems():
if field_name in self._values:
value = self._values[field_name]
try:
value = field_type.validate(value)
except TypeError as te:
errors.append(te)
else:
self._values[field_name] = value
if len(errors) > 0:
error_msg = 'Raising %d errors' % (len(errors))
raise ModelError(error_msg, errors)
from base_models import BaseModel, IntType, StringType
class MyModel(BaseModel):
i = IntType()
ii = IntType()
iii = IntType()
s = StringType()
def __init__(self, *a, **kw):
super(MyModel, self).__init__(*a, **kw)
from models import MyModel
mm = MyModel()
mm.i = 3
mm.ii = "bar"
mm.iii = "barr"
mm.s = "foo"
try:
mm.validate()
except Exception as e:
print e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment