Skip to content

Commit 14c2bfd

Browse files
committed
small optimizations so we don't load functions that are not needed
1 parent c718369 commit 14c2bfd

File tree

3 files changed

+45
-54
lines changed

3 files changed

+45
-54
lines changed

deepdiff/diff.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
from enum import Enum
1212
from copy import deepcopy
1313
from math import isclose as is_close
14-
from typing import List, Dict, IO, Callable, Set, Union, Any, Pattern, Tuple, Optional
14+
from typing import List, Dict, Callable, Union, Any, Pattern, Tuple, Optional
1515
from collections.abc import Mapping, Iterable, Sequence
1616
from collections import defaultdict
1717
from inspect import getmembers
1818
from itertools import zip_longest
19+
from functools import lru_cache
1920
from deepdiff.helper import (strings, bytes_type, numbers, uuids, datetimes, ListItemRemovedOrAdded, notpresent,
2021
IndexedHash, unprocessed, add_to_frozen_set, basic_types,
2122
convert_item_or_items_into_set_else_none, get_type,
@@ -1123,6 +1124,7 @@ def _create_hashtable(self, level, t):
11231124
return local_hashes
11241125

11251126
@staticmethod
1127+
@lru_cache(maxsize=2028)
11261128
def _get_distance_cache_key(added_hash, removed_hash):
11271129
key1, key2 = (added_hash, removed_hash) if added_hash > removed_hash else (removed_hash, added_hash)
11281130
if isinstance(key1, int):

deepdiff/helper.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import sys
22
import re
33
import os
4-
import math
54
import datetime
65
import uuid
76
import logging

deepdiff/serialization.py

Lines changed: 42 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,6 @@
1111
import decimal # NOQA
1212
import orderly_set # NOQA
1313
import collections # NOQA
14-
try:
15-
import yaml
16-
except ImportError: # pragma: no cover.
17-
yaml = None # pragma: no cover.
18-
try:
19-
if sys.version_info >= (3, 11):
20-
import tomllib as tomli
21-
else:
22-
import tomli
23-
except ImportError: # pragma: no cover.
24-
tomli = None # pragma: no cover.
25-
try:
26-
import tomli_w
27-
except ImportError: # pragma: no cover.
28-
tomli_w = None # pragma: no cover.
29-
try:
30-
import clevercsv
31-
csv = None
32-
except ImportError: # pragma: no cover.
33-
import csv
34-
clevercsv = None # pragma: no cover.
35-
try:
36-
import orjson
37-
except ImportError: # pragma: no cover.
38-
orjson = None
39-
try:
40-
from pydantic import BaseModel as PydanticBaseModel
41-
except ImportError: # pragma: no cover.
42-
PydanticBaseModel = None
43-
4414
from copy import deepcopy, copy
4515
from functools import partial
4616
from collections.abc import Mapping
@@ -56,16 +26,17 @@
5626
np_ndarray,
5727
Opcode,
5828
SetOrdered,
29+
pydantic_base_model_type,
30+
PydanticBaseModel,
5931
)
6032
from deepdiff.model import DeltaResult
6133

62-
logger = logging.getLogger(__name__)
63-
6434
try:
65-
import jsonpickle
66-
except ImportError: # pragma: no cover. Json pickle is getting deprecated.
67-
jsonpickle = None # pragma: no cover. Json pickle is getting deprecated.
35+
import orjson
36+
except ImportError: # pragma: no cover.
37+
orjson = None
6838

39+
logger = logging.getLogger(__name__)
6940

7041
class UnsupportedFormatErr(TypeError):
7142
pass
@@ -162,10 +133,11 @@ def to_json_pickle(self):
162133
:ref:`to_json_pickle_label`
163134
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.
164135
"""
165-
if jsonpickle:
136+
try:
137+
import jsonpickle
166138
copied = self.copy()
167139
return jsonpickle.encode(copied)
168-
else:
140+
except ImportError: # pragma: no cover. Json pickle is getting deprecated.
169141
logger.error('jsonpickle library needs to be installed in order to run to_json_pickle') # pragma: no cover. Json pickle is getting deprecated.
170142

171143
@classmethod
@@ -175,9 +147,10 @@ def from_json_pickle(cls, value):
175147
Load DeepDiff object with all the bells and whistles from the json pickle dump.
176148
Note that json pickle dump comes from to_json_pickle
177149
"""
178-
if jsonpickle:
150+
try:
151+
import jsonpickle
179152
return jsonpickle.decode(value)
180-
else:
153+
except ImportError: # pragma: no cover. Json pickle is getting deprecated.
181154
logger.error('jsonpickle library needs to be installed in order to run from_json_pickle') # pragma: no cover. Json pickle is getting deprecated.
182155

183156
def to_json(self, default_mapping: Optional[dict]=None, force_use_builtin_json=False, **kwargs):
@@ -483,31 +456,42 @@ def load_path_content(path, file_type=None):
483456
"""
484457
Loads and deserializes the content of the path.
485458
"""
459+
486460
if file_type is None:
487461
file_type = path.split('.')[-1]
488462
if file_type == 'json':
489463
with open(path, 'r') as the_file:
490464
content = json_loads(the_file.read())
491465
elif file_type in {'yaml', 'yml'}:
492-
if yaml is None: # pragma: no cover.
493-
raise ImportError('Pyyaml needs to be installed.') # pragma: no cover.
466+
try:
467+
import yaml
468+
except ImportError: # pragma: no cover.
469+
raise ImportError('Pyyaml needs to be installed.') from None # pragma: no cover.
494470
with open(path, 'r') as the_file:
495471
content = yaml.safe_load(the_file)
496472
elif file_type == 'toml':
497-
if tomli is None: # pragma: no cover.
498-
raise ImportError('On python<=3.10 tomli needs to be installed.') # pragma: no cover.
473+
try:
474+
if sys.version_info >= (3, 11):
475+
import tomllib as tomli
476+
else:
477+
import tomli
478+
except ImportError: # pragma: no cover.
479+
raise ImportError('On python<=3.10 tomli needs to be installed.') from None # pragma: no cover.
499480
with open(path, 'rb') as the_file:
500481
content = tomli.load(the_file)
501482
elif file_type == 'pickle':
502483
with open(path, 'rb') as the_file:
503484
content = the_file.read()
504485
content = pickle_load(content)
505486
elif file_type in {'csv', 'tsv'}:
506-
if clevercsv: # pragma: no cover.
487+
try:
488+
import clevercsv
507489
content = clevercsv.read_dicts(path)
508-
else:
490+
except ImportError: # pragma: no cover.
491+
import csv
509492
with open(path, 'r') as the_file:
510493
content = list(csv.DictReader(the_file))
494+
511495
logger.info(f"NOTE: CSV content was empty in {path}")
512496

513497
# Everything in csv is string but we try to automatically convert any numbers we find
@@ -554,22 +538,28 @@ def _save_content(content, path, file_type, keep_backup=True):
554538
content = json_dumps(content)
555539
the_file.write(content)
556540
elif file_type in {'yaml', 'yml'}:
557-
if yaml is None: # pragma: no cover.
558-
raise ImportError('Pyyaml needs to be installed.') # pragma: no cover.
541+
try:
542+
import yaml
543+
except ImportError: # pragma: no cover.
544+
raise ImportError('Pyyaml needs to be installed.') from None # pragma: no cover.
559545
with open(path, 'w') as the_file:
560546
content = yaml.safe_dump(content, stream=the_file)
561547
elif file_type == 'toml':
562-
if tomli_w is None: # pragma: no cover.
563-
raise ImportError('Tomli-w needs to be installed.') # pragma: no cover.
548+
try:
549+
import tomli_w
550+
except ImportError: # pragma: no cover.
551+
raise ImportError('Tomli-w needs to be installed.') from None # pragma: no cover.
564552
with open(path, 'wb') as the_file:
565553
content = tomli_w.dump(content, the_file)
566554
elif file_type == 'pickle':
567555
with open(path, 'wb') as the_file:
568556
content = pickle_dump(content, file_obj=the_file)
569557
elif file_type in {'csv', 'tsv'}:
570-
if clevercsv: # pragma: no cover.
558+
try:
559+
import clevercsv
571560
dict_writer = clevercsv.DictWriter
572-
else:
561+
except ImportError: # pragma: no cover.
562+
import csv
573563
dict_writer = csv.DictWriter
574564
with open(path, 'w', newline='') as csvfile:
575565
fieldnames = list(content[0].keys())
@@ -613,7 +603,7 @@ def _serialize_tuple(value):
613603
Mapping: dict,
614604
}
615605

616-
if PydanticBaseModel:
606+
if PydanticBaseModel is not pydantic_base_model_type:
617607
JSON_CONVERTOR[PydanticBaseModel] = lambda x: x.dict()
618608

619609

0 commit comments

Comments
 (0)