From c3a4f32b6c79a1bb8c5c8ebea4edc39515a420a8 Mon Sep 17 00:00:00 2001 From: Shivam Dhar Date: Thu, 6 Jan 2022 02:02:18 +0530 Subject: [PATCH] delays importing numpy and pandas to reduce the startup time Signed-off-by: Shivam Dhar --- opensearchpy/serializer.py | 89 ++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/opensearchpy/serializer.py b/opensearchpy/serializer.py index d7180e8e..391cf92d 100644 --- a/opensearchpy/serializer.py +++ b/opensearchpy/serializer.py @@ -40,37 +40,6 @@ INTEGER_TYPES = () FLOAT_TYPES = (Decimal,) TIME_TYPES = (date, datetime) -try: - import numpy as np - - INTEGER_TYPES += ( - np.int_, - np.intc, - np.int8, - np.int16, - np.int32, - np.int64, - np.uint8, - np.uint16, - np.uint32, - np.uint64, - ) - FLOAT_TYPES += ( - np.float_, - np.float16, - np.float32, - np.float64, - ) -except ImportError: - np = None - -try: - import pandas as pd - - TIME_TYPES += (pd.Timestamp,) -except ImportError: - pd = None - class Serializer(object): mimetype = "" @@ -99,9 +68,15 @@ class JSONSerializer(Serializer): mimetype = "application/json" def default(self, data): - if isinstance(data, TIME_TYPES) and getattr(pd, "NaT", None) is not data: - return data.isoformat() - elif isinstance(data, uuid.UUID): + if isinstance(data, TIME_TYPES): + # Little hack to avoid importing pandas but to not + # return 'NaT' string for pd.NaT as that's not a valid + # date. + formatted_data = data.isoformat() + if formatted_data != "NaT": + return formatted_data + + if isinstance(data, uuid.UUID): return str(data) elif isinstance(data, FLOAT_TYPES): return float(data) @@ -109,18 +84,58 @@ class JSONSerializer(Serializer): return int(data) # Special cases for numpy and pandas types - elif np: - if isinstance(data, np.bool_): + # These are expensive to import so we try them last. + try: + import numpy as np + + if isinstance( + data, + ( + np.int_, + np.intc, + np.int8, + np.int16, + np.int32, + np.int64, + np.uint8, + np.uint16, + np.uint32, + np.uint64, + ), + ): + return int(data) + elif isinstance( + data, + ( + np.float_, + np.float16, + np.float32, + np.float64, + ), + ): + return float(data) + elif isinstance(data, np.bool_): return bool(data) elif isinstance(data, np.datetime64): return data.item().isoformat() elif isinstance(data, np.ndarray): return data.tolist() - if pd: + except ImportError: + pass + + try: + import pandas as pd + if isinstance(data, (pd.Series, pd.Categorical)): return data.tolist() + elif isinstance(data, pd.Timestamp) and data is not getattr( + pd, "NaT", None + ): + return data.isoformat() elif data is getattr(pd, "NA", None): return None + except ImportError: + pass raise TypeError("Unable to serialize %r (type: %s)" % (data, type(data)))