running black on files and updating docs.
modified: README.rst modified: nested_lookup/nested_lookup.py modified: test_nested_loopkup.py
This commit is contained in:
parent
7260463455
commit
0d17bb8c7f
3 changed files with 84 additions and 99 deletions
52
README.rst
52
README.rst
|
|
@ -5,8 +5,9 @@ nested_lookup
|
||||||
:target: https://pypi.python.org/pypi/nested-lookup
|
:target: https://pypi.python.org/pypi/nested-lookup
|
||||||
|
|
||||||
A small Python library which enables:
|
A small Python library which enables:
|
||||||
1. key lookups on deeply nested documents.
|
|
||||||
2. fetching all keys from a nested dictionary.
|
#. key lookups on deeply nested documents.
|
||||||
|
#. fetching all keys from a nested dictionary.
|
||||||
|
|
||||||
Documents may be built out of dictionaries (dicts) and/or lists.
|
Documents may be built out of dictionaries (dicts) and/or lists.
|
||||||
|
|
||||||
|
|
@ -78,7 +79,21 @@ For example, given the following document:
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
We could act `wild` and find all the email addresses like this:
|
To get a list of every nested key in a document, run this:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from nested_lookup import get_all_keys
|
||||||
|
|
||||||
|
keys = get_all_keys(my_document)
|
||||||
|
|
||||||
|
print(keys)
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
['name', 'email_address', 'other', 'secondary_email', 'EMAIL_RECOVERY', 'email_address']
|
||||||
|
|
||||||
|
Next, we could act `wild` and find all the email addresses like this:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
@ -116,36 +131,6 @@ Additionally, if you also needed the matched key names, you could do this:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Tutorial to get all keys from a nested dictionary
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
sample_data = {
|
|
||||||
"hardware_details": {
|
|
||||||
"model_name": "MacBook Pro",
|
|
||||||
"processor_details": {
|
|
||||||
"processor_name": "Intel Core i7",
|
|
||||||
"processor_speed": "2.7 GHz",
|
|
||||||
"core_details": {
|
|
||||||
"total_numberof_cores": "4",
|
|
||||||
"l2_cache(per_core)": "256 KB"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"total_number_of_cores": "4",
|
|
||||||
"memory": "16 GB",
|
|
||||||
},
|
|
||||||
"os_details": {
|
|
||||||
"product_version": "10.13.6",
|
|
||||||
"build_version": "17G65"
|
|
||||||
},
|
|
||||||
"name": "Test",
|
|
||||||
"date": "YYYY-MM-DD HH:MM:SS"
|
|
||||||
}
|
|
||||||
|
|
||||||
result = get_all_keys(sample_data)
|
|
||||||
|
|
||||||
print(result)
|
|
||||||
|
|
||||||
misc
|
misc
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|
@ -155,6 +140,7 @@ misc
|
||||||
:authors:
|
:authors:
|
||||||
* Russell Ballestrini
|
* Russell Ballestrini
|
||||||
* Douglas Miranda
|
* Douglas Miranda
|
||||||
|
* Ramesh RV
|
||||||
|
|
||||||
:web:
|
:web:
|
||||||
* http://russell.ballestrini.net
|
* http://russell.ballestrini.net
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from six import iteritems
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
def nested_lookup(key, document, wild=False, with_keys=False):
|
def nested_lookup(key, document, wild=False, with_keys=False):
|
||||||
"""Lookup a key in a nested document, return a list of values"""
|
"""Lookup a key in a nested document, return a list of values"""
|
||||||
if with_keys:
|
if with_keys:
|
||||||
|
|
@ -11,6 +12,7 @@ def nested_lookup(key, document, wild=False, with_keys=False):
|
||||||
return d
|
return d
|
||||||
return list(_nested_lookup(key, document, wild=wild, with_keys=with_keys))
|
return list(_nested_lookup(key, document, wild=wild, with_keys=with_keys))
|
||||||
|
|
||||||
|
|
||||||
def _nested_lookup(key, document, wild=False, with_keys=False):
|
def _nested_lookup(key, document, wild=False, with_keys=False):
|
||||||
"""Lookup a key in a nested document, yield a value"""
|
"""Lookup a key in a nested document, yield a value"""
|
||||||
if isinstance(document, list):
|
if isinstance(document, list):
|
||||||
|
|
@ -30,7 +32,9 @@ def _nested_lookup(key, document, wild=False, with_keys=False):
|
||||||
yield result
|
yield result
|
||||||
elif isinstance(v, list):
|
elif isinstance(v, list):
|
||||||
for d in v:
|
for d in v:
|
||||||
for result in _nested_lookup(key, d, wild=wild, with_keys=with_keys):
|
for result in _nested_lookup(
|
||||||
|
key, d, wild=wild, with_keys=with_keys
|
||||||
|
):
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,75 +6,70 @@ from nested_lookup import nested_lookup, get_all_keys
|
||||||
class TestNestedLookup(TestCase):
|
class TestNestedLookup(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.subject_dict = {'a':1,'b':{'d':100},'c':{'d':200}}
|
self.subject_dict = {"a": 1, "b": {"d": 100}, "c": {"d": 200}}
|
||||||
self.subject_dict2 = {
|
self.subject_dict2 = {
|
||||||
'name' : 'Russell Ballestrini',
|
"name": "Russell Ballestrini",
|
||||||
'email_address' : 'test1@example.com',
|
"email_address": "test1@example.com",
|
||||||
'other' : {
|
"other": {
|
||||||
'secondary_email' : 'test2@example.com',
|
"secondary_email": "test2@example.com",
|
||||||
'EMAIL_RECOVERY' : 'test3@example.com',
|
"EMAIL_RECOVERY": "test3@example.com",
|
||||||
'email_address' : 'test4@example.com',
|
"email_address": "test4@example.com",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_nested_lookup(self):
|
def test_nested_lookup(self):
|
||||||
results = nested_lookup('d', self.subject_dict)
|
results = nested_lookup("d", self.subject_dict)
|
||||||
self.assertEqual(2, len(results))
|
self.assertEqual(2, len(results))
|
||||||
self.assertIn(100, results)
|
self.assertIn(100, results)
|
||||||
self.assertIn(200, results)
|
self.assertIn(200, results)
|
||||||
self.assertSetEqual({100,200}, set(results))
|
self.assertSetEqual({100, 200}, set(results))
|
||||||
|
|
||||||
def test_nested_lookup_wrapped_in_list(self):
|
def test_nested_lookup_wrapped_in_list(self):
|
||||||
results = nested_lookup('d', [{}, self.subject_dict, {}])
|
results = nested_lookup("d", [{}, self.subject_dict, {}])
|
||||||
self.assertEqual(2, len(results))
|
self.assertEqual(2, len(results))
|
||||||
self.assertIn(100, results)
|
self.assertIn(100, results)
|
||||||
self.assertIn(200, results)
|
self.assertIn(200, results)
|
||||||
self.assertSetEqual({100,200}, set(results))
|
self.assertSetEqual({100, 200}, set(results))
|
||||||
|
|
||||||
def test_nested_lookup_wrapped_in_list_in_dict_in_list(self):
|
def test_nested_lookup_wrapped_in_list_in_dict_in_list(self):
|
||||||
results = nested_lookup('d', [{}, {'H' : [self.subject_dict]} ])
|
results = nested_lookup("d", [{}, {"H": [self.subject_dict]}])
|
||||||
self.assertEqual(2, len(results))
|
self.assertEqual(2, len(results))
|
||||||
self.assertIn(100, results)
|
self.assertIn(100, results)
|
||||||
self.assertIn(200, results)
|
self.assertIn(200, results)
|
||||||
self.assertSetEqual({100,200}, set(results))
|
self.assertSetEqual({100, 200}, set(results))
|
||||||
|
|
||||||
def test_nested_lookup_wrapped_in_list_in_list(self):
|
def test_nested_lookup_wrapped_in_list_in_list(self):
|
||||||
results = nested_lookup('d', [ {}, [self.subject_dict, {}] ])
|
results = nested_lookup("d", [{}, [self.subject_dict, {}]])
|
||||||
self.assertEqual(2, len(results))
|
self.assertEqual(2, len(results))
|
||||||
self.assertIn(100, results)
|
self.assertIn(100, results)
|
||||||
self.assertIn(200, results)
|
self.assertIn(200, results)
|
||||||
self.assertSetEqual({100,200}, set(results))
|
self.assertSetEqual({100, 200}, set(results))
|
||||||
|
|
||||||
def test_wild_nested_lookup(self):
|
def test_wild_nested_lookup(self):
|
||||||
results = nested_lookup(
|
results = nested_lookup(key="mail", document=self.subject_dict2, wild=True)
|
||||||
key = 'mail',
|
|
||||||
document = self.subject_dict2
|
|
||||||
wild = True,
|
|
||||||
)
|
|
||||||
self.assertEqual(4, len(results))
|
self.assertEqual(4, len(results))
|
||||||
self.assertIn('test1@example.com', results)
|
self.assertIn("test1@example.com", results)
|
||||||
self.assertIn('test2@example.com', results)
|
self.assertIn("test2@example.com", results)
|
||||||
self.assertIn('test3@example.com', results)
|
self.assertIn("test3@example.com", results)
|
||||||
|
|
||||||
def test_wild_with_keys_nested_lookup(self):
|
def test_wild_with_keys_nested_lookup(self):
|
||||||
matches = nested_lookup(
|
matches = nested_lookup(
|
||||||
key = 'mail',
|
key="mail", document=self.subject_dict2, wild=True, with_keys=True
|
||||||
document = self.subject_dict2,
|
|
||||||
wild = True,
|
|
||||||
with_keys = True,
|
|
||||||
)
|
)
|
||||||
self.assertEqual(3, len(matches))
|
self.assertEqual(3, len(matches))
|
||||||
self.assertIn('email_address', matches)
|
self.assertIn("email_address", matches)
|
||||||
self.assertIn('secondary_email', matches)
|
self.assertIn("secondary_email", matches)
|
||||||
self.assertIn('EMAIL_RECOVERY', matches)
|
self.assertIn("EMAIL_RECOVERY", matches)
|
||||||
self.assertSetEqual({'test1@example.com','test4@example.com'}, set(matches['email_address']))
|
self.assertSetEqual(
|
||||||
self.assertIn('test2@example.com', matches['secondary_email'])
|
{"test1@example.com", "test4@example.com"}, set(matches["email_address"])
|
||||||
|
)
|
||||||
|
self.assertIn("test2@example.com", matches["secondary_email"])
|
||||||
|
|
||||||
def test_nested_lookup_with_keys(self):
|
def test_nested_lookup_with_keys(self):
|
||||||
matches = nested_lookup('d', self.subject_dict, with_keys=True)
|
matches = nested_lookup("d", self.subject_dict, with_keys=True)
|
||||||
self.assertIn('d', matches)
|
self.assertIn("d", matches)
|
||||||
self.assertEqual(2, len(matches['d']))
|
self.assertEqual(2, len(matches["d"]))
|
||||||
self.assertSetEqual({100,200}, set(matches['d']))
|
self.assertSetEqual({100, 200}, set(matches["d"]))
|
||||||
|
|
||||||
|
|
||||||
class TestGetAllKeys(TestCase):
|
class TestGetAllKeys(TestCase):
|
||||||
|
|
@ -88,30 +83,29 @@ class TestGetAllKeys(TestCase):
|
||||||
"processor_speed": "2.7 GHz",
|
"processor_speed": "2.7 GHz",
|
||||||
"core_details": {
|
"core_details": {
|
||||||
"total_numberof_cores": "4",
|
"total_numberof_cores": "4",
|
||||||
"l2_cache(per_core)": "256 KB"
|
"l2_cache(per_core)": "256 KB",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
"total_number_of_cores": "4",
|
"total_number_of_cores": "4",
|
||||||
"memory": "16 GB",
|
"memory": "16 GB",
|
||||||
},
|
},
|
||||||
"os_details": {
|
"os_details": {"product_version": "10.13.6", "build_version": "17G65"},
|
||||||
"product_version": "10.13.6",
|
|
||||||
"build_version": "17G65"
|
|
||||||
},
|
|
||||||
"name": "Test",
|
"name": "Test",
|
||||||
"date": "YYYY-MM-DD HH:MM:SS"
|
"date": "YYYY-MM-DD HH:MM:SS",
|
||||||
}
|
}
|
||||||
self.sample2 = {
|
self.sample2 = {
|
||||||
"hardware_details": {
|
"hardware_details": {
|
||||||
"model_name": "MacBook Pro",
|
"model_name": "MacBook Pro",
|
||||||
"processor_details": [{
|
"processor_details": [
|
||||||
"processor_name": "Intel Core i7",
|
{
|
||||||
"processor_speed": "2.7 GHz",
|
"processor_name": "Intel Core i7",
|
||||||
"core_details": {
|
"processor_speed": "2.7 GHz",
|
||||||
"total_numberof_cores": "4",
|
"core_details": {
|
||||||
"l2_cache(per_core)": "256 KB"
|
"total_numberof_cores": "4",
|
||||||
|
"l2_cache(per_core)": "256 KB",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}],
|
],
|
||||||
"total_number_of_cores": "4",
|
"total_number_of_cores": "4",
|
||||||
"memory": "16 GB",
|
"memory": "16 GB",
|
||||||
}
|
}
|
||||||
|
|
@ -120,14 +114,8 @@ class TestGetAllKeys(TestCase):
|
||||||
"hardware_details": {
|
"hardware_details": {
|
||||||
"model_name": "MacBook Pro",
|
"model_name": "MacBook Pro",
|
||||||
"processor_details": [
|
"processor_details": [
|
||||||
{
|
{"processor_name": "Intel Core i7", "processor_speed": "2.7 GHz"},
|
||||||
"processor_name": "Intel Core i7",
|
{"total_numberof_cores": "4", "l2_cache(per_core)": "256 KB"},
|
||||||
"processor_speed": "2.7 GHz",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"total_numberof_cores": "4",
|
|
||||||
"l2_cache(per_core)": "256 KB"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"total_number_of_cores": "4",
|
"total_number_of_cores": "4",
|
||||||
"memory": "16 GB",
|
"memory": "16 GB",
|
||||||
|
|
@ -138,8 +126,11 @@ class TestGetAllKeys(TestCase):
|
||||||
result = get_all_keys(self.sample1)
|
result = get_all_keys(self.sample1)
|
||||||
self.assertEqual(15, len(result))
|
self.assertEqual(15, len(result))
|
||||||
keys_to_verify = [
|
keys_to_verify = [
|
||||||
'model_name', 'core_details', 'l2_cache(per_core)',
|
"model_name",
|
||||||
'build_version', 'date'
|
"core_details",
|
||||||
|
"l2_cache(per_core)",
|
||||||
|
"build_version",
|
||||||
|
"date",
|
||||||
]
|
]
|
||||||
for key in keys_to_verify:
|
for key in keys_to_verify:
|
||||||
self.assertIn(key, result)
|
self.assertIn(key, result)
|
||||||
|
|
@ -148,8 +139,10 @@ class TestGetAllKeys(TestCase):
|
||||||
result = get_all_keys(self.sample2)
|
result = get_all_keys(self.sample2)
|
||||||
self.assertEqual(10, len(result))
|
self.assertEqual(10, len(result))
|
||||||
keys_to_verify = [
|
keys_to_verify = [
|
||||||
'hardware_details', 'processor_speed',
|
"hardware_details",
|
||||||
'total_numberof_cores', 'memory'
|
"processor_speed",
|
||||||
|
"total_numberof_cores",
|
||||||
|
"memory",
|
||||||
]
|
]
|
||||||
for key in keys_to_verify:
|
for key in keys_to_verify:
|
||||||
self.assertIn(key, result)
|
self.assertIn(key, result)
|
||||||
|
|
@ -158,12 +151,14 @@ class TestGetAllKeys(TestCase):
|
||||||
result = get_all_keys(self.sample3)
|
result = get_all_keys(self.sample3)
|
||||||
self.assertEqual(9, len(result))
|
self.assertEqual(9, len(result))
|
||||||
keys_to_verify = [
|
keys_to_verify = [
|
||||||
'processor_details', 'processor_name',
|
"processor_details",
|
||||||
'l2_cache(per_core)', 'total_number_of_cores'
|
"processor_name",
|
||||||
|
"l2_cache(per_core)",
|
||||||
|
"total_number_of_cores",
|
||||||
]
|
]
|
||||||
for key in keys_to_verify:
|
for key in keys_to_verify:
|
||||||
self.assertIn(key, result)
|
self.assertIn(key, result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue