Skip to content

Commit c2bd1f1

Browse files
authored
Merge pull request #173 from seperman/dev
4.2.0
2 parents c8e61d1 + 5709f22 commit c2bd1f1

24 files changed

+131
-139
lines changed

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
language: python
2+
cache: pip
23

34
matrix:
45
include:
5-
- python: 3.4
66
- python: 3.5
77
- python: 3.6
88
- python: pypy3
99
- python: 3.7
1010
- python: 3.8
11-
dist: xenial
12-
sudo: true
1311

1412
install:
1513
- pip install -r requirements-dev.txt

AUTHORS

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
Authors:
1+
Many thanks to the following people for their contributions to DeepDiff:
2+
23
- Seperman
34
- Victor Hahn Castell @ Flexoptix
45
- nfvs for Travis-CI setup script.
56
- brbsix for initial Py3 porting.
6-
- WangFenjin for unicode support.
7+
- WangFenjin for Unicode support.
78
- timoilya for comparing list of sets when ignoring order.
89
- Bernhard10 for significant digits comparison.
910
- b-jazz for PEP257 cleanup, Standardize on full names, fixing line endings.
@@ -21,3 +22,5 @@ Authors:
2122
- Juan Soler (Soleronline) for adding ignore_type_number
2223
- mthaddon for adding timedelta diffing support
2324
- Necrophagos for Hashing of the number 1 vs. True
25+
- Hugo (hugovk) for fixes for Python 3.10 and dropping support for EOL Python 3.4
26+
- Andrey Gavrilin (gaal-dev) for hashing classes.

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# DeepDiff v 4.0.9
1+
# DeepDiff v 4.2.0
22

33
<!-- ![Downloads](https://img.shields.io/pypi/dm/deepdiff.svg?style=flat) -->
44
![Python Versions](https://img.shields.io/pypi/pyversions/deepdiff.svg?style=flat)
@@ -11,7 +11,7 @@
1111
- DeepSearch: Search for objects within other objects.
1212
- DeepHash: Hash any object based on their content.
1313

14-
Tested on Python 3.4, 3.5, 3.6, 3.7, Pypy3
14+
Tested on Python 3.5+ and PyPy3.
1515

1616
**NOTE: Python 2 is not supported any more. DeepDiff v3.3.0 was the last version to support Python 2**
1717

@@ -417,6 +417,7 @@ And then running
417417

418418
# ChangeLog
419419

420+
- v4-2-0: .json property is finally removed. Fix for Py3.10. Dropping support for EOL Python 3.4. Ignoring private keys when calculating hashes. For example __init__ is not a part of hash calculation anymore. Fix for #166 Problem with comparing lists, with an boolean as element.
420421
- v4-0-9: Fixing the bug for hashing custom unhashable objects
421422
- v4-0-8: Adding ignore_nan_inequality for float('nan')
422423
- v4-0-7: Hashing of the number 1 vs. True

deepdiff/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""This module offers the DeepDiff, DeepSearch, grep and DeepHash classes."""
22
# flake8: noqa
3-
__version__ = '4.0.9'
3+
__version__ = '4.2.0'
44
import logging
55

66
if __name__ == '__main__':

deepdiff/deephash.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
32
import logging
43
from collections.abc import Iterable, MutableMapping
54
from collections import defaultdict
@@ -171,8 +170,8 @@ def __contains__(self, obj):
171170
return super().__contains__(key)
172171

173172
def _prep_obj(self, obj, parent, parents_ids=EMPTY_FROZENSET, is_namedtuple=False):
174-
"""Difference of 2 objects"""
175-
original_type = type(obj)
173+
"""prepping objects"""
174+
original_type = type(obj) if not isinstance(obj, type) else obj
176175
try:
177176
if is_namedtuple:
178177
obj = obj._asdict()
@@ -209,6 +208,9 @@ def _prep_dict(self, obj, parent, parents_ids=EMPTY_FROZENSET, print_as_attribut
209208

210209
key_text = "%s{}".format(INDEX_VS_ATTRIBUTE[print_as_attribute])
211210
for key, item in obj.items():
211+
# ignore private variables
212+
if isinstance(key, str) and key.startswith('__'):
213+
continue
212214
key_formatted = "'%s'" % key if not print_as_attribute and isinstance(key, strings) else key
213215
key_in_report = key_text % (parent, key_formatted)
214216

@@ -232,7 +234,7 @@ def _prep_dict(self, obj, parent, parents_ids=EMPTY_FROZENSET, print_as_attribut
232234
break
233235
else:
234236
type_str = 'dict'
235-
return "%s:{%s}" % (type_str, result)
237+
return "{}:{{{}}}".format(type_str, result)
236238

237239
def _prep_iterable(self, obj, parent, parents_ids=EMPTY_FROZENSET):
238240

deepdiff/diff.py

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
32

43
# In order to run the docstrings:
54
# python3 -m deepdiff.diff
@@ -10,7 +9,6 @@
109
import difflib
1110
import logging
1211
import json
13-
import jsonpickle
1412
import warnings
1513

1614
from itertools import zip_longest
@@ -27,12 +25,19 @@
2725
from deepdiff.model import RemapDict, ResultDict, TextResult, TreeResult, DiffLevel
2826
from deepdiff.model import DictRelationship, AttributeRelationship
2927
from deepdiff.model import SubscriptableIterableRelationship, NonSubscriptableIterableRelationship, SetRelationship
30-
from deepdiff.deephash import DeepHash
28+
from deepdiff.deephash import DeepHash, BoolObj
3129
from deepdiff.base import Base
3230

3331
logger = logging.getLogger(__name__)
3432
warnings.simplefilter('once', DeprecationWarning)
3533

34+
try:
35+
import jsonpickle
36+
except ImportError:
37+
jsonpickle = None
38+
logger.info('jsonpickle is not installed. The to_json_pickle and from_json_pickle functions will not work.'
39+
'If you dont need those functions, there is nothing to do.')
40+
3641
TREE_VIEW = 'tree'
3742
TEXT_VIEW = 'text'
3843

@@ -476,7 +481,13 @@ def __create_hashtable(self, t, level):
476481
ignore_string_case=self.ignore_string_case,
477482
number_to_string_func=self.number_to_string,
478483
)
479-
item_hash = hashes_all[item]
484+
# import pytest; pytest.set_trace()
485+
key = item
486+
if item is True:
487+
key = BoolObj.TRUE
488+
elif item is False:
489+
key = BoolObj.FALSE
490+
item_hash = hashes_all[key]
480491
except Exception as e: # pragma: no cover
481492
logger.error("Can not produce a hash for %s."
482493
"Not counting this object.\n %s" %
@@ -642,45 +653,26 @@ def __diff(self, level, parents_ids=frozenset({})):
642653
else:
643654
self.__diff_obj(level, parents_ids)
644655

645-
@property
646-
def json(self):
647-
warnings.warn(
648-
"json property will be deprecated. Instead use: to_json_pickle() to get the json pickle or to_json() for bare-bone json.",
649-
DeprecationWarning
650-
)
651-
if not hasattr(self, '_json'):
652-
# copy of self removes all the extra attributes since it assumes
653-
# we have only a simple dictionary.
654-
copied = self.copy()
655-
self._json = jsonpickle.encode(copied)
656-
return self._json
657-
658656
def to_json_pickle(self):
659657
"""
660658
Get the json pickle of the diff object. Unless you need all the attributes and functionality of DeepDiff, running to_json() is the safer option that json pickle.
661659
"""
662-
copied = self.copy()
663-
return jsonpickle.encode(copied)
664-
665-
@json.deleter
666-
def json(self):
667-
del self._json
668-
669-
@classmethod
670-
def from_json(cls, value):
671-
warnings.warn(
672-
"from_json is renamed to from_json_pickle",
673-
DeprecationWarning
674-
)
675-
return cls.from_json_pickle(value)
660+
if jsonpickle:
661+
copied = self.copy()
662+
return jsonpickle.encode(copied)
663+
else:
664+
logger.error('jsonpickle library needs to be installed in order to run to_json_pickle')
676665

677666
@classmethod
678667
def from_json_pickle(cls, value):
679668
"""
680669
Load DeepDiff object with all the bells and whistles from the json pickle dump.
681670
Note that json pickle dump comes from to_json_pickle
682671
"""
683-
return jsonpickle.decode(value)
672+
if jsonpickle:
673+
return jsonpickle.decode(value)
674+
else:
675+
logger.error('jsonpickle library needs to be installed in order to run from_json_pickle')
684676

685677
def to_json(self, default_mapping=None):
686678
"""

deepdiff/diff_doc.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ ignore_type_in_groups
375375
1. Set ignore_string_type_changes=True.
376376
2. Or set ignore_type_in_groups=[(str, bytes)]. Here you are saying if we detect one type to be str and the other one bytes, do not report them as type change. It is exactly as passing ignore_type_in_groups=[DeepDiff.strings] or ignore_type_in_groups=DeepDiff.strings .
377377

378-
Now what if you want also typeA and typeB to be ignored when comparing agains each other?
378+
Now what if you want also typeA and typeB to be ignored when comparing against each other?
379379

380380
1. ignore_type_in_groups=[DeepDiff.strings, (typeA, typeB)]
381381
2. or ignore_type_in_groups=[(str, bytes), (typeA, typeB)]

deepdiff/helper.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
import sys
32
import datetime
43
import re
@@ -10,12 +9,11 @@
109

1110
logger = logging.getLogger(__name__)
1211

13-
py_major_version = sys.version[0]
14-
py_minor_version = sys.version[2]
12+
py_major_version = sys.version_info.major
1513

16-
py2 = py_major_version == '2'
17-
py3 = py_major_version == '3'
18-
py4 = py_major_version == '4'
14+
py2 = py_major_version == 2
15+
py3 = py_major_version == 3
16+
py4 = py_major_version == 4
1917

2018
if py4:
2119
logger.warning('Python 4 is not supported yet. Switching logic to Python 3.') # pragma: no cover
@@ -166,7 +164,7 @@ def add_to_frozen_set(parents_ids, item_id):
166164
def convert_item_or_items_into_set_else_none(items):
167165
if items:
168166
if isinstance(items, strings):
169-
items = set([items])
167+
items = {items}
170168
else:
171169
items = set(items)
172170
else:

deepdiff/model.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
from deepdiff.helper import RemapDict, strings, short_repr, Verbose, notpresent
42
from ast import literal_eval
53
from copy import copy
@@ -156,7 +154,7 @@ def _from_tree_value_changed(self, tree):
156154
def _from_tree_unprocessed(self, tree):
157155
if 'unprocessed' in tree:
158156
for change in tree['unprocessed']:
159-
self['unprocessed'].append("%s: %s and %s" % (change.path(
157+
self['unprocessed'].append("{}: {} and {}".format(change.path(
160158
force=FORCE_DEFAULT), change.t1, change.t2))
161159

162160
def _from_tree_set_item_removed(self, tree):
@@ -167,7 +165,7 @@ def _from_tree_set_item_removed(self, tree):
167165
item = change.t1
168166
if isinstance(item, strings):
169167
item = "'%s'" % item
170-
self['set_item_removed'].add("%s[%s]" % (path, str(item)))
168+
self['set_item_removed'].add("{}[{}]".format(path, str(item)))
171169
# this syntax is rather peculiar, but it's DeepDiff 2.x compatible
172170

173171
def _from_tree_set_item_added(self, tree):
@@ -178,7 +176,7 @@ def _from_tree_set_item_added(self, tree):
178176
item = change.t2
179177
if isinstance(item, strings):
180178
item = "'%s'" % item
181-
self['set_item_added'].add("%s[%s]" % (path, str(item)))
179+
self['set_item_added'].add("{}[{}]".format(path, str(item)))
182180
# this syntax is rather peculiar, but it's DeepDiff 2.x compatible)
183181

184182
def _from_tree_repetition_change(self, tree):
@@ -190,7 +188,7 @@ def _from_tree_repetition_change(self, tree):
190188
self['repetition_change'][path]['value'] = change.t1
191189

192190

193-
class DiffLevel(object):
191+
class DiffLevel:
194192
"""
195193
An object of this class represents a single object-tree-level in a reported change.
196194
A double-linked list of these object describes a single change on all of its levels.
@@ -523,7 +521,7 @@ def copy(self):
523521
return result
524522

525523

526-
class ChildRelationship(object):
524+
class ChildRelationship:
527525
"""
528526
Describes the relationship between a container object (the "parent") and the contained
529527
"child" object.

deepdiff/search.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
32
import re
43
from collections.abc import MutableMapping, Iterable
54
import logging
@@ -225,7 +224,7 @@ def __search_iterable(self,
225224
"""Search iterables except dictionaries, sets and strings."""
226225

227226
for i, thing in enumerate(obj):
228-
new_parent = "%s[%s]" % (parent, i)
227+
new_parent = "{}[{}]".format(parent, i)
229228
if self.__skip_this(thing, parent=new_parent):
230229
continue
231230

0 commit comments

Comments
 (0)