Skip to content

Commit

Permalink
Added BaseDict to keep pointer to the initial input dict. #32
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiocaccamo committed Sep 17, 2020
1 parent ac3895a commit eac655b
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 19 deletions.
3 changes: 3 additions & 0 deletions benedict/dicts/base/__init__.py
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-

from benedict.dicts.base.base_dict import BaseDict
75 changes: 75 additions & 0 deletions benedict/dicts/base/base_dict.py
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-

from benedict.utils import type_util


class BaseDict(dict):

_dict = {}

def __init__(self, *args, **kwargs):
super(BaseDict, self).__init__()
if len(args) == 1 and type_util.is_dict(args[0]):
self._dict = args[0]
else:
self._dict = dict(*args, **kwargs)

def __bool__(self):
return bool(self._dict)

def __contains__(self, key):
return key in self._dict

def __delitem__(self, key):
del self._dict[key]

def __eq__(self, other):
return self._dict == other

def __getitem__(self, key):
return self._dict[key]

def __iter__(self):
return iter(self._dict)

def __len__(self):
return len(self._dict)

def __repr__(self):
return repr(self._dict)

def __setitem__(self, key, value):
self._dict[key] = value

def __str__(self):
return str(self._dict)

def clear(self):
self._dict.clear()

def copy(self):
return self._dict.copy()

def dict(self):
return self._dict

def get(self, key, default=None):
return self._dict.get(key, default)

def items(self):
return self._dict.items()

def keys(self):
return self._dict.keys()

def pop(self, key, *args):
return self._dict.pop(key, *args)

def setdefault(self, key, default=None):
return self._dict.setdefault(key, default)

def update(self, other):
self._dict.update(other)

def values(self):
return self._dict.values()
19 changes: 10 additions & 9 deletions benedict/dicts/io/io_dict.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-

from benedict.dicts.base import BaseDict
from benedict.dicts.io import io_util
from benedict.utils import type_util


class IODict(dict):
class IODict(BaseDict):

def __init__(self, *args, **kwargs):
"""
Expand Down Expand Up @@ -158,7 +159,7 @@ def to_base64(self, subformat='json', encoding='utf-8', **kwargs):
"""
kwargs['subformat'] = subformat
kwargs['encoding'] = encoding
return self._encode(self, 'base64', **kwargs)
return self._encode(self._dict, 'base64', **kwargs)

def to_csv(self, key='values', columns=None, columns_row=True, **kwargs):
"""
Expand All @@ -180,7 +181,7 @@ def to_json(self, **kwargs):
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'json', **kwargs)
return self._encode(self._dict, 'json', **kwargs)

def to_pickle(self, **kwargs):
"""
Expand All @@ -191,7 +192,7 @@ def to_pickle(self, **kwargs):
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'pickle', **kwargs)
return self._encode(self._dict, 'pickle', **kwargs)

def to_plist(self, **kwargs):
"""
Expand All @@ -201,15 +202,15 @@ def to_plist(self, **kwargs):
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'plist', **kwargs)
return self._encode(self._dict, 'plist', **kwargs)

def to_query_string(self, **kwargs):
"""
Encode the current dict instance in query-string format.
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'query_string', **kwargs)
return self._encode(self._dict, 'query_string', **kwargs)

def to_toml(self, **kwargs):
"""
Expand All @@ -219,7 +220,7 @@ def to_toml(self, **kwargs):
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'toml', **kwargs)
return self._encode(self._dict, 'toml', **kwargs)

def to_xml(self, **kwargs):
"""
Expand All @@ -229,7 +230,7 @@ def to_xml(self, **kwargs):
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'xml', **kwargs)
return self._encode(self._dict, 'xml', **kwargs)

def to_yaml(self, **kwargs):
"""
Expand All @@ -239,4 +240,4 @@ def to_yaml(self, **kwargs):
Return the encoded string and optionally save it at 'filepath'.
A ValueError is raised in case of failure.
"""
return self._encode(self, 'yaml', **kwargs)
return self._encode(self._dict, 'yaml', **kwargs)
3 changes: 2 additions & 1 deletion benedict/dicts/keylist/keylist_dict.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-

from benedict.dicts.base import BaseDict
from benedict.dicts.keylist import keylist_util
from benedict.utils import type_util


class KeylistDict(dict):
class KeylistDict(BaseDict):

def __init__(self, *args, **kwargs):
super(KeylistDict, self).__init__(*args, **kwargs)
Expand Down
3 changes: 2 additions & 1 deletion benedict/dicts/parse/parse_dict.py
@@ -1,12 +1,13 @@
# -*- coding: utf-8 -*-

from benedict.dicts.base import BaseDict
from benedict.dicts.parse import parse_util
from benedict.utils import type_util

from decimal import Decimal


class ParseDict(dict):
class ParseDict(BaseDict):

def __init__(self, *args, **kwargs):
"""
Expand Down
6 changes: 3 additions & 3 deletions tests/dicts/test_benedict.py
Expand Up @@ -20,7 +20,7 @@ def test_clean(self):
'g': None,
'h': '0'
}
bd = benedict(d)
bd = benedict(d.copy())
bd.clean()
r = {
'b': { 'x': 1 },
Expand All @@ -30,7 +30,7 @@ def test_clean(self):
}
self.assertEqual(bd, r)

bd = benedict(d)
bd = benedict(d.copy())
bd.clean(collections=False)
r = {
'a': {},
Expand All @@ -42,7 +42,7 @@ def test_clean(self):
}
self.assertEqual(bd, r)

bd = benedict(d)
bd = benedict(d.copy())
bd.clean(strings=False)
r = {
'b': { 'x': 1 },
Expand Down
10 changes: 5 additions & 5 deletions tests/github/test_issue_0025.py
Expand Up @@ -3,6 +3,7 @@
from benedict import benedict

import unittest
import yaml


class github_issue_0025_test_case(unittest.TestCase):
Expand Down Expand Up @@ -31,14 +32,12 @@ def load_dict():
floar: s01_floar
room: s01_room
"""
servers = benedict.from_yaml(yaml_str)
# print(servers.dump())
return dict(servers)
servers = yaml.safe_load(yaml_str)
return servers

# @unittest.skip('testing main_dict and pointers failure')
def test_pointers_with_dict(self):
servers = dict(self.load_dict())
# s01_ptr=dict(servers['SERVER']['S01'])
s01_ptr=servers['SERVER']['S01']
s01_ptr['alias']='ptr_alias'
s01_ptr['location']['building']='ptr_building'
Expand All @@ -48,8 +47,9 @@ def test_pointers_with_dict(self):
# @unittest.skip('testing copy and pointers failure')
def test_pointers_with_benedict_casting(self):
servers = benedict(self.load_dict())
# s01_ptr=benedict(servers['SERVER.S01'])
s01_ptr=servers['SERVER.S01']
self.assertTrue(isinstance(s01_ptr, benedict))
self.assertEqual(type(s01_ptr), benedict)
s01_ptr['alias']='ptr_alias'
s01_ptr['location']['building']='ptr_building'
s01_ptr['credentials']['username']='ptr_unsername'
Expand Down
46 changes: 46 additions & 0 deletions tests/github/test_issue_0032.py
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-

from benedict import benedict

import unittest


class github_issue_0032_test_case(unittest.TestCase):

"""
https://github.com/fabiocaccamo/python-benedict/issues/32
To run this specific test:
- For each method comment @unittest.skip decorator
- Run python -m unittest tests.github.test_issue_0032
"""

@staticmethod
def load_dict():
return {
'a': {
'b': {
'c': {
'd': 10,
},
'x': 100,
}
}
}

def test_pointers_with_dict(self):
b = benedict(self.load_dict())
ab = benedict(b['a.b'])
ab['c']['d'] = 20
ab['x'] = 200
r = {
'a': {
'b': {
'c': {
'd': 20,
},
'x': 200,
}
}
}
self.assertEqual(b, r)

0 comments on commit eac655b

Please sign in to comment.