Created
December 1, 2014 08:50
-
-
Save kalda341/b958ab2cd70641252c46 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
from mongo import Mongo | |
import inspect | |
""" | |
Metaclass to simplify use of items stored in the database | |
""" | |
class DatabaseLinkMeta(type): | |
def __new__(metaclass, classname, bases, classdict): | |
mongo = Mongo() | |
#Collection in database for class can be specified with the _collectionName | |
#variable, otherwise the class name with an "s" appended will be used | |
if classdict.get('_collectionName') == None: | |
collecionName = classname + 's' | |
else: | |
collecionName = classdict.get('_collectionName') | |
def _update(obj, changes): | |
mongo.update(collecionName, obj._id, changes) | |
def _find(query): | |
mongo.find(collecionName, query) | |
classdict['find'] = staticmethod(_find) | |
def _find_one(query): | |
mongo.find_one(collecionName, query) | |
classdict['find_one'] = staticmethod(_find_one) | |
#Preserve classes original constructor | |
classinit = classdict.get('__init__') | |
def _init(object, *args, **kwargs): | |
_id = kwargs.get('_id') | |
if _id == None: | |
#If object has no ID then it needs to be created to recieve one | |
object._id = _save(obj) | |
if not classinit == None: | |
#Call original constructor | |
classinit(object, *args, **kwargs) | |
else: | |
#Constructor has been passed an ID kwarg. Attempt to create object | |
#from database records | |
dbobj = mongo.get({'_id': id}) | |
if dbobj == None: | |
raise AttributeError("No object exists with id %s" % _id) | |
classdict.update(dbobj) | |
print ("ID=%s" % object._id ) | |
#Override constructor on class | |
classdict['__init__'] = _init | |
""" | |
Checks that instance variables types haven't changed | |
""" | |
def _originaltypecheck(obj, attr, value): | |
if attr in classdict: | |
if not isinstance(value, type(classdict[attr])): | |
raise TypeError("%s must of the type used in the class definition" % attr) | |
def _setattr(obj, attr, value): | |
#Do not allow changing an objects ID | |
if attr == '_id': | |
raise AttributeError("id attribute cannot be changed") | |
if attr in classdict['DatabaseAttributes']: | |
#Do not allow changing the type of a database attribute | |
_originaltypecheck(obj, attr, value) | |
#Replace value with an ID if object's class is stored in the database | |
if type(value).__metaclass__ == inspect.stack()[0].__class__: | |
db_value = value._id | |
else: | |
dn_value = value | |
#Update the database record | |
_update(obj, {attr: db_value}) | |
#Update the value of the attribute if it has made it this far | |
object.__setattr__(obj, attr, value) | |
#Override __setattr__ | |
classdict['__setattr__'] = _setattr | |
"Gets an instance with the following attributes" | |
def getWithAttributes(**kwargs): | |
pass | |
classdict['getWithAttributes'] = _getWithAttributes | |
#Finally, create the class | |
return type.__new__(metaclass, classname, bases, classdict) | |
class Article(metaclass=DatabaseLinkMeta): | |
DatabaseAttributes = ('text') | |
text = "" | |
def __init__(self): | |
pass | |
class Edit(metaclass=DatabaseLinkMeta): | |
DatabaseAttributes = (article, startchar, endchar, text) | |
article = Article() | |
startchar = 0 | |
endchar = 0 | |
text = "" | |
class GlobalTag(metaclass=DatabaseLinkMeta): | |
DatabaseAttributes = (tag) | |
tag = "" | |
class Tag(metaclass=DatabaseLinkMeta): | |
global_tag = GlobalTag() | |
article = Article() | |
DatabaseAttributes = (global_tag) | |
a = Article() | |
a.text = "a" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment