My problem is a general one, how to chain a series of attribute lookups when one of the intermediate ones might return None, but since I ran into this problem t
One solution would be to wrap the outer object inside a Proxy that handles None values for you. See below for a beginning implementation.
import unittest
class SafeProxy(object):
def __init__(self, instance):
self.__dict__["instance"] = instance
def __eq__(self, other):
return self.instance==other
def __call__(self, *args, **kwargs):
return self.instance(*args, **kwargs)
# TODO: Implement other special members
def __getattr__(self, name):
if hasattr(self.__dict__["instance"], name):
return SafeProxy(getattr(self.instance, name))
if name=="val":
return lambda: self.instance
return SafeProxy(None)
def __setattr__(self, name, value):
setattr(self.instance, name, value)
# Simple stub for creating objects for testing
class Dynamic(object):
def __init__(self, **kwargs):
for name, value in kwargs.iteritems():
self.__setattr__(name, value)
def __setattr__(self, name, value):
self.__dict__[name] = value
class Test(unittest.TestCase):
def test_nestedObject(self):
inner = Dynamic(value="value")
middle = Dynamic(child=inner)
outer = Dynamic(child=middle)
wrapper = SafeProxy(outer)
self.assertEqual("value", wrapper.child.child.value)
self.assertEqual(None, wrapper.child.child.child.value)
def test_NoneObject(self):
self.assertEqual(None, SafeProxy(None))
def test_stringOperations(self):
s = SafeProxy("string")
self.assertEqual("String", s.title())
self.assertEqual(type(""), type(s.val()))
self.assertEqual()
if __name__=="__main__":
unittest.main()
NOTE: I am personally not sure wether I would use this in an actual project, but it makes an interesting experiment and I put it here to get people thoughts on this.