Skip to content
This repository was archived by the owner on Dec 1, 2021. It is now read-only.

Commit

Permalink
Implemented easydict. (#1094)
Browse files Browse the repository at this point in the history
## What this patch does to fix the issue.

#1092
  • Loading branch information
odoku authored Jun 25, 2020
1 parent 0d22ed4 commit aee0301
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
52 changes: 52 additions & 0 deletions blueoil/utils/smartdict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
# Copyright 2018 The Blueoil Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =============================================================================


class SmartDict(dict):
def __init__(self, d=None, **kwargs):
super(SmartDict, self).__init__()
self.update(d, **kwargs)

def update(self, d=None, **kwargs):
d = d or {}
d.update(kwargs)
for key, value in d.items():
self[key] = value

def __setitem__(self, name, value):
if isinstance(value, (list, tuple)):
value = [
self.__class__(x) if isinstance(x, dict) else x
for x in value
]
elif isinstance(value, dict) and not isinstance(value, self.__class__):
value = self.__class__(value)
super(SmartDict, self).__setitem__(name, value)

def __getattr__(self, name):
if name in self:
return self[name]
raise AttributeError("'{}' object has no attribute '{}'".format(
self.__class__.__name__, name,
))

def __setattr__(self, name, value):
self[name] = value

def __dir__(self):
parent = super(SmartDict, self).__dir__()
attrs = parent + list(self.keys())
return sorted(attrs)
98 changes: 98 additions & 0 deletions tests/unit/util_tests/test_smartdict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Copyright 2018 The Blueoil Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =============================================================================
import pytest

from blueoil.utils.smartdict import SmartDict


def test_init():
d = SmartDict(a=10, b=20, c=30)
assert isinstance(d, SmartDict)
assert d.a == 10
assert d.b == 20
assert d.c == 30
assert d["a"] == 10
assert d["b"] == 20
assert d["c"] == 30


def test_init_with_dict():
d = SmartDict({"a": 10, "b": 20, "c": 30})
assert isinstance(d, SmartDict)
assert d.a == 10
assert d.b == 20
assert d.c == 30
assert d["a"] == 10
assert d["b"] == 20
assert d["c"] == 30


def test_update():
d = SmartDict({"a": 10, "b": 20, "c": 30})
d.update({"a": 40, "b": 50})
assert d.a == 40
assert d.b == 50
assert d.c == 30
d.update(c=60)
assert d.c == 60


def test_setitem():
d = SmartDict()
d["a"] = [
100,
{"a": 10, "b": 20, "c": 30},
]
assert d.a[0] == 100
assert isinstance(d.a[1], SmartDict)
assert d.a[1].a == 10
assert d.a[1].b == 20
assert d.a[1].c == 30

d["b"] = {"a": 10, "b": 20, "c": 30}
assert isinstance(d.b, SmartDict)
assert d.b.a == 10
assert d.b.b == 20
assert d.b.c == 30


def test_getattr():
d = SmartDict(a=10, b=20, c=30)
assert d.a == 10
assert d.b == 20
assert d.c == 30
with pytest.raises(AttributeError):
d.d


def test_setattr():
d = SmartDict()
d.a = 10
d.b = 20
d.c = 30
assert d["a"] == 10
assert d["b"] == 20
assert d["c"] == 30


def test_dir():
d = SmartDict(a=10, b=20, c=30)
expects = sorted(
dir(dict())
+ ["a", "b", "c"]
+ ["__dict__", "__getattr__", "__module__", "__weakref__"]
)
assert dir(d) == expects

0 comments on commit aee0301

Please sign in to comment.