From 3420ac8d6bef0bde8a2c4973a5f4630d6ac71da7 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Mon, 18 Nov 2019 23:35:45 -0500 Subject: [PATCH] Add support for __getattr__ (#36) --- forbiddenfruit/__init__.py | 2 ++ tests/unit/test_forbidden_fruit.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/forbiddenfruit/__init__.py b/forbiddenfruit/__init__.py index afcd926..5b3e095 100644 --- a/forbiddenfruit/__init__.py +++ b/forbiddenfruit/__init__.py @@ -203,6 +203,7 @@ class PyAsyncMethods(ctypes.Structure): ('tp_hash', ctypes.CFUNCTYPE(ctypes.c_int64, PyObject_p)), ('tp_call', ctypes.CFUNCTYPE(PyObject_p, PyObject_p, PyObject_p, PyObject_p)), ('tp_str', ctypes.CFUNCTYPE(PyObject_p, PyObject_p)), + ('tp_getattr', ctypes.CFUNCTYPE(PyObject_p, PyObject_p, PyObject_p)) # ... ] @@ -317,6 +318,7 @@ def __filtered_dir__(obj=None): # divmod isn't a dunder, still make it overridable override_dict['divmod()'] = ('tp_as_number', "nb_divmod") override_dict['__str__'] = ('tp_str', "tp_str") +override_dict['__getattr__'] = ('tp_getattr', "tp_getattr") def _is_dunder(func_name): diff --git a/tests/unit/test_forbidden_fruit.py b/tests/unit/test_forbidden_fruit.py index 5830337..be5dbe7 100644 --- a/tests/unit/test_forbidden_fruit.py +++ b/tests/unit/test_forbidden_fruit.py @@ -330,3 +330,16 @@ def type_error_str(self): reverse(TypeError, '__str__') assert str(te) == "testing" + +@skip_legacy +def test_overriding_getattr(): + """Overload __getattr__ for dicts to lookup a key""" + def getter(self, x): + try: + return object.__getattribute__(self, x) + except AttributeError: + return self[x] + curse(dict, "__getattr__", getter) + + my_dict = {"abc": "xyz"} + assert(my_dict.abc == "xyz")