Skip to content

Instantly share code, notes, and snippets.

@kalda341
Created December 1, 2014 08:50
Show Gist options
  • Save kalda341/b958ab2cd70641252c46 to your computer and use it in GitHub Desktop.
Save kalda341/b958ab2cd70641252c46 to your computer and use it in GitHub Desktop.
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