From dab92e3da7c5ab1f26b58df11ee56dcbeb8ad971 Mon Sep 17 00:00:00 2001 From: Isaac Flath Date: Wed, 2 Oct 2024 07:30:25 -0400 Subject: [PATCH] Bug fix for keys --- fastcore/basics.py | 10 ++++------ nbs/01_basics.ipynb | 44 +++++++++++++++++++------------------------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/fastcore/basics.py b/fastcore/basics.py index 3c94682e..b6d41d44 100644 --- a/fastcore/basics.py +++ b/fastcore/basics.py @@ -714,12 +714,10 @@ def only(o): def nested_attr(o, attr, default=None): "Same as `getattr`, but if `attr` includes a `.`, then looks inside nested objects" try: - for a in attr.split("."): - if hasattr(o, a): o = getattr(o, a) - elif isinstance(o, (list, tuple, dict)) and a.isdigit():o = o[int(a)] - elif hasattr(o, '__getitem__'): o = o[a] - else: return default - except (AttributeError, KeyError, IndexError, TypeError): + for a in attr.split("."): + try: o = getattr(o, a) + except AttributeError: o = o[a] + except (KeyError,IndexError, TypeError, ValueError): return default return o diff --git a/nbs/01_basics.ipynb b/nbs/01_basics.ipynb index a5347899..446453d5 100644 --- a/nbs/01_basics.ipynb +++ b/nbs/01_basics.ipynb @@ -3903,13 +3903,6 @@ "test_fail(lambda: only([0,1]), contains='iterable has more than 1 item')" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, @@ -3920,12 +3913,10 @@ "def nested_attr(o, attr, default=None):\n", " \"Same as `getattr`, but if `attr` includes a `.`, then looks inside nested objects\"\n", " try:\n", - " for a in attr.split(\".\"):\n", - " if hasattr(o, a): o = getattr(o, a)\n", - " elif isinstance(o, (list, tuple, dict)) and a.isdigit():o = o[int(a)]\n", - " elif hasattr(o, '__getitem__'): o = o[a]\n", - " else: return default\n", - " except (AttributeError, KeyError, IndexError, TypeError):\n", + " for a in attr.split(\".\"): \n", + " try: o = getattr(o, a)\n", + " except AttributeError: o = o[a]\n", + " except (KeyError,IndexError, TypeError, ValueError):\n", " return default\n", " return o" ] @@ -3935,6 +3926,20 @@ "execution_count": null, "metadata": {}, "outputs": [], + "source": [ + "class CustomIndexable:\n", + " def __init__(self): self.data = {'a':1,'b':'v','c':{'d':5}}\n", + " def __getitem__(self, key): return self.data[key]\n", + "\n", + "custom_indexable = CustomIndexable()\n", + "test_eq(nested_attr(custom_indexable,'a'),1)\n", + "test_eq(nested_attr(custom_indexable,'c.d'),5)\n", + "test_eq(nested_attr(custom_indexable,'e'),None)" + ] + }, + { + "cell_type": "raw", + "metadata": {}, "source": [ "class TestObj:\n", " def __init__(self): self.nested = {'key': [1, 2, {'inner': 'value'}]}\n", @@ -3973,6 +3978,7 @@ "metadata": {}, "outputs": [], "source": [ + "#|hide\n", "class CustomIndexable:\n", " def __init__(self): self.data = {'a':1,'b':'v','c':{'d':5}}\n", " def __getitem__(self, key): return self.data[key]\n", @@ -4009,18 +4015,6 @@ "test_eq(o, {'a':{'b':{'c':'d'}},'e':'f'})" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#|hide\n", - "o = {'a':'b'}\n", - "test_eq(nested_setdefault(o, 'a', 'c'), 'b')\n", - "test_eq(o, {'a':'b'})" - ] - }, { "cell_type": "code", "execution_count": null,