Skip to content

Commit

Permalink
Documented redish.models
Browse files Browse the repository at this point in the history
  • Loading branch information
Ask Solem committed Apr 29, 2010
1 parent 82001a1 commit 617a7cf
Showing 1 changed file with 78 additions and 7 deletions.
85 changes: 78 additions & 7 deletions redish/models.py
Expand Up @@ -2,6 +2,7 @@




class ModelType(type): class ModelType(type):
"""Metaclass for :class:`Model`s."""


def __new__(cls, name, bases, attrs): def __new__(cls, name, bases, attrs):
attrs.setdefault("name", name) attrs.setdefault("name", name)
Expand All @@ -14,37 +15,85 @@ def __new__(cls, name, bases, attrs):




class Model(dict): class Model(dict):
"""A Model.
:param manager: The :class:`Manager` for this model.
:keyword id: Id of the entry, ``None`` if the entry has not been
created yet.
:keyword \*\*fields: Values of the entry.
.. attribute:: name
Name of the model.
**REQUIRED**
All models needs a name, this name is used to keep track of ids
related to this model.
.. attribute:: id
The unique id for this entry.
If the entry does not have an id, it means the entry has not yet
been created and a new id will be automatically assigned when saved.
.. attribute:: objects
:class:`Manager` instance for this model.
"""
__metaclass__ = ModelType

id = None id = None
name = None name = None
objects = None objects = None
__metaclass__ = ModelType


def __init__(self, manager, id=None, **fields): def __init__(self, manager, id=None, **fields):
self.objects = manager self.objects = manager
self.id = id self.id = id
dict.__init__(self, self.prepare_fields(fields)) dict.__init__(self, self.prepare_fields(fields))


def save(self): def save(self):
"""Save this entry.
If the entry does not have an :attr:`id`, a new id will be assigned,
and the :attr:`id` attribute set accordingly.
Pre-save processing of the fields saved can be done by
overriding the :meth:`prepare_save` method.
Additional actions to be done after the save operation
has been completed can be added by defining the
:meth:`post_save` method.
"""
id = self.id or self.objects.id(self.name) id = self.id or self.objects.id(self.name)
self.objects[id] = self.prepare_save(dict(self)) self.objects[id] = self.prepare_save(dict(self))
self.id = id self.id = id
self.post_save() self.post_save()
return id return id


def delete(self): def delete(self):
"""Delete this entry."""
del(self.objects[self.id]) del(self.objects[self.id])
self.post_delete() self.post_delete()


def prepare_save(self, fields): def prepare_save(self, fields):
"""Prepare fields for saving."""
return fields return fields


def prepare_fields(self, fields): def prepare_fields(self, fields):
"""Prepare fields when creating an instance of this class."""
return fields return fields


def post_save(self): def post_save(self):
"""Additional actions to be done after a :meth:`save` operation has been
completed."""
pass pass


def post_delete(self): def post_delete(self):
"""Additional actions to be done after a :meth:`delete` operation has
been completed."""
pass pass


def __repr__(self): def __repr__(self):
Expand All @@ -63,7 +112,8 @@ def __setattr__(self, key, value):
object.__setattr__(self, key, value) object.__setattr__(self, key, value)




class WithModelRelation(type): class ManagerType(type):
"""Metaclass for :class:`Manager`s."""


def __new__(cls, name, bases, attrs): def __new__(cls, name, bases, attrs):
if not attrs.get("abstract", False): if not attrs.get("abstract", False):
Expand All @@ -75,30 +125,51 @@ def instance(self, id=None, **fields):
attrs[model.name] = attrs["instance"] = instance attrs[model.name] = attrs["instance"] = instance
attrs["abstract"] = False attrs["abstract"] = False


return super(WithModelRelation, cls).__new__(cls, name, bases, attrs) return super(ManagerType, cls).__new__(cls, name, bases, attrs)




class Manager(Client): class Manager(Client):
__metaclass__ = WithModelRelation """A manager.
.. attribute model::
The :class:`Model` this is a manager for.
**REQUIRED**
.. attribute abstract::
Set this to ``True`` if this is an abstract class,
(i.e not having a :attr:`model` instance assigned to it).
.. attribute instance::
Method returning an instance of the model that is
connected to this manager.
"""
__metaclass__ = ManagerType

model = None model = None
abstract = True abstract = True


def get(self, id): def get(self, id):
"""Get entry by id."""
return self.instance(id, **self[id]) return self.instance(id, **self[id])


def get_many(self, ids): def get_many(self, ids):
"""Get several entries at once."""
return [self.instance(id, **fields) return [self.instance(id, **fields)
for id, fields in zip(ids, self.api.mget(ids))] for id, fields in zip(ids, self.api.mget(ids))]


def __iter__(self): def __iter__(self):
pattern = ":*" % self.model.name pattern = "%s:*" % self.model.name
return (self.instance(id, **fields) return (self.instance(id, **fields)
for id, fields in self.iteritems(pattern)) for id, fields in self.iteritems(pattern))


def all(self): def all(self):
"""Get all entries."""
return list(iter(self)) return list(iter(self))


def create(self, **data): def create(self, **fields):
entry = self.instance(**data) """Create new entry."""
entry = self.instance(**fields)
entry.save() entry.save()
return entry return entry

0 comments on commit 617a7cf

Please sign in to comment.