perspective-python 4.2.0__cp311-abi3-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. perspective/__init__.py +396 -0
  2. perspective/extension/finos-perspective-nbextension.json +5 -0
  3. perspective/handlers/__init__.py +11 -0
  4. perspective/handlers/aiohttp.py +61 -0
  5. perspective/handlers/starlette.py +55 -0
  6. perspective/handlers/tornado.py +184 -0
  7. perspective/perspective.pyd +0 -0
  8. perspective/templates/exported_widget.html.template +35 -0
  9. perspective/tests/__init__.py +11 -0
  10. perspective/tests/async/test_async_client.py +83 -0
  11. perspective/tests/async/test_websocket_client.py +124 -0
  12. perspective/tests/conftest.py +272 -0
  13. perspective/tests/core/__init__.py +11 -0
  14. perspective/tests/core/test_async.py +351 -0
  15. perspective/tests/multi_threaded/__init__.py +11 -0
  16. perspective/tests/multi_threaded/test_multi_threaded.py +201 -0
  17. perspective/tests/server/__init__.py +11 -0
  18. perspective/tests/server/test_server.py +1016 -0
  19. perspective/tests/server/test_session.py +110 -0
  20. perspective/tests/table/__init__.py +11 -0
  21. perspective/tests/table/arrow/date32.arrow +0 -0
  22. perspective/tests/table/arrow/date64.arrow +0 -0
  23. perspective/tests/table/arrow/dict.arrow +0 -0
  24. perspective/tests/table/arrow/dict_update.arrow +0 -0
  25. perspective/tests/table/arrow/int_float_str.arrow +0 -0
  26. perspective/tests/table/arrow/int_float_str_file.arrow +0 -0
  27. perspective/tests/table/arrow/int_float_str_update.arrow +0 -0
  28. perspective/tests/table/object_sequence.py +402 -0
  29. perspective/tests/table/test_column_paths.py +89 -0
  30. perspective/tests/table/test_delete.py +124 -0
  31. perspective/tests/table/test_exception.py +65 -0
  32. perspective/tests/table/test_leaks.py +54 -0
  33. perspective/tests/table/test_ports.py +178 -0
  34. perspective/tests/table/test_remove.py +102 -0
  35. perspective/tests/table/test_table.py +641 -0
  36. perspective/tests/table/test_table_arrow.py +503 -0
  37. perspective/tests/table/test_table_datetime.py +2409 -0
  38. perspective/tests/table/test_table_infer.py +201 -0
  39. perspective/tests/table/test_table_limit.py +45 -0
  40. perspective/tests/table/test_table_numpy.py +1022 -0
  41. perspective/tests/table/test_table_pandas.py +1018 -0
  42. perspective/tests/table/test_table_polars.py +251 -0
  43. perspective/tests/table/test_table_view_table.py +130 -0
  44. perspective/tests/table/test_to_arrow.py +417 -0
  45. perspective/tests/table/test_to_arrow_lz4.py +32 -0
  46. perspective/tests/table/test_to_format.py +1024 -0
  47. perspective/tests/table/test_to_polars.py +26 -0
  48. perspective/tests/table/test_update.py +545 -0
  49. perspective/tests/table/test_update_arrow.py +980 -0
  50. perspective/tests/table/test_update_pandas.py +211 -0
  51. perspective/tests/table/test_view.py +2261 -0
  52. perspective/tests/table/test_view_expression.py +1940 -0
  53. perspective/tests/test_dependencies.py +53 -0
  54. perspective/tests/viewer/__init__.py +11 -0
  55. perspective/tests/viewer/test_viewer.py +246 -0
  56. perspective/tests/widget/__init__.py +11 -0
  57. perspective/tests/widget/test_widget.py +278 -0
  58. perspective/tests/widget/test_widget_pandas.py +453 -0
  59. perspective/virtual_servers/__init__.py +134 -0
  60. perspective/virtual_servers/clickhouse.py +245 -0
  61. perspective/virtual_servers/duckdb.py +236 -0
  62. perspective/widget/__init__.py +349 -0
  63. perspective/widget/viewer/__init__.py +15 -0
  64. perspective/widget/viewer/validate.py +22 -0
  65. perspective/widget/viewer/viewer.py +343 -0
  66. perspective/widget/viewer/viewer_traitlets.py +101 -0
  67. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/install.json +5 -0
  68. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json +71 -0
  69. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/253.5f5c9e80605aa4106a28.js +2 -0
  70. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/253.5f5c9e80605aa4106a28.js.LICENSE.txt +25 -0
  71. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/523.c030af5d3c4f67ff83f6.js +1 -0
  72. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/remoteEntry.95a8ea1b44d96032833f.js +1 -0
  73. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/style.js +4 -0
  74. perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/third-party-licenses.json +16 -0
  75. perspective_python-4.2.0.dist-info/METADATA +27 -0
  76. perspective_python-4.2.0.dist-info/RECORD +79 -0
  77. perspective_python-4.2.0.dist-info/WHEEL +4 -0
  78. perspective_python-4.2.0.dist-info/licenses/LICENSE.md +193 -0
  79. perspective_python-4.2.0.dist-info/licenses/LICENSE_THIRDPARTY_cargo.yml +17395 -0
@@ -0,0 +1,1022 @@
1
+ # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ # ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ # ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ # ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ # ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ # ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ # ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ # ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ # ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ # ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ from datetime import date, datetime
14
+ import numpy as np
15
+ import pandas as pd
16
+ from pytest import raises, mark
17
+ import perspective as psp
18
+
19
+ client = psp.Server().new_local_client()
20
+ Table = client.table
21
+
22
+
23
+ @mark.skip(reason="We do not support numpy types in the Table constructor")
24
+ class TestTableNumpy(object):
25
+ def test_empty_table(self):
26
+ tbl = Table([])
27
+ assert tbl.size() == 0
28
+
29
+ def test_table_int(self):
30
+ data = {"a": np.array([1, 2, 3]), "b": np.array([4, 5, 6])}
31
+ tbl = Table(data)
32
+ assert tbl.size() == 3
33
+ assert tbl.view().to_columns() == {"a": [1, 2, 3], "b": [4, 5, 6]}
34
+
35
+ def test_table_int_lots_of_columns(self):
36
+ data = {
37
+ "a": np.array([1, 2, 3]),
38
+ "b": np.array([4, 5, 6]),
39
+ "c": np.array([4, 5, 6]),
40
+ "d": np.array([4, 5, 6]),
41
+ "e": np.array([4, 5, 6]),
42
+ "f": np.array([4, 5, 6]),
43
+ }
44
+ tbl = Table(data)
45
+ assert tbl.size() == 3
46
+ assert tbl.view().to_columns() == {
47
+ "a": [1, 2, 3],
48
+ "b": [4, 5, 6],
49
+ "c": [4, 5, 6],
50
+ "d": [4, 5, 6],
51
+ "e": [4, 5, 6],
52
+ "f": [4, 5, 6],
53
+ }
54
+
55
+ def test_table_int_with_None(self):
56
+ data = {
57
+ "a": np.array([1, 2, 3, None, None]),
58
+ "b": np.array([4, 5, 6, None, None]),
59
+ }
60
+ tbl = Table(data)
61
+ assert tbl.size() == 5
62
+ assert tbl.view().to_columns() == {
63
+ "a": [1, 2, 3, None, None],
64
+ "b": [4, 5, 6, None, None],
65
+ }
66
+
67
+ def test_table_int8(self):
68
+ data = {
69
+ "a": np.array([1, 2, 3]).astype(np.int8),
70
+ "b": np.array([4, 5, 6]).astype(np.int8),
71
+ }
72
+ tbl = Table(data)
73
+ assert tbl.size() == 3
74
+ assert tbl.view().to_columns() == {"a": [1, 2, 3], "b": [4, 5, 6]}
75
+
76
+ def test_table_int16(self):
77
+ data = {
78
+ "a": np.array([1, 2, 3]).astype(np.int16),
79
+ "b": np.array([4, 5, 6]).astype(np.int16),
80
+ }
81
+ tbl = Table(data)
82
+ assert tbl.size() == 3
83
+ assert tbl.view().to_columns() == {"a": [1, 2, 3], "b": [4, 5, 6]}
84
+
85
+ def test_table_int32(self):
86
+ data = {
87
+ "a": np.array([1, 2, 3]).astype(np.int32),
88
+ "b": np.array([4, 5, 6]).astype(np.int32),
89
+ }
90
+ tbl = Table(data)
91
+ assert tbl.size() == 3
92
+ assert tbl.view().to_columns() == {"a": [1, 2, 3], "b": [4, 5, 6]}
93
+
94
+ def test_table_int64(self):
95
+ data = {
96
+ "a": np.array([1, 2, 3]).astype(np.int64),
97
+ "b": np.array([4, 5, 6]).astype(np.int64),
98
+ }
99
+ tbl = Table(data)
100
+ assert tbl.size() == 3
101
+ assert tbl.view().to_columns() == {"a": [1, 2, 3], "b": [4, 5, 6]}
102
+
103
+ def test_table_float(self):
104
+ data = {"a": np.array([1.1, 2.2]), "b": np.array([3.3, 4.4])}
105
+ tbl = Table(data)
106
+ assert tbl.size() == 2
107
+ assert tbl.view().to_columns() == {"a": [1.1, 2.2], "b": [3.3, 4.4]}
108
+
109
+ def test_table_float32(self):
110
+ data = {
111
+ "a": np.array([1.1, 2.2]).astype(np.float32),
112
+ "b": np.array([3.3, 4.4]).astype(np.float32),
113
+ }
114
+ tbl = Table(data)
115
+ assert tbl.size() == 2
116
+ assert tbl.view().to_columns() == {
117
+ # py::cast automatically upcasts to 64-bit float
118
+ "a": [1.100000023841858, 2.200000047683716],
119
+ "b": [3.299999952316284, 4.400000095367432],
120
+ }
121
+
122
+ def test_table_float64(self):
123
+ data = {
124
+ "a": np.array([1.1, 2.2]).astype(np.float64),
125
+ "b": np.array([3.3, 4.4]).astype(np.float64),
126
+ }
127
+ tbl = Table(data)
128
+ assert tbl.size() == 2
129
+ assert tbl.view().to_columns() == {"a": [1.1, 2.2], "b": [3.3, 4.4]}
130
+
131
+ # booleans
132
+
133
+ def test_table_bool(self):
134
+ data = {"a": np.array([True, False]), "b": np.array([False, True])}
135
+ tbl = Table(data)
136
+ assert tbl.size() == 2
137
+ assert tbl.view().to_columns() == {"a": [True, False], "b": [False, True]}
138
+
139
+ def test_table_bool8(self):
140
+ data = {
141
+ "a": np.array([True, False]).astype(np.bool8),
142
+ "b": np.array([False, True]).astype(np.bool8),
143
+ }
144
+ tbl = Table(data)
145
+ assert tbl.size() == 2
146
+ assert tbl.view().to_columns() == {"a": [True, False], "b": [False, True]}
147
+
148
+ def test_table_bool_with_none(self):
149
+ data = {
150
+ "a": np.array([True, False, None, False]),
151
+ "b": np.array([False, True, None, False]),
152
+ }
153
+ tbl = Table(data)
154
+ assert tbl.size() == 4
155
+ assert tbl.view().to_columns() == {
156
+ "a": [True, False, None, False],
157
+ "b": [False, True, None, False],
158
+ }
159
+
160
+ def test_table_bool_with_dtype(self):
161
+ data = {
162
+ "a": np.array([True, False, False], dtype="?"),
163
+ "b": np.array([False, True, False], dtype="?"),
164
+ }
165
+ tbl = Table(data)
166
+ assert tbl.size() == 3
167
+ assert tbl.view().to_columns() == {
168
+ "a": [True, False, False],
169
+ "b": [False, True, False],
170
+ }
171
+
172
+ def test_table_bool_str(self):
173
+ data = {"a": np.array(["True", "False"]), "b": np.array(["False", "True"])}
174
+ tbl = Table(data)
175
+ assert tbl.size() == 2
176
+ assert tbl.schema() == {"a": bool, "b": "boolean"}
177
+ assert tbl.view().to_columns() == {"a": [True, False], "b": [False, True]}
178
+
179
+ # strings
180
+
181
+ def test_table_str_object(self):
182
+ data = {
183
+ "a": np.array(["abc", "def"], dtype=object),
184
+ "b": np.array(["hij", "klm"], dtype=object),
185
+ }
186
+ tbl = Table(data)
187
+ assert tbl.size() == 2
188
+ assert tbl.view().to_columns() == {"a": ["abc", "def"], "b": ["hij", "klm"]}
189
+
190
+ def test_table_str_dtype(self):
191
+ dtype = "U3"
192
+ data = {
193
+ "a": np.array(["abc", "def"], dtype=dtype),
194
+ "b": np.array(["hij", "klm"], dtype=dtype),
195
+ }
196
+ tbl = Table(data)
197
+ assert tbl.size() == 2
198
+ assert tbl.view().to_columns() == {"a": ["abc", "def"], "b": ["hij", "klm"]}
199
+
200
+ # date and datetime
201
+
202
+ def test_table_date(self):
203
+ data = {"a": np.array([date(2019, 7, 11)]), "b": np.array([date(2019, 7, 12)])}
204
+ tbl = Table(data)
205
+ assert tbl.size() == 1
206
+ assert tbl.schema() == {"a": date, "b": "date"}
207
+ assert tbl.view().to_columns() == {
208
+ "a": [datetime(2019, 7, 11)],
209
+ "b": [datetime(2019, 7, 12)],
210
+ }
211
+
212
+ def test_table_np_datetime(self):
213
+ data = {
214
+ "a": np.array([datetime(2019, 7, 11, 12, 13)], dtype="datetime64[ns]"),
215
+ "b": np.array([datetime(2019, 7, 11, 12, 14)], dtype="datetime64[ns]"),
216
+ }
217
+ tbl = Table(data)
218
+ assert tbl.size() == 1
219
+ assert tbl.schema() == {"a": datetime, "b": "datetime"}
220
+ assert tbl.view().to_numpy() == {
221
+ "a": np.array([datetime(2019, 7, 11, 12, 13)], dtype=object),
222
+ "b": np.array([datetime(2019, 7, 11, 12, 14)], dtype=object),
223
+ }
224
+
225
+ def test_table_np_datetime_mixed_dtype(self):
226
+ data = {
227
+ "a": np.array([datetime(2019, 7, 11, 12, 13)], dtype="datetime64[ns]"),
228
+ "b": np.array([datetime(2019, 7, 11, 12, 14)], dtype=object),
229
+ }
230
+ tbl = Table(data)
231
+ assert tbl.size() == 1
232
+ assert tbl.schema() == {"a": datetime, "b": "datetime"}
233
+ assert tbl.view().to_numpy() == {
234
+ "a": np.array([datetime(2019, 7, 11, 12, 13)], dtype=object),
235
+ "b": np.array([datetime(2019, 7, 11, 12, 14)], dtype=object),
236
+ }
237
+
238
+ def test_table_np_datetime_default(self, util):
239
+ tbl = Table(
240
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[ns]")}
241
+ )
242
+
243
+ assert tbl.view().to_columns() == {
244
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
245
+ }
246
+
247
+ def test_table_np_datetime_string_dtype(self):
248
+ data = ["2019/07/11 15:30:05", "2019/07/11 15:30:05"]
249
+ tbl = Table({"a": np.array(data)})
250
+
251
+ assert tbl.view().to_columns() == {
252
+ "a": [datetime(2019, 7, 11, 15, 30, 5), datetime(2019, 7, 11, 15, 30, 5)]
253
+ }
254
+
255
+ def test_table_np_datetime_string_on_schema(self):
256
+ data = ["2019/07/11 15:30:05", "2019/07/11 15:30:05"]
257
+ tbl = Table({"a": "datetime"})
258
+
259
+ tbl.update({"a": data})
260
+
261
+ assert tbl.view().to_columns() == {
262
+ "a": [datetime(2019, 7, 11, 15, 30, 5), datetime(2019, 7, 11, 15, 30, 5)]
263
+ }
264
+
265
+ def test_table_np_datetime_ns(self, util):
266
+ tbl = Table(
267
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[ns]")}
268
+ )
269
+
270
+ assert tbl.view().to_columns() == {
271
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
272
+ }
273
+
274
+ def test_table_np_datetime_us(self, util):
275
+ tbl = Table(
276
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[us]")}
277
+ )
278
+
279
+ assert tbl.view().to_columns() == {
280
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
281
+ }
282
+
283
+ def test_table_np_datetime_ms(self, util):
284
+ tbl = Table(
285
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[ms]")}
286
+ )
287
+
288
+ assert tbl.view().to_columns() == {
289
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
290
+ }
291
+
292
+ def test_table_np_datetime_s(self, util):
293
+ tbl = Table(
294
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[s]")}
295
+ )
296
+
297
+ assert tbl.view().to_columns() == {
298
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
299
+ }
300
+
301
+ def test_table_np_datetime_m(self, util):
302
+ tbl = Table(
303
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[m]")}
304
+ )
305
+
306
+ assert tbl.view().to_columns() == {
307
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
308
+ }
309
+
310
+ def test_table_np_datetime_h(self, util):
311
+ tbl = Table(
312
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[h]")}
313
+ )
314
+
315
+ assert tbl.view().to_columns() == {
316
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
317
+ }
318
+
319
+ def test_table_np_datetime_D(self, util):
320
+ tbl = Table(
321
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[D]")}
322
+ )
323
+
324
+ assert tbl.schema() == {"a": "date"}
325
+
326
+ assert tbl.view().to_columns() == {
327
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 0, 0))]
328
+ }
329
+
330
+ def test_table_np_datetime_W(self, util):
331
+ tbl = Table(
332
+ {"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[W]")}
333
+ )
334
+
335
+ assert tbl.schema() == {"a": "date"}
336
+
337
+ assert tbl.view().to_columns() == {
338
+ "a": [util.to_timestamp(datetime(2019, 7, 11, 0, 0))]
339
+ }
340
+
341
+ def test_table_np_datetime_M(self):
342
+ tbl = Table(
343
+ {
344
+ "a": np.array(
345
+ [
346
+ datetime(2019, 5, 12, 11, 0),
347
+ datetime(2019, 6, 12, 11, 0),
348
+ datetime(2019, 7, 12, 11, 0),
349
+ ],
350
+ dtype="datetime64[M]",
351
+ )
352
+ }
353
+ )
354
+
355
+ assert tbl.schema() == {"a": "date"}
356
+
357
+ assert tbl.view().to_columns() == {
358
+ "a": [
359
+ datetime(2019, 5, 1, 0, 0),
360
+ datetime(2019, 6, 1, 0, 0),
361
+ datetime(2019, 7, 1, 0, 0),
362
+ ]
363
+ }
364
+
365
+ def test_table_np_datetime_Y(self):
366
+ tbl = Table(
367
+ {
368
+ "a": np.array(
369
+ [
370
+ datetime(2017, 5, 12, 11, 0),
371
+ datetime(2018, 6, 12, 11, 0),
372
+ datetime(2019, 7, 12, 11, 0),
373
+ ],
374
+ dtype="datetime64[Y]",
375
+ )
376
+ }
377
+ )
378
+
379
+ assert tbl.schema() == {"a": "date"}
380
+
381
+ assert tbl.view().to_columns() == {
382
+ "a": [
383
+ datetime(2017, 1, 1, 0, 0),
384
+ datetime(2018, 1, 1, 0, 0),
385
+ datetime(2019, 1, 1, 0, 0),
386
+ ]
387
+ }
388
+
389
+ def test_table_np_datetime_ms_nat(self, util):
390
+ tbl = Table(
391
+ {
392
+ "a": np.array(
393
+ [datetime(2019, 7, 12, 11, 0), np.datetime64("nat")],
394
+ dtype="datetime64[ms]",
395
+ )
396
+ }
397
+ )
398
+
399
+ assert tbl.view().to_columns() == {
400
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0)), None]
401
+ }
402
+
403
+ def test_table_np_datetime_s_nat(self, util):
404
+ tbl = Table(
405
+ {
406
+ "a": np.array(
407
+ [datetime(2019, 7, 12, 11, 0), np.datetime64("nat")],
408
+ dtype="datetime64[s]",
409
+ )
410
+ }
411
+ )
412
+
413
+ assert tbl.view().to_columns() == {
414
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0)), None]
415
+ }
416
+
417
+ def test_table_np_timedelta(self):
418
+ tbl = Table(
419
+ {
420
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[ns]")
421
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[ns]")
422
+ }
423
+ )
424
+
425
+ assert tbl.schema() == {"a": "string"}
426
+
427
+ assert tbl.view().to_columns() == {"a": ["950400000000000 nanoseconds"]}
428
+
429
+ def test_table_np_timedelta_us(self):
430
+ tbl = Table(
431
+ {
432
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[us]")
433
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[us]")
434
+ }
435
+ )
436
+
437
+ assert tbl.schema() == {"a": "string"}
438
+
439
+ assert tbl.view().to_columns() == {"a": ["950400000000 microseconds"]}
440
+
441
+ def test_table_np_timedelta_ms(self):
442
+ tbl = Table(
443
+ {
444
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[ms]")
445
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[ms]")
446
+ }
447
+ )
448
+
449
+ assert tbl.schema() == {"a": "string"}
450
+
451
+ assert tbl.view().to_columns() == {"a": ["950400000 milliseconds"]}
452
+
453
+ def test_table_np_timedelta_s(self):
454
+ tbl = Table(
455
+ {
456
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[s]")
457
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[s]")
458
+ }
459
+ )
460
+
461
+ assert tbl.schema() == {"a": "string"}
462
+
463
+ assert tbl.view().to_columns() == {"a": ["950400 seconds"]}
464
+
465
+ def test_table_np_timedelta_m(self):
466
+ tbl = Table(
467
+ {
468
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[m]")
469
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[m]")
470
+ }
471
+ )
472
+
473
+ assert tbl.schema() == {"a": "string"}
474
+
475
+ assert tbl.view().to_columns() == {"a": ["15840 minutes"]}
476
+
477
+ def test_table_np_timedelta_h(self):
478
+ tbl = Table(
479
+ {
480
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[h]")
481
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[h]")
482
+ }
483
+ )
484
+
485
+ assert tbl.schema() == {"a": "string"}
486
+
487
+ assert tbl.view().to_columns() == {"a": ["264 hours"]}
488
+
489
+ def test_table_np_timedelta_d(self):
490
+ tbl = Table(
491
+ {
492
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype="datetime64[D]")
493
+ - np.array([datetime(2019, 7, 1, 11, 0)], dtype="datetime64[D]")
494
+ }
495
+ )
496
+
497
+ assert tbl.schema() == {"a": "string"}
498
+
499
+ assert tbl.view().to_columns() == {"a": ["11 days"]}
500
+
501
+ def test_table_np_timedelta_with_none(self):
502
+ tbl = Table(
503
+ {
504
+ "a": np.array(
505
+ [None, datetime(2019, 7, 12, 11, 0)], dtype="datetime64[ns]"
506
+ )
507
+ - np.array([datetime(2019, 7, 1, 11, 0), None], dtype="datetime64[ns]")
508
+ }
509
+ )
510
+
511
+ assert tbl.schema() == {"a": "string"}
512
+
513
+ assert tbl.view().to_columns() == {"a": [None, None]} # two `NaT` values
514
+
515
+ def test_table_np_mixed(self):
516
+ data = {
517
+ "a": np.arange(5),
518
+ "b": np.full(5, np.nan),
519
+ "c": ["a", "b", "c", "d", "e"],
520
+ }
521
+
522
+ # should not be able to parse mixed dicts of numpy array with list
523
+ with raises(psp.PerspectiveError):
524
+ Table(data)
525
+
526
+ def test_table_np_promote(self):
527
+ data = {
528
+ "a": np.arange(5),
529
+ "b": np.full(5, np.nan),
530
+ "c": np.array([1, 2, 3, 2147483648, 5]),
531
+ }
532
+ tbl = Table({"a": "integer", "b": "float", "c": "integer"})
533
+ tbl.update(data)
534
+ assert tbl.size() == 5
535
+ assert tbl.schema() == {"a": "integer", "b": "float", "c": "integer"}
536
+
537
+ assert tbl.view().to_columns() == {
538
+ "a": [0, 1, 2, 3, 4],
539
+ "b": [None, None, None, None, None],
540
+ "c": [1.0, 2.0, 3.0, 2147483648.0, 5.0],
541
+ }
542
+
543
+ def test_table_np_promote_to_string(self):
544
+ data = {
545
+ "a": np.arange(4),
546
+ "b": np.array([1, 2, "abc", "abc"]),
547
+ }
548
+ tbl = Table(data)
549
+ assert tbl.size() == 4
550
+ assert tbl.schema() == {
551
+ "a": "integer",
552
+ "b": "string",
553
+ }
554
+
555
+ assert tbl.view().to_columns() == {
556
+ "a": [0, 1, 2, 3],
557
+ "b": ["1", "2", "abc", "abc"],
558
+ }
559
+
560
+ def test_table_np_implicit_index(self):
561
+ data = {
562
+ "a": np.array(["a", "b", "c", "d", "e"]),
563
+ "b": np.array([1, 2, 3, 4, 5]),
564
+ }
565
+ tbl = Table(data)
566
+ assert tbl.size() == 5
567
+ assert tbl.schema() == {"a": "string", "b": "integer"}
568
+ tbl.update(
569
+ {
570
+ "__INDEX__": np.array([1, 2, 3, 4]),
571
+ "a": np.array(["bb", "cc", "dd", "ee"]),
572
+ }
573
+ )
574
+
575
+ assert tbl.view().to_columns() == {
576
+ "a": ["a", "bb", "cc", "dd", "ee"],
577
+ "b": [1, 2, 3, 4, 5],
578
+ }
579
+
580
+ # from schema
581
+
582
+ def test_table_numpy_from_schema_int(self):
583
+ df = {"a": np.array([1, None, 2, None, 3, 4])}
584
+ table = Table({"a": "integer"})
585
+ table.update(df)
586
+ assert table.view().to_columns()["a"] == [1, None, 2, None, 3, 4]
587
+
588
+ def test_table_numpy_from_schema_bool(self):
589
+ data = [True, False, True, False]
590
+ df = {"a": data}
591
+ table = Table({"a": "boolean"})
592
+ table.update(df)
593
+ assert table.view().to_columns()["a"] == data
594
+
595
+ def test_table_numpy_from_schema_float(self):
596
+ data = [1.5, None, 2.5, None, 3.5, 4.5]
597
+ df = {"a": np.array(data)}
598
+ table = Table({"a": "float"})
599
+ table.update(df)
600
+ assert table.view().to_columns()["a"] == data
601
+
602
+ def test_table_numpy_from_schema_float_all_nan(self):
603
+ data = [np.nan, np.nan, np.nan, np.nan]
604
+ df = {"a": np.array(data)}
605
+ table = Table({"a": "float"})
606
+ table.update(df)
607
+ assert table.view().to_columns()["a"] == [None, None, None, None]
608
+
609
+ def test_table_numpy_from_schema_float_to_int(self):
610
+ data = [None, 1.5, None, 2.5, None, 3.5, 4.5]
611
+ df = {"a": np.array(data)}
612
+ table = Table({"a": "integer"})
613
+ table.update(df)
614
+ # truncates decimal
615
+ assert table.view().to_columns()["a"] == [None, 1, None, 2, None, 3, 4]
616
+
617
+ def test_table_numpy_from_schema_float_to_int_with_nan(self):
618
+ df = {"a": np.array([np.nan, 1.5, np.nan, 2.5, np.nan, 3.5, 4.5])}
619
+ table = Table({"a": "integer"})
620
+ table.update(df)
621
+ # truncates decimal
622
+ assert table.view().to_columns()["a"] == [None, 1, None, 2, None, 3, 4]
623
+
624
+ def test_table_numpy_from_schema_float_to_int_with_nan_partial(self):
625
+ df = {"a": np.array([np.nan, 1.5, np.nan, 2.5, np.nan, 3.5, 4.5])}
626
+ table = Table({"a": "integer", "b": "integer"})
627
+ table.update(df)
628
+ assert table.size() == 7
629
+ # truncates decimal
630
+ assert table.view().to_columns() == {
631
+ "a": [None, 1, None, 2, None, 3, 4],
632
+ "b": [None, None, None, None, None, None, None],
633
+ }
634
+
635
+ def test_table_numpy_from_schema_float_to_int_with_nan_partial_indexed(self):
636
+ """Assert that the null masking works even when primary keys
637
+ are being reordered."""
638
+ df = {
639
+ "a": np.array([np.nan, 1.5, np.nan, 2.5, np.nan, 3.5, 4.5]),
640
+ "b": np.array([1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]),
641
+ }
642
+ table = Table({"a": "integer", "b": "integer"}, index="b")
643
+ table.update(df)
644
+
645
+ # truncates decimal
646
+ assert table.view().to_columns() == {
647
+ "a": [None, 1, None, 2, None, 3, 4],
648
+ "b": [1, 2, 3, 4, 5, 6, 7],
649
+ }
650
+
651
+ table.update(pd.DataFrame({"a": [10, 9, 8], "b": [2, 3, 5]}))
652
+
653
+ assert table.view().to_columns() == {
654
+ "a": [None, 10, 9, 2, 8, 3, 4],
655
+ "b": [1, 2, 3, 4, 5, 6, 7],
656
+ }
657
+
658
+ table.update(
659
+ {
660
+ "a": np.array([100, np.nan], dtype=np.float64),
661
+ "b": np.array([-1, 6], dtype=np.float64),
662
+ }
663
+ )
664
+
665
+ assert table.view().to_columns() == {
666
+ "a": [100, None, 10, 9, 2, 8, None, 4],
667
+ "b": [-1, 1, 2, 3, 4, 5, 6, 7],
668
+ }
669
+
670
+ table.update(
671
+ {
672
+ "a": np.array([100, 1000, np.nan], dtype=np.float64),
673
+ "b": np.array([100, 6, 97], dtype=np.float64),
674
+ }
675
+ )
676
+
677
+ assert table.view().to_columns() == {
678
+ "a": [100, None, 10, 9, 2, 8, 1000, 4, None, 100],
679
+ "b": [-1, 1, 2, 3, 4, 5, 6, 7, 97, 100],
680
+ }
681
+
682
+ def test_table_numpy_from_schema_int_to_float(self):
683
+ data = [None, 1, None, 2, None, 3, 4]
684
+ df = {"a": np.array(data)}
685
+ table = Table({"a": "float"})
686
+ table.update(df)
687
+ assert table.view().to_columns()["a"] == [None, 1.0, None, 2.0, None, 3.0, 4.0]
688
+
689
+ def test_table_numpy_from_schema_date(self):
690
+ data = [date(2019, 8, 15), None, date(2019, 8, 16)]
691
+ df = {"a": np.array(data)}
692
+ table = Table({"a": "date"})
693
+ table.update(df)
694
+ assert table.view().to_columns()["a"] == [
695
+ datetime(2019, 8, 15),
696
+ None,
697
+ datetime(2019, 8, 16),
698
+ ]
699
+
700
+ def test_table_numpy_from_schema_datetime(self):
701
+ data = [
702
+ datetime(2019, 7, 11, 12, 30, 5),
703
+ None,
704
+ datetime(2019, 7, 11, 13, 30, 5),
705
+ None,
706
+ ]
707
+ df = {"a": np.array(data)}
708
+ table = Table({"a": "datetime"})
709
+ table.update(df)
710
+ assert table.view().to_columns()["a"] == data
711
+
712
+ def test_table_numpy_from_schema_datetime_timestamp_s(self, util):
713
+ data = [
714
+ util.to_timestamp(datetime(2019, 7, 11, 12, 30, 5)),
715
+ np.nan,
716
+ util.to_timestamp(datetime(2019, 7, 11, 13, 30, 5)),
717
+ np.nan,
718
+ ]
719
+ df = {"a": np.array(data)}
720
+ table = Table({"a": "datetime"})
721
+ table.update(df)
722
+ assert table.view().to_columns()["a"] == [
723
+ datetime(2019, 7, 11, 12, 30, 5),
724
+ None,
725
+ datetime(2019, 7, 11, 13, 30, 5),
726
+ None,
727
+ ]
728
+
729
+ def test_table_numpy_from_schema_datetime_timestamp_ms(self, util):
730
+ data = [
731
+ util.to_timestamp(datetime(2019, 7, 11, 12, 30, 5)) * 1000,
732
+ np.nan,
733
+ util.to_timestamp(datetime(2019, 7, 11, 13, 30, 5)) * 1000,
734
+ np.nan,
735
+ ]
736
+
737
+ df = {"a": np.array(data)}
738
+ table = Table({"a": "datetime"})
739
+ table.update(df)
740
+ assert table.view().to_columns()["a"] == [
741
+ datetime(2019, 7, 11, 12, 30, 5),
742
+ None,
743
+ datetime(2019, 7, 11, 13, 30, 5),
744
+ None,
745
+ ]
746
+
747
+ def test_table_numpy_from_schema_str(self):
748
+ data = ["a", None, "b", None, "c"]
749
+ df = {"a": np.array(data)}
750
+ table = Table({"a": "string"})
751
+ table.update(df)
752
+ assert table.view().to_columns()["a"] == data
753
+
754
+ # partial update
755
+
756
+ def test_table_numpy_partial_update(self):
757
+ data = ["a", None, "b", None, "c"]
758
+ df = {"a": np.array([1, 2, 3, 4, 5]), "b": np.array(data), "c": np.array(data)}
759
+ table = Table(df, index="a")
760
+ table.update({"a": np.array([2, 4, 5]), "b": np.array(["x", "y", "z"])})
761
+ assert table.view().to_columns() == {
762
+ "a": [1, 2, 3, 4, 5],
763
+ "b": ["a", "x", "b", "y", "z"],
764
+ "c": ["a", None, "b", None, "c"],
765
+ }
766
+
767
+ def test_table_numpy_partial_update_implicit(self):
768
+ data = ["a", None, "b", None, "c"]
769
+ df = {"a": np.array([1, 2, 3, 4, 5]), "b": np.array(data), "c": np.array(data)}
770
+ table = Table(df)
771
+ table.update({"__INDEX__": np.array([1, 3, 4]), "b": np.array(["x", "y", "z"])})
772
+ assert table.view().to_columns() == {
773
+ "a": [1, 2, 3, 4, 5],
774
+ "b": ["a", "x", "b", "y", "z"],
775
+ "c": ["a", None, "b", None, "c"],
776
+ }
777
+
778
+ # structured array
779
+
780
+ def test_table_structured_array(self):
781
+ d = np.array([(1.0, 2), (3.0, 4)], dtype=[("x", "<f8"), ("y", "<i8")])
782
+ table = Table(d)
783
+ assert table.schema() == {"x": "float", "y": "integer"}
784
+ assert table.view().to_columns() == {"x": [1.0, 3.0], "y": [2, 4]}
785
+
786
+ # recarray
787
+
788
+ def test_table_recarray(self):
789
+ d = np.array([(1.0, 2), (3.0, 4)], dtype=[("x", "<f8"), ("y", "<i8")]).view(
790
+ np.recarray
791
+ )
792
+ table = Table(d)
793
+ assert table.schema() == {"x": "float", "y": "integer"}
794
+ assert table.view().to_columns() == {"x": [1.0, 3.0], "y": [2, 4]}
795
+
796
+ def test_table_recarray_datetime_ns(self):
797
+ d = np.array(
798
+ [
799
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
800
+ (datetime(2019, 7, 11, 8, 30, 29), 4),
801
+ ],
802
+ dtype=[("x", "datetime64[ns]"), ("y", "<i8")],
803
+ ).view(np.recarray)
804
+ table = Table(d)
805
+ assert table.schema() == {"x": "datetime", "y": "integer"}
806
+ assert table.view().to_columns() == {
807
+ "x": [datetime(2019, 7, 11, 8, 30, 29), datetime(2019, 7, 11, 8, 30, 29)],
808
+ "y": [2, 4],
809
+ }
810
+
811
+ def test_table_recarray_datetime_us(self):
812
+ d = np.array(
813
+ [
814
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
815
+ (datetime(2019, 7, 11, 8, 30, 29), 4),
816
+ ],
817
+ dtype=[("x", "datetime64[us]"), ("y", "<i8")],
818
+ ).view(np.recarray)
819
+ table = Table(d)
820
+ assert table.schema() == {"x": "datetime", "y": "integer"}
821
+ assert table.view().to_columns() == {
822
+ "x": [datetime(2019, 7, 11, 8, 30, 29), datetime(2019, 7, 11, 8, 30, 29)],
823
+ "y": [2, 4],
824
+ }
825
+
826
+ def test_table_recarray_datetime_ms(self):
827
+ d = np.array(
828
+ [
829
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
830
+ (datetime(2019, 7, 11, 8, 30, 29), 4),
831
+ ],
832
+ dtype=[("x", "datetime64[ms]"), ("y", "<i8")],
833
+ ).view(np.recarray)
834
+ table = Table(d)
835
+ assert table.schema() == {"x": "datetime", "y": "integer"}
836
+ assert table.view().to_columns() == {
837
+ "x": [datetime(2019, 7, 11, 8, 30, 29), datetime(2019, 7, 11, 8, 30, 29)],
838
+ "y": [2, 4],
839
+ }
840
+
841
+ def test_table_recarray_datetime_s(self):
842
+ d = np.array(
843
+ [
844
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
845
+ (datetime(2019, 7, 11, 8, 30, 29), 4),
846
+ ],
847
+ dtype=[("x", "datetime64[s]"), ("y", "<i8")],
848
+ ).view(np.recarray)
849
+ table = Table(d)
850
+ assert table.schema() == {"x": "datetime", "y": "integer"}
851
+ assert table.view().to_columns() == {
852
+ "x": [datetime(2019, 7, 11, 8, 30, 29), datetime(2019, 7, 11, 8, 30, 29)],
853
+ "y": [2, 4],
854
+ }
855
+
856
+ def test_table_recarray_datetime_m(self):
857
+ d = np.array(
858
+ [
859
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
860
+ (datetime(2019, 7, 11, 8, 31, 29), 4),
861
+ ],
862
+ dtype=[("x", "datetime64[m]"), ("y", "<i8")],
863
+ ).view(np.recarray)
864
+ table = Table(d)
865
+ assert table.schema() == {"x": "datetime", "y": "integer"}
866
+ assert table.view().to_columns() == {
867
+ "x": [datetime(2019, 7, 11, 8, 30, 0), datetime(2019, 7, 11, 8, 31, 0)],
868
+ "y": [2, 4],
869
+ }
870
+
871
+ def test_table_recarray_datetime_h(self):
872
+ d = np.array(
873
+ [
874
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
875
+ (datetime(2019, 7, 11, 9, 30, 29), 4),
876
+ ],
877
+ dtype=[("x", "datetime64[h]"), ("y", "<i8")],
878
+ ).view(np.recarray)
879
+ table = Table(d)
880
+ assert table.schema() == {"x": "datetime", "y": "integer"}
881
+ assert table.view().to_columns() == {
882
+ "x": [datetime(2019, 7, 11, 8, 0, 0), datetime(2019, 7, 11, 9, 0, 0)],
883
+ "y": [2, 4],
884
+ }
885
+
886
+ def test_table_recarray_datetime_D(self):
887
+ d = np.array(
888
+ [
889
+ (datetime(2019, 7, 11, 8, 30, 29), 2),
890
+ (datetime(2019, 7, 12, 8, 30, 29), 4),
891
+ ],
892
+ dtype=[("x", "datetime64[D]"), ("y", "<i8")],
893
+ ).view(np.recarray)
894
+ table = Table(d)
895
+ assert table.schema() == {"x": "date", "y": "integer"}
896
+ assert table.view().to_columns() == {
897
+ "x": [datetime(2019, 7, 11, 0, 0, 0), datetime(2019, 7, 12, 0, 0, 0)],
898
+ "y": [2, 4],
899
+ }
900
+
901
+ def test_table_recarray_datetime_W(self):
902
+ d = np.array(
903
+ [(datetime(2019, 6, 30, 0, 0, 0), 2), (datetime(2019, 7, 7, 0, 0, 0), 4)],
904
+ dtype=[("x", "datetime64[W]"), ("y", "<i8")],
905
+ ).view(np.recarray)
906
+ table = Table(d)
907
+ assert table.schema() == {"x": "date", "y": "integer"}
908
+ assert table.view().to_columns() == {
909
+ # one week apart
910
+ "x": [datetime(2019, 6, 27, 0, 0, 0), datetime(2019, 7, 4, 0, 0, 0)],
911
+ "y": [2, 4],
912
+ }
913
+
914
+ def test_table_recarray_datetime_M(self):
915
+ d = np.array(
916
+ [
917
+ (datetime(2019, 6, 11, 8, 30, 29), 2),
918
+ (datetime(2019, 7, 11, 8, 30, 29), 4),
919
+ ],
920
+ dtype=[("x", "datetime64[M]"), ("y", "<i8")],
921
+ ).view(np.recarray)
922
+ table = Table(d)
923
+ assert table.schema() == {"x": "date", "y": "integer"}
924
+ assert table.view().to_columns() == {
925
+ "x": [datetime(2019, 6, 1, 0, 0, 0), datetime(2019, 7, 1, 0, 0, 0)],
926
+ "y": [2, 4],
927
+ }
928
+
929
+ def test_table_recarray_datetime_Y(self):
930
+ d = np.array(
931
+ [
932
+ (datetime(2018, 7, 11, 8, 30, 29), 2),
933
+ (datetime(2019, 7, 11, 8, 30, 29), 4),
934
+ ],
935
+ dtype=[("x", "datetime64[Y]"), ("y", "<i8")],
936
+ ).view(np.recarray)
937
+ table = Table(d)
938
+ assert table.schema() == {"x": "date", "y": "integer"}
939
+ assert table.view().to_columns() == {
940
+ "x": [datetime(2018, 1, 1, 0, 0, 0), datetime(2019, 1, 1, 0, 0, 0)],
941
+ "y": [2, 4],
942
+ }
943
+
944
+ def test_table_recarray_str(self):
945
+ table = Table(
946
+ np.array(
947
+ [("string1", "string2"), ("string3", "string4")],
948
+ dtype=[("x", "O"), ("y", "O")],
949
+ ).view(np.recarray)
950
+ )
951
+ assert table.schema() == {"x": "string", "y": "string"}
952
+ assert table.view().to_columns() == {
953
+ "x": ["string1", "string3"],
954
+ "y": ["string2", "string4"],
955
+ }
956
+
957
+ def test_table_recarray_str_dtype(self):
958
+ dtype = "U7"
959
+ table = Table(
960
+ np.array(
961
+ [("string1", "string2"), ("string3", "string4")],
962
+ dtype=[("x", dtype), ("y", dtype)],
963
+ ).view(np.recarray)
964
+ )
965
+ assert table.schema() == {"x": "string", "y": "string"}
966
+ assert table.view().to_columns() == {
967
+ "x": ["string1", "string3"],
968
+ "y": ["string2", "string4"],
969
+ }
970
+
971
+ def test_table_float32_to_float64(self):
972
+ data = {
973
+ "a": np.array([1.1, 2.2]).astype(np.float32),
974
+ "b": np.array([3.3, 4.4]).astype(np.float32),
975
+ }
976
+ table = Table(data)
977
+ assert table.size() == 2
978
+ schema = table.schema()
979
+ assert schema == {"a": "float", "b": "float"}
980
+ assert table.view().to_columns() == {
981
+ "a": [1.100000023841858, 2.200000047683716],
982
+ "b": [3.299999952316284, 4.400000095367432],
983
+ }
984
+
985
+ def test_table_float64_to_float32(self):
986
+ data = {
987
+ "a": np.array([1.1, 2.2]).astype(np.float64),
988
+ "b": np.array([3.3, 4.4]).astype(np.float64),
989
+ }
990
+ table = Table(data)
991
+ assert table.size() == 2
992
+ schema = table.schema()
993
+ assert schema == {"a": "float", "b": "float"}
994
+ view = table.view()
995
+ assert view.to_columns() == {"a": [1.1, 2.2], "b": [3.3, 4.4]}
996
+ view.schema({"a": np.float32, "b": np.float32})
997
+ assert view.to_columns() == {"a": [1.1, 2.2], "b": [3.3, 4.4]}
998
+ data["a"] = data["a"].astype(np.float32)
999
+ data["b"] = data["b"].astype(np.float32)
1000
+ table = Table(data)
1001
+ assert table.size() == 2
1002
+ schema = table.schema()
1003
+ assert schema == {"a": "float", "b": "float"}
1004
+ view = table.view()
1005
+ assert view.to_columns() == {
1006
+ "a": [1.100000023841858, 2.200000047683716],
1007
+ "b": [3.299999952316284, 4.400000095367432],
1008
+ }
1009
+
1010
+ def test_table_float32_to_float64_with_nulls(self):
1011
+ data = {
1012
+ "a": np.array([1.1, np.nan, 2.2]).astype(np.float32),
1013
+ "b": np.array([3.3, 4.4, np.nan]).astype(np.float32),
1014
+ }
1015
+ table = Table(data)
1016
+ assert table.size() == 3
1017
+ schema = table.schema()
1018
+ assert schema == {"a": "float", "b": "float"}
1019
+ assert table.view().to_columns() == {
1020
+ "a": [1.100000023841858, None, 2.200000047683716],
1021
+ "b": [3.299999952316284, 4.400000095367432, None],
1022
+ }