def test_hash_numpy_array1(self): t1 = np.array([[1, 2]], np.int8) t2 = np.array([[2, 1]], np.int8) t1_hash = DeepHashPrep(t1) t2_hash = DeepHashPrep(t2) assert t1_hash[t1] == 'ndarray:ndarray:int8:1,int8:2' assert t2_hash[t2] == t1_hash[t1]
def test_invalid_numpy_type(self): t1 = np.array([1, 2, 3], np.int8) delta_dict = {'iterable_item_added': {'root[2]': 5}, '_numpy_paths': {'root': 'int11'}} with pytest.raises(DeltaError) as excinfo: Delta(delta_dict, raise_errors=True) + t1 expected_msg = NOT_VALID_NUMPY_TYPE.format("'int11'") assert expected_msg == str(excinfo.value)
def test_hash_numpy_array2_multi_dimensional_can_not_retrieve_individual_array_item_hashes( self): """ This is a very interesting case. When DeepHash extracts t1[0] to create a hash for it, Numpy creates an array. But that array will only be technically available during the DeepHash run. Once DeepHash is run, the array is marked to be deleted by the garbage collector. However depending on the version of the python and the machine that runs it, by the time we get to the line that is t1_hash[t1[0]], the t1[0] may or may not be still in memory. If it is still in the memory, t1_hash[t1[0]] works without a problem. If it is already garbage collected, t1_hash[t1[0]] will throw a key error since there will be a new t1[0] by the time t1_hash[t1[0]] is called. Hence it will have a new ID and thus it will not be available anymore in t1_hash. Remember that since Numpy arrays are not hashable, the ID of the array is stored in t1_hash as a key and not the object itself. """ t1 = np.array([[1, 2, 3, 4], [4, 2, 2, 1]], np.int8) t1_hash = DeepHashPrep(t1) try: t1_hash[t1[0]] except Exception as e: assert str(e).strip("'") == HASH_LOOKUP_ERR_MSG.format(t1[0])
def test_numpy_type_invalid(self): t1 = np.array([[1, 2, 3], [4, 2, 2]], np.int8) diff = { 'iterable_item_added': {'root[2]': [7, 8, 9]}, 'values_changed': { 'root[0][2]': { 'new_value': 5 }, 'root[1][1]': { 'new_value': 1 } }, '_numpy_paths': { 'root': 'int88' } } delta = Delta(diff, raise_errors=True) with pytest.raises(DeltaError) as excinfo: delta + t1 assert "'int88' is not a valid numpy type." == str(excinfo.value)
'delta_case15_similar_to_delta_numpy': { 't1': [1, 2, 3], 't2': [1, 2, 5], 'deepdiff_kwargs': {}, 'to_delta_kwargs': {}, 'expected_delta_dict': { 'values_changed': { 'root[2]': { 'new_value': 5 } } }, 'expected_result': 't2' }, 'delta_numpy1_operator_override': { 't1': np.array([1, 2, 3], np.int8), 't2': np.array([1, 2, 5], np.int8), 'deepdiff_kwargs': {}, 'to_delta_kwargs': {}, 'expected_delta_dict': { 'values_changed': { 'root[2]': { 'new_value': 5 } }, '_numpy_paths': { 'root': 'int8' } }, 'expected_result': DeltaNumpyOperatorOverrideError },
class TestDeepDistance: @pytest.mark.parametrize('diff, expected_length', [ ({ 'set_item_added': { 'root[1]': {6} } }, 1), ({ 'iterable_items_added_at_indexes': { 'root': { 0: 7, 6: 8, 1: 4, 2: 4, 5: 4 } }, 'iterable_items_removed_at_indexes': { 'root': { 6: 6, 0: 5 } } }, 5), ({ 'type_changes': { 'root': { 'old_type': float, 'new_type': Decimal, 'new_value': Decimal('3.2') } } }, 3), ]) def test_item_length(self, diff, expected_length): length = _get_item_length(diff) assert expected_length == length def test_distance_of_the_same_objects(self): t1 = [{1, 2, 3}, {4, 5, 6}] t2 = [{4, 5, 6}, {1, 2, 3}] ddiff = DeepDiff(t1, t2, ignore_order=True, cache_purge_level=0) assert {} == ddiff assert 0 == _get_item_length(ddiff) assert '0' == str(ddiff._get_rough_distance())[:10] assert 9 == ddiff._DistanceMixin__get_item_rough_length(ddiff.t1) assert 9 == ddiff._DistanceMixin__get_item_rough_length(ddiff.t2) def test_distance_of_list_sets(self): t1 = [{1, 2, 3}, {4, 5}] t2 = [{4, 5, 6}, {1, 2, 3}] ddiff = DeepDiff(t1, t2, ignore_order=True, cache_purge_level=0) delta = ddiff._to_delta_dict(report_repetition_required=False) assert {'set_item_added': {'root[1]': {6}}} == delta assert 1 == _get_item_length(ddiff) assert '0.05882352' == str(ddiff._get_rough_distance())[:10] assert 8 == ddiff._DistanceMixin__get_item_rough_length(ddiff.t1) assert 9 == ddiff._DistanceMixin__get_item_rough_length(ddiff.t2) @pytest.mark.parametrize('verbose_level', [0, 1, 1]) def test_distance_of_list_sets2(self, verbose_level): t1 = [{1, 2, 3}, {4, 5}, {1}] t2 = [{4, 5, 6}, {1, 2, 3}, {1, 4}] ddiff = DeepDiff(t1, t2, ignore_order=True, verbose_level=verbose_level, get_deep_distance=True, cache_purge_level=0) delta = ddiff._to_delta_dict(report_repetition_required=False) assert {'set_item_added': {'root[2]': {4}, 'root[1]': {6}}} == delta assert 2 == _get_item_length(ddiff) assert '0.09090909' == str(ddiff['deep_distance'])[:10] assert 10 == ddiff._DistanceMixin__get_item_rough_length(ddiff.t1) assert 12 == ddiff._DistanceMixin__get_item_rough_length(ddiff.t2) @pytest.mark.parametrize('verbose_level', [0, 1, 1]) def test_distance_of_list_sets_and_strings(self, verbose_level): t1 = [{1, 2, 3}, {4, 5, 'hello', 'right!'}, {4, 5, (2, 4, 7)}] t2 = [{4, 5, 6, (2, )}, {1, 2, 3}, {5, 'hello', 'right!'}] ddiff = DeepDiff(t1, t2, ignore_order=True, view=DELTA_VIEW, verbose_level=verbose_level) delta = ddiff._to_delta_dict(report_repetition_required=False) expected = { 'set_item_removed': { 'root[1]': {4} }, 'iterable_items_added_at_indexes': { 'root': { 0: {(2, ), 4, 5, 6} } }, 'iterable_items_removed_at_indexes': { 'root': { 2: {4, 5, (2, 4, 7)} } } } assert expected == ddiff # If the diff was in delta view, spitting out another delta dict should produce identical results. assert delta == ddiff assert 10 == _get_item_length(ddiff) def test_distance_of_tuple_in_list(self): t1 = {(2, ), 4, 5, 6} t2 = {'right!', 'hello', 4, 5} diff = DeepDiff(t1, t2, ignore_order=True, view=DELTA_VIEW, get_deep_distance=True) assert { 'set_item_removed': { 'root': {(2, ), 6} }, 'set_item_added': { 'root': {'hello', 'right!'} } } == diff # delta view should not have the distance info in it assert 'get_deep_distance' not in diff def test_get_item_length_when_loops1(self): t1 = [[1, 2, 1, 3]] t1.append(t1) item_length = _get_item_length(t1) assert 8 == item_length def test_get_item_length_when_loops2(self): t1 = {1: 1} t1[2] = t1 item_length = _get_item_length(t1) assert 2 == item_length def test_get_distance_works_event_when_ignore_order_is_false1(self): t1 = 10 t2 = 110 diff = DeepDiff(t1, t2, get_deep_distance=True) dist = diff['deep_distance'] assert dist == Decimal('0.25') def test_get_distance_works_event_when_ignore_order_is_false2(self): t1 = ["a", "b"] t2 = ["a", "b", "c"] diff = DeepDiff(t1, t2, get_deep_distance=True) dist = diff['deep_distance'] assert str(dist)[:4] == '0.14' assert set(diff.keys()) == {'iterable_item_added', 'deep_distance'} def test_get_distance_works_event_when_ignore_order_is_false3(self): t1 = ["a", "b"] t2 = ["a", "b", "c", "d"] diff = DeepDiff(t1, t2, get_deep_distance=True) dist = diff['deep_distance'] assert str(dist)[:4] == '0.25' def test_get_distance_works_event_when_ignore_order_and_different_hasher( self): t1 = ["a", "b", 2] t2 = ["a", "b", "c", 2.2] diff = DeepDiff(t1, t2, ignore_order=True, get_deep_distance=True, cache_size=100, hasher=sha256hex) dist = diff['deep_distance'] assert str(dist)[:4] == '0.44' def test_get_distance_does_not_care_about_the_size_of_string(self): t1 = ["a", "b"] t2 = ["a", "b", "c", "dddddd"] diff = DeepDiff(t1, t2, get_deep_distance=True) dist = diff['deep_distance'] assert str(dist)[:4] == '0.25' def test_get_item_length_custom_class1(self): item = CustomClass(a=10) item_length = _get_item_length(item) assert 2 == item_length def test_get_item_length_custom_class2_loop(self): item = CustomClass(a=10) item.b = item item_length = _get_item_length(item) assert 2 == item_length @pytest.mark.parametrize('num1, num2, max_, expected', [ (10.0, 10, 1, 0), (Decimal('10.1'), Decimal('10.2'), 1, Decimal('0.004926108374384236453201970443')), (Decimal(10), Decimal(-10), 1, 1), (2, 3, 1, 0.2), (10, -10, .1, .1), (10, -10.1, .1, .1), (10, -10.1, .3, 0.3), ]) def test_get_numbers_distance(self, num1, num2, max_, expected): result = _get_numbers_distance(num1, num2, max_) assert abs(expected - result) < 0.0001 @pytest.mark.parametrize('arr1, arr2', [ (np.array([4.1978, 4.1979, 4.1980]), np.array([4.1971, 4.1879, 4.1981 ])), (np.array([1, 2, 4]), np.array([4, 2, 3])), ]) def test_numpy_distance_vs_get_numbers_distance(self, arr1, arr2): dist_arr = _get_numpy_array_distance(arr1, arr2) for i in range(3): assert dist_arr[i] == _get_numbers_distance(arr1[i], arr2[i]) @pytest.mark.parametrize('num1, num2, max_, expected', [ (10, -10.1, .3, 0.3), (datetime.datetime.utcnow(), datetime.datetime.utcnow() + datetime.timedelta(days=100), 1, 0.002707370659621624), (1589703146.9556487, 1001589703146.9557, 1, 0.9968306702929068), (datetime.time(10, 11), datetime.time(12, 11), .5, 0.0447093889716), (datetime.timedelta(days=2), datetime.timedelta( 12, 11), .5, 0.35714415626180646), (datetime.date(2018, 1, 1), datetime.date( 2020, 1, 10), 1, 0.0005013129787148886), ]) def test_get_numeric_types_distance(self, num1, num2, max_, expected): result = get_numeric_types_distance(num1, num2, max_) assert abs(expected - result) < 0.0001 def test_get_rough_length_after_cache_purge(self): diff = DeepDiff([1], ['a']) with pytest.raises(RuntimeError) as excinfo: diff._get_rough_distance() assert DISTANCE_CALCS_NEEDS_CACHE == str(excinfo.value) def test_cutoff_distance_for_pairs_range(self): with pytest.raises(ValueError) as excinfo: DeepDiff(1, 2, cutoff_distance_for_pairs=2) assert CUTOFF_RANGE_ERROR_MSG == str(excinfo.value)
import pytest from deepdiff import DeepDiff from deepdiff.helper import np from tests import parameterize_cases """ These are numpy specific test cases. There are more numpy tests for delta additions in the test_delta.py """ NUMPY_CASES = { 'numpy_bools': { 't1': np.array([True, False, True, False], dtype=bool), 't2': np.array([False, True, True, False], dtype=bool), 'deepdiff_kwargs': {}, 'expected_result': { 'values_changed': { 'root[0]': { 'new_value': False, 'old_value': True }, 'root[1]': { 'new_value': True, 'old_value': False } } }, }, 'numpy_bools_ignore_order': { 't1': np.array([True, False, True, False], dtype=bool), 't2': np.array([False, True, True, False], dtype=bool), 'deepdiff_kwargs': {
def test_hash_numpy_array_ignore_numeric_type_changes(self): t1 = np.array([[1, 2]], np.int8) t1_hash = DeepHashPrep(t1, ignore_numeric_type_changes=True) assert t1_hash[ t1] == 'ndarray:ndarray:number:1.000000000000,number:2.000000000000'