Repository: frmdstryr/magicattr

Issue:
Support default values in get()
getattr() supports a default value if the attr doesn't exist. magicattr should mimic that behaviour.

Discussion:

Patch:
diff --git a/magicattr.py b/magicattr.py
index dc8343e..282e186 100644
--- a/magicattr.py
+++ b/magicattr.py
@@ -17,7 +17,7 @@ _AST_TYPES = (ast.Name, ast.Attribute, ast.Subscript, ast.Call)
 _STRING_TYPE = basestring if sys.version_info.major == 2 else str
 
 
-def get(obj, attr):
+def get(obj, attr, **kwargs):
     """ A getattr that supports nested lookups on objects, dicts, lists, and
     any combination in between.
     
@@ -27,13 +27,24 @@ def get(obj, attr):
         An object to lookup the attribute on
     attr: String
         A attribute string to lookup
-        
+    kwargs:
+        default: Any
+            A default value used as a fallback if attr doesn't exist
+
     Returns
     -------
     result: Object
-        The object retrieved
+        The object retrieved or the default fallback value, if it was passed
     """
-    return reduce(_lookup, _parse(attr), obj)
+    for chunk in _parse(attr):
+        try:
+            obj = _lookup(obj, chunk)
+        except Exception as ex:
+            if "default" in kwargs:
+                return kwargs["default"]
+            else:
+                raise ex
+    return obj
 
 
 def set(obj, attr, val):


Test patch:
diff --git a/tests.py b/tests.py
index 8424d62..17698dd 100644
--- a/tests.py
+++ b/tests.py
@@ -60,6 +60,11 @@ def test_person_example():
     # Nothing new
     assert magicattr.get(bob, 'age') == 31
 
+    # Default value (optional)
+    with pytest.raises(AttributeError) as e:
+        magicattr.get(bob, 'weight')
+    assert magicattr.get(bob, 'weight', default=75) == 75
+
     # Lists
     assert magicattr.get(jill, 'friends[0].name') == 'Bob'
     assert magicattr.get(jack, 'friends[-1].age') == 29