diff --git a/README.md b/README.md
index 3624063..247d19d 100644
--- a/README.md
+++ b/README.md
@@ -46,9 +46,9 @@ data = {
}
```
-|  |  |
+|  |  |
|--|--|
-|  |
+|  |
## Installation
**NestedFetch** works with Python3.
You can directly install it via **pip**
diff --git a/asset/after.png b/asset/after.png
new file mode 100644
index 0000000..1f4f92b
Binary files /dev/null and b/asset/after.png differ
diff --git a/asset/before.png b/asset/before.png
new file mode 100644
index 0000000..8adc497
Binary files /dev/null and b/asset/before.png differ
diff --git a/nestedfetch/__init__.py b/nestedfetch/__init__.py
index ad1c7fd..5bfc4a3 100644
--- a/nestedfetch/__init__.py
+++ b/nestedfetch/__init__.py
@@ -1 +1 @@
-from .nested_fetch import nested_get, nested_set, flatten_data
\ No newline at end of file
+from .nested_fetch import nested_get, nested_set, flatten_data
diff --git a/nestedfetch/nested_fetch.py b/nestedfetch/nested_fetch.py
index 2fbfeeb..01129e9 100644
--- a/nestedfetch/nested_fetch.py
+++ b/nestedfetch/nested_fetch.py
@@ -1,44 +1,45 @@
import itertools
+
def flatten_data(data):
"""
- @Arguments:
+ @Arguments:
- data : list
+ data : list
- @Return:
+ @Return:
- Returns the flattened list
+ Returns the flattened list
"""
- if isinstance(data,list):
- while(any(isinstance(o, list) for o in data)):
- data = list(itertools.chain.from_iterable(data))
- return data
+ if isinstance(data, list):
+ while any(isinstance(o, list) for o in data):
+ data = list(itertools.chain.from_iterable(data))
+ return data
def nested_get(data, keys, default=None, flatten=False):
- '''
- @Arguments:
+ """
+ @Arguments:
- data : dict / list
+ data : dict / list
- keys => List of sequential keys leading to the desired value to fetch
+ keys => List of sequential keys leading to the desired value to fetch
- default => Specifies the default value to be returned if any specified key is not present.
- If not specified, it will be None
+ default => Specifies the default value to be returned if any specified key is not present.
+ If not specified, it will be None
- flatten => Specifies whether to flatten the returned value
+ flatten => Specifies whether to flatten the returned value
- @Return:
+ @Return:
- Returns the fetched value if it exists, or returns specified default value
- '''
+ Returns the fetched value if it exists, or returns specified default value
+ """
return {
- True : lambda: flatten_data(_nested_get(data,keys,default)),
- False : lambda: _nested_get(data,keys,default)
- }.get(flatten, lambda : None)()
+ True: lambda: flatten_data(_nested_get(data, keys, default)),
+ False: lambda: _nested_get(data, keys, default),
+ }.get(flatten, lambda: None)()
def _nested_get(data, keys, default):
@@ -48,14 +49,28 @@ def _nested_get(data, keys, default):
if isinstance(value, list):
if isinstance(key, int):
if any(isinstance(o, list) for o in value):
- value = list(map((lambda o: default if (key >= len(o)) else o[key]), value))
+ value = list(
+ map(
+ (lambda o: default if (key >= len(o)) else o[key]),
+ value,
+ )
+ )
else:
value = value[key]
else:
- value = list(map((lambda o: default if o == default else _nested_get(o, [key], default)), value))
+ value = list(
+ map(
+ (
+ lambda o: default
+ if o == default
+ else _nested_get(o, [key], default)
+ ),
+ value,
+ )
+ )
else:
value = dict.get(value, key, default)
-
+
if value == default:
break
return value
@@ -63,23 +78,23 @@ def _nested_get(data, keys, default):
return default
-def nested_set(data, keys, value, create_missing=False, _count = 0):
+def nested_set(data, keys, value, create_missing=False, _count=0):
"""
- @Arguments:
+ @Arguments:
- data => dict / list
+ data => dict / list
- keys => List of sequential keys leading to the desired value to set / update
+ keys => List of sequential keys leading to the desired value to set / update
- value => Specifies the value to set / update
+ value => Specifies the value to set / update
- create_missing => Specifies whether to create new key while building up if the specified key does not exists
+ create_missing => Specifies whether to create new key while building up if the specified key does not exists
- @Return:
+ @Return:
- Returns the number of values updated
+ Returns the number of values updated
"""
d = data
count = _count
@@ -88,21 +103,38 @@ def nested_set(data, keys, value, create_missing=False, _count = 0):
if key in d:
d = d[key]
if isinstance(d, list):
- if (itr != len(keys)-1) and (isinstance(keys[itr+1], int)):
- if (itr == len(keys)-2):
+ if (itr != len(keys) - 1) and (isinstance(keys[itr + 1], int)):
+ if itr == len(keys) - 2:
d[keys[-1]] = value
count += 1
else:
- d = d[keys[itr+1]]
- count = nested_set(d, keys[itr+2:], value, create_missing, _count= count)
+ d = d[keys[itr + 1]]
+ count = nested_set(
+ d, keys[itr + 2 :], value, create_missing, _count=count
+ )
else:
- count = sum(list(map((lambda o: nested_set(o,keys[itr+1:],value,create_missing,_count = count)),d)))
+ count = sum(
+ list(
+ map(
+ (
+ lambda o: nested_set(
+ o,
+ keys[itr + 1 :],
+ value,
+ create_missing,
+ _count=count,
+ )
+ ),
+ d,
+ )
+ )
+ )
return count
elif create_missing:
d = d.setdefault(key, {})
else:
return count
- if (keys[-1] in d or create_missing):
+ if keys[-1] in d or create_missing:
d[keys[-1]] = value
return count + 1
elif (isinstance(keys[-1], int)) and isinstance(d, list):
@@ -112,4 +144,3 @@ def nested_set(data, keys, value, create_missing=False, _count = 0):
return count
except Exception as e:
return count
-
diff --git a/setup.py b/setup.py
index ceca5b2..2f9f153 100644
--- a/setup.py
+++ b/setup.py
@@ -1,28 +1,39 @@
from setuptools import setup, find_packages
setup(
- name = 'nestedfetch',
- packages = ['nestedfetch'],
- version = '0.1.2',
- license='MIT',
- description = 'Syntactic sugar inspired by XPath to GET, SET, UPDATE and FLATTEN values from nested dictionaries and nested lists',
- long_description=open("README.md").read(),
- long_description_content_type='text/markdown',
- author = 'Shubham Dalvi',
- author_email = 'shubham.dalvi97@gmail.com',
- url = 'https://github.com/saintlyzero/NestedFetch',
- download_url = ('https://github.com/saintlyzero/NestedFetch/archive/v_012.tar.gz'),
- keywords = ['dict','nested dictionary','nested list','list','flatten','scalpl','nestedfetch','addict','box','Nested Fetch'],
- install_requires=[],
- classifiers=[
- 'Development Status :: 3 - Alpha',
- 'Intended Audience :: Developers',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- 'License :: OSI Approved :: MIT License',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.4',
- 'Programming Language :: Python :: 3.5',
- 'Programming Language :: Python :: 3.6',
- "Programming Language :: Python :: 3.7"
- ]
-)
\ No newline at end of file
+ name="nestedfetch",
+ packages=["nestedfetch"],
+ version="0.1.2",
+ license="MIT",
+ description="Syntactic sugar inspired by XPath to GET, SET, UPDATE and FLATTEN values from nested dictionaries and nested lists",
+ long_description=open("README.md").read(),
+ long_description_content_type="text/markdown",
+ author="Shubham Dalvi",
+ author_email="shubham.dalvi97@gmail.com",
+ url="https://github.com/saintlyzero/NestedFetch",
+ download_url=("https://github.com/saintlyzero/NestedFetch/archive/v_012.tar.gz"),
+ keywords=[
+ "dict",
+ "nested dictionary",
+ "nested list",
+ "list",
+ "flatten",
+ "scalpl",
+ "nestedfetch",
+ "addict",
+ "box",
+ "Nested Fetch",
+ ],
+ install_requires=[],
+ classifiers=[
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "License :: OSI Approved :: MIT License",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ ],
+)
diff --git a/test_nested_fetch.py b/test_nested_fetch.py
index d54a29d..2a388e4 100644
--- a/test_nested_fetch.py
+++ b/test_nested_fetch.py
@@ -1,186 +1,163 @@
-import unittest
+import unittest
from nestedfetch import nested_get, nested_set, flatten_data
+
class TestNestedFetch(unittest.TestCase):
-
simple_get_data = {
- 'name': 'Jesse Pinkman',
- 'details': {
- 'address':{
- 'city': 'Albuquerque'
- }
- }
- }
-
+ "name": "Jesse Pinkman",
+ "details": {"address": {"city": "Albuquerque"}},
+ }
nested_get_data = {
- 'name': 'Walter White',
- 'details': {
- 'address':[{
- 'city': 'Albuquerque'
- },{
- 'city': 'El Paso'
- }]
- }
- }
-
+ "name": "Walter White",
+ "details": {"address": [{"city": "Albuquerque"}, {"city": "El Paso"}]},
+ }
nested_ll_get_data = {
- 'name': 'Walter White',
- 'details': {
- 'address':[{
- 'city': 'Albuquerque'
- },{
- 'city': 'El Paso'
- },{
- 'state': 'New Mexico'
- }]
- }
+ "name": "Walter White",
+ "details": {
+ "address": [
+ {"city": "Albuquerque"},
+ {"city": "El Paso"},
+ {"state": "New Mexico"},
+ ]
+ },
}
-
+
nested_list_get_data = {
- 'name': 'Walter White',
- 'details': {
- 'address':[[{
- 'city': 'Albuquerque'
- },{
- 'city': 'El Paso'
- }]]
- }
- }
-
+ "name": "Walter White",
+ "details": {"address": [[{"city": "Albuquerque"}, {"city": "El Paso"}]]},
+ }
+
flatten_data = {
"league": "Champions League",
"matches": [
{
- "match_id": "match_1",
- "goals": [
- {
- "time": 13,
- "scorrer": "Lionel Messi",
- "assist": "Luis Suarez",
- "details": [
+ "match_id": "match_1",
+ "goals": [
{
- "position": "outside-box"
+ "time": 13,
+ "scorrer": "Lionel Messi",
+ "assist": "Luis Suarez",
+ "details": [
+ {"position": "outside-box"},
+ {"position": "right-side"},
+ ],
},
{
- "position": "right-side"
- }
- ]
- },
- {
- "time": 78,
- "scorrer": "Luis Suarez",
- "assist": "Ivan Rakitic",
- "details": [
- {
- "position": "inside-box"
+ "time": 78,
+ "scorrer": "Luis Suarez",
+ "assist": "Ivan Rakitic",
+ "details": [
+ {"position": "inside-box"},
+ {"position": "left-side"},
+ ],
},
- {
- "position": "left-side"
- }
- ]
- }
- ]
+ ],
},
{
- "match_id": "match_2",
- "goals": [
- {
- "time": 36,
- "scorrer": "C. Ronaldo",
- "assist": "Luka Modric",
- "details": [
- {
- "position": "penalty"
- },
+ "match_id": "match_2",
+ "goals": [
{
- "position": "d-box"
+ "time": 36,
+ "scorrer": "C. Ronaldo",
+ "assist": "Luka Modric",
+ "details": [{"position": "penalty"}, {"position": "d-box"}],
}
- ]
- }
- ]
- }
- ]
- }
+ ],
+ },
+ ],
+ }
- flatten_test_data = [
- ['This','is'],
- ['flattened', 'data']
- ]
+ flatten_test_data = [["This", "is"], ["flattened", "data"]]
- flatten_nested_data = [[
- ['This','is'],
- ['flattened', 'data']
- ]]
+ flatten_nested_data = [[["This", "is"], ["flattened", "data"]]]
def test_simple_get_success(self):
- res = nested_get(self.simple_get_data,['details','address','city'])
- self.assertEqual(res, 'Albuquerque')
-
+ res = nested_get(self.simple_get_data, ["details", "address", "city"])
+ self.assertEqual(res, "Albuquerque")
def test_nested_get_all_success(self):
- res = nested_get(self.nested_get_data,['details','address','city'])
- self.assertEqual(res, ['Albuquerque','El Paso'])
-
+ res = nested_get(self.nested_get_data, ["details", "address", "city"])
+ self.assertEqual(res, ["Albuquerque", "El Paso"])
def test_nested_ll_get_all_success(self):
- res = nested_get(self.nested_ll_get_data,['details','address','city'], default= None)
- self.assertEqual(res, ['Albuquerque','El Paso', None])
-
+ res = nested_get(
+ self.nested_ll_get_data, ["details", "address", "city"], default=None
+ )
+ self.assertEqual(res, ["Albuquerque", "El Paso", None])
def test_nested_get_with_index_success(self):
- res = nested_get(self.nested_get_data,['details','address','city', 0])
- self.assertEqual(res, 'Albuquerque')
-
+ res = nested_get(self.nested_get_data, ["details", "address", "city", 0])
+ self.assertEqual(res, "Albuquerque")
def test_nested_list_get_with_index_success(self):
- res = nested_get(self.nested_list_get_data,['details','address',0,0])
- self.assertEqual(res, {'city': 'Albuquerque'})
-
+ res = nested_get(self.nested_list_get_data, ["details", "address", 0, 0])
+ self.assertEqual(res, {"city": "Albuquerque"})
def test_nested_get_with_index_error(self):
- res = nested_get(self.nested_get_data,['details','address','city', 5], default=None)
- self.assertEqual(res, None)
-
+ res = nested_get(
+ self.nested_get_data, ["details", "address", "city", 5], default=None
+ )
+ self.assertEqual(res, None)
def test_nested_get_flatten(self):
- res = nested_get(self.flatten_data,['matches','goals','scorrer'], default=None, flatten=True)
- self.assertEqual(res, ['Lionel Messi', 'Luis Suarez', 'C. Ronaldo'])
-
+ res = nested_get(
+ self.flatten_data,
+ ["matches", "goals", "scorrer"],
+ default=None,
+ flatten=True,
+ )
+ self.assertEqual(res, ["Lionel Messi", "Luis Suarez", "C. Ronaldo"])
def test_nested_get_ll_flatten(self):
- res = nested_get(self.flatten_data,['matches','goals','details'], default=None, flatten=True)
- self.assertEqual(res, [{'position': 'outside-box'}, {'position': 'right-side'}, {'position': 'inside-box'}, {'position': 'left-side'}, {'position': 'penalty'}, {'position': 'd-box'}])
-
+ res = nested_get(
+ self.flatten_data,
+ ["matches", "goals", "details"],
+ default=None,
+ flatten=True,
+ )
+ self.assertEqual(
+ res,
+ [
+ {"position": "outside-box"},
+ {"position": "right-side"},
+ {"position": "inside-box"},
+ {"position": "left-side"},
+ {"position": "penalty"},
+ {"position": "d-box"},
+ ],
+ )
def test_simple_set_success(self):
- res = nested_set(self.simple_get_data,['details','address','city'], "Denver")
- self.assertEqual(res, 1)
-
+ res = nested_set(self.simple_get_data, ["details", "address", "city"], "Denver")
+ self.assertEqual(res, 1)
def test_simple_set_build_success(self):
- res = nested_set(self.simple_get_data,['details','address','state'], "New Mexico", create_missing=True)
- self.assertEqual(res, 1)
- self.assertEqual(self.simple_get_data, {
- 'name':'Jesse Pinkman',
- 'details': {
- 'address':{
- 'city':'Albuquerque',
- 'state': 'New Mexico'
- }}})
+ res = nested_set(
+ self.simple_get_data,
+ ["details", "address", "state"],
+ "New Mexico",
+ create_missing=True,
+ )
+ self.assertEqual(res, 1)
+ self.assertEqual(
+ self.simple_get_data,
+ {
+ "name": "Jesse Pinkman",
+ "details": {"address": {"city": "Albuquerque", "state": "New Mexico"}},
+ },
+ )
def test_simple_flatten(self):
- res = flatten_data(self.flatten_test_data)
- self.assertEqual(res, ['This','is','flattened','data'])
-
+ res = flatten_data(self.flatten_test_data)
+ self.assertEqual(res, ["This", "is", "flattened", "data"])
def test_nested_flatten(self):
- res = flatten_data(self.flatten_nested_data)
- self.assertEqual(res, ['This','is','flattened','data'])
-
+ res = flatten_data(self.flatten_nested_data)
+ self.assertEqual(res, ["This", "is", "flattened", "data"])
if __name__ == "__main__":
- unittest.main()
\ No newline at end of file
+ unittest.main()