diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..edfc4fd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: python +python: + - "2.7" + - "3.5" + - "3.6" +# command to install dependencies +install: + - pip install . +# command to run tests +script: pytest \ No newline at end of file diff --git a/README.rst b/README.rst index 903ac7f..e5a4922 100644 --- a/README.rst +++ b/README.rst @@ -1,8 +1,10 @@ nested_lookup ############# -.. image:: https://img.shields.io/badge/pypi-0.2.12-green.svg +.. image:: https://img.shields.io/badge/pypi-0.2.13-green.svg :target: https://pypi.python.org/pypi/nested-lookup +.. image:: https://travis-ci.org/rameshrvr/nested-lookup.svg?branch=master + :target: https://travis-ci.org/rameshrvr/nested-lookup Make working with JSON, YAML, and XML document responses fun again! diff --git a/nested_lookup/lookup_api.py b/nested_lookup/lookup_api.py index e338ae3..1d8f898 100644 --- a/nested_lookup/lookup_api.py +++ b/nested_lookup/lookup_api.py @@ -22,7 +22,7 @@ def _nested_delete(document, key): for list_items in document: _nested_delete(document=list_items, key=key) elif isinstance(document, dict): - if document.get(key): + if document.get(key) is not None: del document[key] for dict_key, dict_value in iteritems(document): _nested_delete(document=dict_value, key=key) @@ -49,7 +49,7 @@ def _nested_update(document, key, value): for list_items in document: _nested_update(document=list_items, key=key, value=value) elif isinstance(document, dict): - if document.get(key): + if document.get(key) is not None: document[key] = value for dict_key, dict_value in iteritems(document): _nested_update(document=dict_value, key=key, value=value) diff --git a/nested_lookup/nested_lookup.py b/nested_lookup/nested_lookup.py index 39787e4..71ac8e4 100644 --- a/nested_lookup/nested_lookup.py +++ b/nested_lookup/nested_lookup.py @@ -113,9 +113,10 @@ def _get_occurrence(dictionary, item, keyword): def recrusion(dictionary): if item == 'key': - occurrence[0] += 1 if dictionary.get(keyword) else 0 - elif keyword in dictionary.values(): - occurrence[0] += dictionary.values().count(keyword) + if dictionary.get(keyword) is not None: + occurrence[0] += 1 + elif keyword in list(dictionary.values()): + occurrence[0] += list(dictionary.values()).count(keyword) for key, value in iteritems(dictionary): if isinstance(value, dict): recrusion(dictionary=value) diff --git a/setup.py b/setup.py index e5d89bd..9c37864 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ with open('requirements.txt', 'r') as f: setup( name='nested-lookup', - version='0.2.12', + version='0.2.13', description='Python functions for working with deeply nested documents (lists and dicts) ', keywords='nested document dictionary dict list lookup schema json xml yaml', long_description=open('README.rst').read(), diff --git a/test_lookup_api.py b/test_lookup_api.py index b2f8b61..6f29eb4 100644 --- a/test_lookup_api.py +++ b/test_lookup_api.py @@ -55,6 +55,14 @@ class BaseLookUpApi(TestCase): }] } + self.sample_data4 = { + "hardware_details": { + "model_name": 'MacBook Pro', + "total_number_of_cores": 0, + "memory": False + } + } + class TestNestedDelete(BaseLookUpApi): def test_sample_data1(self): @@ -87,6 +95,50 @@ class TestNestedDelete(BaseLookUpApi): result, nested_delete(self.sample_data3, 'monitoring_zones') ) + def test_sample_data4(self): + result1 = { + "hardware_details": { + "model_name": 'MacBook Pro', + "memory": False + } + } + self.assertEqual( + result1, nested_delete(self.sample_data4, 'total_number_of_cores') + ) + result2 = { + "hardware_details": { + "model_name": 'MacBook Pro', + "total_number_of_cores": 0 + } + } + self.assertEqual( + result2, nested_delete(self.sample_data4, 'memory') + ) + + def test_nested_delete_in_place_false(self): + """ + nested_delete with in_place argument set to 'False' + should mutate and return a copy of the original document + """ + before_id = id(self.sample_data1) + result = nested_delete( + self.sample_data1, 'build_version', in_place=False) + after_id = id(result) + # the object ids should _not_ match. + self.assertNotEqual(before_id, after_id) + + def test_nested_delete_in_place_true(self): + """ + nested_delete with in_place argument set to 'True' + should mutate and return the original document + """ + before_id = id(self.sample_data1) + result = nested_delete( + self.sample_data1, 'build_version', in_place=True) + after_id = id(result) + # the object ids should match. + self.assertEqual(before_id, after_id) + class TestNestedUpdate(BaseLookUpApi): def test_sample_data1(self): @@ -104,33 +156,25 @@ class TestNestedUpdate(BaseLookUpApi): ) def test_nested_update_in_place_false(self): - """nested_update should mutate and return a copy of the original document""" + """ + nested_update with in_place argument set to 'False' + should mutate and return a copy of the original document + """ before_id = id(self.sample_data1) - result = nested_update(self.sample_data1, 'build_version', 'Test2', in_place=False) + result = nested_update( + self.sample_data1, 'build_version', 'Test2', in_place=False) after_id = id(result) # the object ids should _not_ match. self.assertNotEqual(before_id, after_id) def test_nested_update_in_place_true(self): - """nested_update should mutate and return the original document""" + """ + nested_update with in_place argument set to 'True' + should mutate and return the original document + """ before_id = id(self.sample_data1) - result = nested_update(self.sample_data1, 'build_version', 'Test2', in_place=True) - after_id = id(result) - # the object ids should match. - self.assertEqual(before_id, after_id) - - def test_nested_delete_in_place_false(self): - """nested_delete should mutate and return a copy of the original document""" - before_id = id(self.sample_data1) - result = nested_delete(self.sample_data1, 'build_version', in_place=False) - after_id = id(result) - # the object ids should _not_ match. - self.assertNotEqual(before_id, after_id) - - def test_nested_delete_in_place_true(self): - """nested_delete should mutate and return the original document""" - before_id = id(self.sample_data1) - result = nested_delete(self.sample_data1, 'build_version', in_place=True) + result = nested_update( + self.sample_data1, 'build_version', 'Test2', in_place=True) after_id = id(result) # the object ids should match. self.assertEqual(before_id, after_id) @@ -171,3 +215,30 @@ class TestNestedUpdate(BaseLookUpApi): } ) ) + + def test_sample_data4(self): + result1 = { + "hardware_details": { + "model_name": 'MacBook Pro', + "total_number_of_cores": 1, + "memory": False + } + } + self.assertEqual( + result1, nested_update( + self.sample_data4, key='total_number_of_cores', + value=1 + ) + ) + result2 = { + "hardware_details": { + "model_name": 'MacBook Pro', + "total_number_of_cores": 0, + "memory": True + } + } + self.assertEqual( + result2, nested_update( + self.sample_data4, key='memory', value=True + ) + ) diff --git a/test_nested_lookup.py b/test_nested_lookup.py index cc344b0..5f44f8a 100644 --- a/test_nested_lookup.py +++ b/test_nested_lookup.py @@ -308,6 +308,14 @@ class TestGetOccurrence(TestCase): }] } + self.sample5 = { + "hardware_details": { + "model_name": 'MacBook Pro', + "total_number_of_cores": 0, + "memory": False + } + } + def test_sample_data1(self): result = get_occurrence_of_key(self.sample1, 'build_version') self.assertEqual(4, result) @@ -336,6 +344,15 @@ class TestGetOccurrence(TestCase): 'mziad') self.assertEqual(2, get_occurrence_of_value(self.sample4, 'mziad')) + def test_sample_data5(self): + self.assertEqual( + 1, get_occurrence_of_key(self.sample5, 'total_number_of_cores') + ) + self.assertEqual(1, get_occurrence_of_key(self.sample5, 'memory')) + # Add key 'memory' and verify + self.sample5['memory'] = 0 + self.assertEqual(2, get_occurrence_of_key(self.sample5, 'memory')) + if __name__ == "__main__": pass