|
31 | 31 | FLOAT_TYPES = (Decimal,)
|
32 | 32 | TIME_TYPES = (date, datetime)
|
33 | 33 |
|
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 |
| - |
65 | 34 |
|
66 | 35 | class Serializer(object):
|
67 | 36 | mimetype = ""
|
@@ -90,28 +59,77 @@ class JSONSerializer(Serializer):
|
90 | 59 | mimetype = "application/json"
|
91 | 60 |
|
92 | 61 | 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): |
96 | 71 | return str(data)
|
97 | 72 | elif isinstance(data, FLOAT_TYPES):
|
98 | 73 | return float(data)
|
| 74 | + |
| 75 | + # This is kept for backwards compatibility even |
| 76 | + # if 'INTEGER_TYPES' isn't used by default anymore. |
99 | 77 | elif INTEGER_TYPES and isinstance(data, INTEGER_TYPES):
|
100 | 78 | return int(data)
|
101 | 79 |
|
102 | 80 | # 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_): |
105 | 112 | return bool(data)
|
106 | 113 | elif isinstance(data, np.datetime64):
|
107 | 114 | return data.item().isoformat()
|
108 | 115 | elif isinstance(data, np.ndarray):
|
109 | 116 | return data.tolist()
|
110 |
| - if pd: |
| 117 | + except ImportError: |
| 118 | + pass |
| 119 | + |
| 120 | + try: |
| 121 | + import pandas as pd |
| 122 | + |
111 | 123 | if isinstance(data, (pd.Series, pd.Categorical)):
|
112 | 124 | return data.tolist()
|
| 125 | + elif isinstance(data, pd.Timestamp) and data is not getattr( |
| 126 | + pd, "NaT", None |
| 127 | + ): |
| 128 | + return data.isoformat() |
113 | 129 | elif data is getattr(pd, "NA", None):
|
114 | 130 | return None
|
| 131 | + except ImportError: |
| 132 | + pass |
115 | 133 |
|
116 | 134 | raise TypeError("Unable to serialize %r (type: %s)" % (data, type(data)))
|
117 | 135 |
|
|
0 commit comments