Skip to content

Instantly share code, notes, and snippets.

@juliengrenier
Created May 10, 2012 19:01
Show Gist options
  • Save juliengrenier/2655143 to your computer and use it in GitHub Desktop.
Save juliengrenier/2655143 to your computer and use it in GitHub Desktop.
NullProxy and Borg objects
class NullProxy(object):
"""Pretend you have a model object with three attributes:
class Person(object):
name = String(40)
age = Integer()
email = Email()
And have a sub-class adding extra attributes:
class SpecialPerson(Person):
role = "true believer"
If you want to safely treat Person and all subclasses the same:
me = NullProxy(Person(name="Alice"))
me.role == None
"""
def __init__(self, obj=None, default=None, parent=None):
self.obj = obj
self.default = default
self.parent = parent
def __call__(self, *args, **kw):
if not hasattr(self.obj, '__call__'):
raise TypeError("'{0!r}' object is not callable".format(self.obj))
value = self.obj(*args, **kw)
if value is None:
return self.parent
return value
def __getattr__(self, name):
try:
return NullProxy(getattr(self.obj, name), self.default, self.obj)
except AttributeError:
return NullProxy(self.default, self.default, self.obj)
def __setattr__(self, name, value):
if self.obj is None:
raise AttributeError("Can not write to null object.")
setattr(self.obj, name, value)
class Borg(object):
__collective__ = None
def __init__(self):
name = '_'.join(reversed([i.__name__ for i in type(self).mro()]))
if Borg.__dict__.setdefault('__collective_{0}__'.format(name), None) is None:
Borg.__dict__[name] = self.__dict__
else:
self.__dict__ = Borg.__dict__[name]
def __eq__(self, other):
return self.__dict__ is other.__dict__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment