Skip to content

Commit 2aab5fd

Browse files
[7.x] Delay importing numpy and pandas until necessary
Co-authored-by: Seth Michael Larson <seth.larson@elastic.co>
1 parent 29b8ce2 commit 2aab5fd

File tree

1 file changed

+55
-37
lines changed

1 file changed

+55
-37
lines changed

elasticsearch/serializer.py

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,37 +31,6 @@
3131
FLOAT_TYPES = (Decimal,)
3232
TIME_TYPES = (date, datetime)
3333

34-
try:
35-
import numpy as np
36-
37-
INTEGER_TYPES += (
38-
np.int_,
39-
np.intc,
40-
np.int8,
41-
np.int16,
42-
np.int32,
43-
np.int64,
44-
np.uint8,
45-
np.uint16,
46-
np.uint32,
47-
np.uint64,
48-
)
49-
FLOAT_TYPES += (
50-
np.float_,
51-
np.float16,
52-
np.float32,
53-
np.float64,
54-
)
55-
except ImportError:
56-
np = None
57-
58-
try:
59-
import pandas as pd
60-
61-
TIME_TYPES += (pd.Timestamp,)
62-
except ImportError:
63-
pd = None
64-
6534

6635
class Serializer(object):
6736
mimetype = ""
@@ -90,28 +59,77 @@ class JSONSerializer(Serializer):
9059
mimetype = "application/json"
9160

9261
def default(self, data):
93-
if isinstance(data, TIME_TYPES) and getattr(pd, "NaT", None) is not data:
94-
return data.isoformat()
95-
elif isinstance(data, uuid.UUID):
62+
if isinstance(data, TIME_TYPES):
63+
# Little hack to avoid importing pandas but to not
64+
# return 'NaT' string for pd.NaT as that's not a valid
65+
# Elasticsearch date.
66+
formatted_data = data.isoformat()
67+
if formatted_data != "NaT":
68+
return formatted_data
69+
70+
if isinstance(data, uuid.UUID):
9671
return str(data)
9772
elif isinstance(data, FLOAT_TYPES):
9873
return float(data)
74+
75+
# This is kept for backwards compatibility even
76+
# if 'INTEGER_TYPES' isn't used by default anymore.
9977
elif INTEGER_TYPES and isinstance(data, INTEGER_TYPES):
10078
return int(data)
10179

10280
# Special cases for numpy and pandas types
103-
elif np:
104-
if isinstance(data, np.bool_):
81+
# These are expensive to import so we try them last.
82+
try:
83+
import numpy as np
84+
85+
if isinstance(
86+
data,
87+
(
88+
np.int_,
89+
np.intc,
90+
np.int8,
91+
np.int16,
92+
np.int32,
93+
np.int64,
94+
np.uint8,
95+
np.uint16,
96+
np.uint32,
97+
np.uint64,
98+
),
99+
):
100+
return int(data)
101+
elif isinstance(
102+
data,
103+
(
104+
np.float_,
105+
np.float16,
106+
np.float32,
107+
np.float64,
108+
),
109+
):
110+
return float(data)
111+
elif isinstance(data, np.bool_):
105112
return bool(data)
106113
elif isinstance(data, np.datetime64):
107114
return data.item().isoformat()
108115
elif isinstance(data, np.ndarray):
109116
return data.tolist()
110-
if pd:
117+
except ImportError:
118+
pass
119+
120+
try:
121+
import pandas as pd
122+
111123
if isinstance(data, (pd.Series, pd.Categorical)):
112124
return data.tolist()
125+
elif isinstance(data, pd.Timestamp) and data is not getattr(
126+
pd, "NaT", None
127+
):
128+
return data.isoformat()
113129
elif data is getattr(pd, "NA", None):
114130
return None
131+
except ImportError:
132+
pass
115133

116134
raise TypeError("Unable to serialize %r (type: %s)" % (data, type(data)))
117135

0 commit comments

Comments
 (0)