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:
russellballestrini 2018-09-25 17:16:04 -04:00
parent 7260463455
commit 0d17bb8c7f
3 changed files with 84 additions and 99 deletions

View file

@ -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

View file

@ -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

View file

@ -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