Skip to content

Instantly share code, notes, and snippets.

@marconi
Created August 25, 2011 00:00
Show Gist options
  • Select an option

  • Save marconi/1169614 to your computer and use it in GitHub Desktop.

Select an option

Save marconi/1169614 to your computer and use it in GitHub Desktop.
Cleaner model API
import copy
class Field(object):
def __init__(self, value=None):
self.name = None
self.value = value
def set_field_name(self, name):
"""
Called upon field assignment on
model so fields remember who they are.
"""
self.name = name
def __set__(self, instance, value):
instance.__dict__[self.name] = value
def __get__(self, instance, owner):
if instance is None:
raise AttributeError
elif self.name not in instance.__dict__:
raise AttributeError, self.name
return instance.__dict__[self.name].value
class ModelMeta(type):
def __new__(cls, name, bases, attrs):
super_class = super(ModelMeta, cls).__new__
# pass the name of the field to its instance
# so its aware what to retrieve later
for attr_name, attr in attrs.items():
if isinstance(attr, Field):
attr.set_field_name(attr_name)
new_class = super_class(cls, name, bases, attrs)
return new_class
class Model(object):
__metaclass__ = ModelMeta
def __init__(self, **kwargs):
# copy all fields from class namespace to the instance
for attr_name, attr in self.__class__.__dict__.items():
if isinstance(attr, Field):
attr.set_field_name(attr_name)
setattr(self, attr_name, copy.deepcopy(attr))
# set any override for the fields
for key, val in kwargs.items():
if hasattr(self, key):
setattr(self.__dict__[key], 'value', val)
else:
raise TypeError, "got an unexpected keyword argument '%s'" % key
class User(Model):
name = Field() # <--- Look ma, its cleaner! :)
email = Field()
if __name__ == "__main__":
users = (User(name='Marc', email='marc@gmail.com'),
User(name='Juan', email='juan@gmail.com'))
for u in users:
print "Name: %s\nEmail:%s\n" % (u.name, u.email)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment