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,417 @@
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
+ import pyarrow as pa
14
+ from datetime import date, datetime
15
+ import perspective as psp
16
+
17
+ client = psp.Server().new_local_client()
18
+ Table = client.table
19
+
20
+
21
+ class TestToArrow(object):
22
+ def test_to_arrow_nones_symmetric(self):
23
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
24
+ tbl = Table(data)
25
+ assert tbl.schema() == {"a": "integer", "b": "float"}
26
+ arr = tbl.view().to_arrow()
27
+ tbl2 = Table(arr)
28
+ assert tbl2.view().to_columns() == data
29
+
30
+ def test_to_arrow_big_numbers_symmetric(self):
31
+ data = {
32
+ "a": [1, 2, 3, 4],
33
+ "b": [
34
+ 1.7976931348623157e308,
35
+ 1.7976931348623157e308,
36
+ 1.7976931348623157e308,
37
+ 1.7976931348623157e308,
38
+ ],
39
+ }
40
+ tbl = Table(data)
41
+ assert tbl.schema() == {"a": "integer", "b": "float"}
42
+ arr = tbl.view().to_arrow()
43
+ tbl2 = Table(arr)
44
+ assert tbl2.view().to_columns() == data
45
+
46
+ def test_to_arrow_boolean_symmetric(self):
47
+ data = {"a": [True, False, None, False, True, None]}
48
+ tbl = Table(data)
49
+ assert tbl.schema() == {"a": "boolean"}
50
+ arr = tbl.view().to_arrow()
51
+ tbl2 = Table(arr)
52
+ assert tbl2.view().to_columns() == data
53
+
54
+ def test_to_arrow_str_symmetric(self):
55
+ data = {"a": ["a", "b", "c", "d", "e", None]}
56
+ tbl = Table(data)
57
+ assert tbl.schema() == {"a": "string"}
58
+ arr = tbl.view().to_arrow()
59
+ tbl2 = Table(arr)
60
+ assert tbl2.view().to_columns() == data
61
+
62
+ def test_to_arrow_str_dict(self):
63
+ data = {
64
+ "a": ["abcdefg", "abcdefg", "h"],
65
+ "b": ["aaa", "bbb", "bbb"],
66
+ "c": ["hello", "world", "world"],
67
+ }
68
+ tbl = Table(data)
69
+ assert tbl.schema() == {"a": "string", "b": "string", "c": "string"}
70
+ arr = tbl.view().to_arrow()
71
+
72
+ # assert that we are actually generating dict arrays
73
+ buf = pa.BufferReader(arr)
74
+ reader = pa.ipc.open_stream(buf)
75
+ arrow_table = reader.read_all()
76
+ arrow_schema = arrow_table.schema
77
+
78
+ for name in ("a", "b", "c"):
79
+ arrow_type = arrow_schema.field(name).type
80
+ assert pa.types.is_dictionary(arrow_type)
81
+
82
+ # assert that data is symmetrical
83
+ tbl2 = Table(arr)
84
+ assert tbl2.view().to_columns() == data
85
+
86
+ def test_to_arrow_date_symmetric(self):
87
+ # data = {"a": [date(2019, 7, 11), date(2016, 2, 29), date(2019, 12, 10)]}
88
+ # tbl = Table(data)
89
+ tbl = Table({"a": "date"})
90
+ # data = {"a": map(lambda x: x.getTime(), [date(2019, 7, 11), date(2016, 2, 29), date(2019, 12, 10)])}
91
+ data = {"a": [date(2019, 7, 11), date(2016, 2, 29), date(2019, 12, 10)]}
92
+ tbl.update(data)
93
+ assert tbl.schema() == {"a": "date"}
94
+ arr = tbl.view().to_arrow()
95
+ tbl2 = Table(arr)
96
+
97
+ def ts(x):
98
+ return int(datetime.timestamp(x) * 1000)
99
+
100
+ assert tbl2.schema() == tbl.schema()
101
+ assert tbl2.view().to_columns() == {
102
+ "a": [
103
+ ts(datetime(2019, 7, 11)),
104
+ ts(datetime(2016, 2, 29)),
105
+ ts(datetime(2019, 12, 10)),
106
+ ]
107
+ }
108
+
109
+ def test_to_arrow_date_symmetric_january(self, util):
110
+ data = {"a": [date(2019, 1, 1), date(2016, 1, 1), date(2019, 1, 1)]}
111
+ tbl = Table(data)
112
+ assert tbl.schema() == {"a": "date"}
113
+ arr = tbl.view().to_arrow()
114
+ tbl2 = Table(arr)
115
+ assert tbl2.schema() == tbl.schema()
116
+ assert tbl2.view().to_columns() == {
117
+ "a": [
118
+ util.to_timestamp(x)
119
+ for x in [
120
+ datetime(2019, 1, 1),
121
+ datetime(2016, 1, 1),
122
+ datetime(2019, 1, 1),
123
+ ]
124
+ ]
125
+ }
126
+
127
+ def test_to_arrow_datetime_symmetric(self, util):
128
+ data = {
129
+ "a": [
130
+ datetime(2019, 7, 11, 12, 30),
131
+ datetime(2016, 2, 29, 11, 0),
132
+ datetime(2019, 12, 10, 12, 0),
133
+ ]
134
+ }
135
+ tbl = Table(data)
136
+ assert tbl.schema() == {"a": "datetime"}
137
+ arr = tbl.view().to_arrow()
138
+ tbl2 = Table(arr)
139
+ assert tbl2.schema() == tbl.schema()
140
+ assert tbl2.view().to_columns() == {
141
+ "a": [
142
+ util.to_timestamp(x)
143
+ for x in [
144
+ datetime(2019, 7, 11, 12, 30),
145
+ datetime(2016, 2, 29, 11, 0),
146
+ datetime(2019, 12, 10, 12, 0),
147
+ ]
148
+ ]
149
+ }
150
+
151
+ def test_to_arrow_one_symmetric(self):
152
+ data = {
153
+ "a": [1, 2, 3, 4],
154
+ "b": ["a", "b", "c", "d"],
155
+ "c": [
156
+ datetime(2019, 7, 11, 12, 0),
157
+ datetime(2019, 7, 11, 12, 10),
158
+ datetime(2019, 7, 11, 12, 20),
159
+ datetime(2019, 7, 11, 12, 30),
160
+ ],
161
+ }
162
+ tbl = Table(data)
163
+ view = tbl.view(group_by=["a"])
164
+ arrow = view.to_arrow()
165
+ tbl2 = Table(arrow)
166
+ assert tbl2.schema() == {
167
+ "a (Group by 1)": "integer",
168
+ "a": "integer",
169
+ "b": "integer",
170
+ "c": "integer",
171
+ }
172
+ d = view.to_columns()
173
+ d["a (Group by 1)"] = [
174
+ x[0] if len(x) > 0 else None for x in d.pop("__ROW_PATH__")
175
+ ]
176
+ assert tbl2.view().to_columns() == d
177
+
178
+ def test_to_arrow_two_symmetric(self):
179
+ data = {
180
+ "a": [1, 2, 3, 4],
181
+ "b": ["hello", "world", "hello2", "world2"],
182
+ "c": [datetime(2019, 7, 11, 12, i) for i in range(0, 40, 10)],
183
+ }
184
+ tbl = Table(data)
185
+ view = tbl.view(group_by=["a"], split_by=["b"])
186
+ arrow = view.to_arrow()
187
+ tbl2 = Table(arrow)
188
+ assert tbl2.schema() == {
189
+ "a (Group by 1)": "integer",
190
+ "hello|a": "integer",
191
+ "hello|b": "integer",
192
+ "hello|c": "integer",
193
+ "world|a": "integer",
194
+ "world|b": "integer",
195
+ "world|c": "integer",
196
+ "hello2|a": "integer",
197
+ "hello2|b": "integer",
198
+ "hello2|c": "integer",
199
+ "world2|a": "integer",
200
+ "world2|b": "integer",
201
+ "world2|c": "integer",
202
+ }
203
+ d = view.to_columns()
204
+ d["a (Group by 1)"] = [
205
+ x[0] if len(x) > 0 else None for x in d.pop("__ROW_PATH__")
206
+ ]
207
+ assert tbl2.view().to_columns() == d
208
+
209
+ def test_to_arrow_column_only_symmetric(self):
210
+ data = {
211
+ "a": [1, 2, 3, 4],
212
+ "b": ["a", "b", "c", "d"],
213
+ "c": [datetime(2019, 7, 11, 12, i) for i in range(0, 40, 10)],
214
+ }
215
+ tbl = Table(data)
216
+ view = tbl.view(split_by=["a"])
217
+ arrow = view.to_arrow()
218
+ tbl2 = Table(arrow)
219
+ assert tbl2.schema() == {
220
+ "1|a": "integer",
221
+ "1|b": "string",
222
+ "1|c": "datetime",
223
+ "2|a": "integer",
224
+ "2|b": "string",
225
+ "2|c": "datetime",
226
+ "3|a": "integer",
227
+ "3|b": "string",
228
+ "3|c": "datetime",
229
+ "4|a": "integer",
230
+ "4|b": "string",
231
+ "4|c": "datetime",
232
+ }
233
+ d = view.to_columns()
234
+ assert tbl2.view().to_columns() == d
235
+
236
+ # start and end row
237
+ def test_to_arrow_start_row(self):
238
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
239
+ tbl = Table(data)
240
+ assert tbl.schema() == {"a": "integer", "b": "float"}
241
+ arr = tbl.view().to_arrow(start_row=3)
242
+ tbl2 = Table(arr)
243
+ assert tbl2.view().to_columns() == {"a": data["a"][3:], "b": data["b"][3:]}
244
+
245
+ def test_to_arrow_end_row(self):
246
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
247
+ tbl = Table(data)
248
+ assert tbl.schema() == {"a": "integer", "b": "float"}
249
+ arr = tbl.view().to_arrow(end_row=2)
250
+ tbl2 = Table(arr)
251
+ assert tbl2.view().to_columns() == {"a": data["a"][:2], "b": data["b"][:2]}
252
+
253
+ def test_to_arrow_start_end_row(self):
254
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
255
+ tbl = Table(data)
256
+ assert tbl.schema() == {"a": "integer", "b": "float"}
257
+ arr = tbl.view().to_arrow(start_row=2, end_row=3)
258
+ tbl2 = Table(arr)
259
+ assert tbl2.view().to_columns() == {"a": data["a"][2:3], "b": data["b"][2:3]}
260
+
261
+ def test_to_arrow_start_end_row_equiv(self):
262
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
263
+ tbl = Table(data)
264
+ assert tbl.schema() == {"a": "integer", "b": "float"}
265
+ arr = tbl.view().to_arrow(start_row=2, end_row=2)
266
+ tbl2 = Table(arr)
267
+ assert tbl2.view().to_columns() == {"a": [], "b": []}
268
+
269
+ def test_to_arrow_start_row_invalid(self):
270
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
271
+ tbl = Table(data)
272
+ assert tbl.schema() == {"a": "integer", "b": "float"}
273
+ arr = tbl.view().to_arrow(start_row=-1)
274
+ tbl2 = Table(arr)
275
+ assert tbl2.view().to_columns() == data
276
+
277
+ def test_to_arrow_end_row_invalid(self):
278
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
279
+ tbl = Table(data)
280
+ assert tbl.schema() == {"a": "integer", "b": "float"}
281
+ arr = tbl.view().to_arrow(end_row=6)
282
+ tbl2 = Table(arr)
283
+ assert tbl2.view().to_columns() == data
284
+
285
+ def test_to_arrow_start_end_row_invalid(self):
286
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
287
+ tbl = Table(data)
288
+ assert tbl.schema() == {"a": "integer", "b": "float"}
289
+ arr = tbl.view().to_arrow(start_row=-1, end_row=6)
290
+ tbl2 = Table(arr)
291
+ assert tbl2.view().to_columns() == data
292
+
293
+ def test_to_arrow_start_col(self):
294
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
295
+ tbl = Table(data)
296
+ assert tbl.schema() == {"a": "integer", "b": "float"}
297
+ arr = tbl.view().to_arrow(start_col=1)
298
+ tbl2 = Table(arr)
299
+ assert tbl2.view().to_columns() == {"b": data["b"]}
300
+
301
+ def test_to_arrow_end_col(self):
302
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
303
+ tbl = Table(data)
304
+ assert tbl.schema() == {"a": "integer", "b": "float"}
305
+ arr = tbl.view().to_arrow(end_col=1)
306
+ tbl2 = Table(arr)
307
+ assert tbl2.view().to_columns() == {"a": data["a"]}
308
+
309
+ def test_to_arrow_start_end_col(self):
310
+ data = {
311
+ "a": [None, 1, None, 2, 3],
312
+ "b": [1.5, 2.5, None, 3.5, None],
313
+ "c": [None, 1, None, 2, 3],
314
+ "d": [1.5, 2.5, None, 3.5, None],
315
+ }
316
+ tbl = Table(data)
317
+ assert tbl.schema() == {
318
+ "a": "integer",
319
+ "b": "float",
320
+ "c": "integer",
321
+ "d": "float",
322
+ }
323
+ arr = tbl.view().to_arrow(start_col=1, end_col=3)
324
+ tbl2 = Table(arr)
325
+ assert tbl2.view().to_columns() == {"b": data["b"], "c": data["c"]}
326
+
327
+ def test_to_arrow_start_col_invalid(self):
328
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
329
+ tbl = Table(data)
330
+ assert tbl.schema() == {"a": "integer", "b": "float"}
331
+ arr = tbl.view().to_arrow(start_col=-1)
332
+ tbl2 = Table(arr)
333
+ assert tbl2.view().to_columns() == data
334
+
335
+ def test_to_arrow_end_col_invalid(self):
336
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
337
+ tbl = Table(data)
338
+ assert tbl.schema() == {"a": "integer", "b": "float"}
339
+ arr = tbl.view().to_arrow(end_col=6)
340
+ tbl2 = Table(arr)
341
+ assert tbl2.view().to_columns() == data
342
+
343
+ def test_to_arrow_start_end_col_invalid(self):
344
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
345
+ tbl = Table(data)
346
+ assert tbl.schema() == {"a": "integer", "b": "float"}
347
+ arr = tbl.view().to_arrow(start_col=-1, end_col=6)
348
+ tbl2 = Table(arr)
349
+ assert tbl2.view().to_columns() == data
350
+
351
+ def test_to_arrow_start_end_col_equiv_row(self):
352
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
353
+ tbl = Table(data)
354
+ assert tbl.schema() == {"a": "integer", "b": "float"}
355
+ arr = tbl.view().to_arrow(start_col=1, end_col=1, start_row=2, end_row=3)
356
+ tbl2 = Table(arr)
357
+ # start/end col is a range - thus start=end provides no columns
358
+ assert tbl2.view().to_columns() == {}
359
+
360
+ def test_to_arrow_start_end_col_equiv(self):
361
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
362
+ tbl = Table(data)
363
+ assert tbl.schema() == {"a": "integer", "b": "float"}
364
+ arr = tbl.view().to_arrow(start_col=1, end_col=1)
365
+ tbl2 = Table(arr)
366
+ assert tbl2.view().to_columns() == {}
367
+
368
+ def test_to_arrow_start_end_row_end_col(self):
369
+ data = {"a": [None, 1, None, 2, 3], "b": [1.5, 2.5, None, 3.5, None]}
370
+ tbl = Table(data)
371
+ assert tbl.schema() == {"a": "integer", "b": "float"}
372
+ arr = tbl.view().to_arrow(end_col=1, start_row=2, end_row=3)
373
+ tbl2 = Table(arr)
374
+ assert tbl2.view().to_columns() == tbl.view().to_columns(
375
+ end_col=1, start_row=2, end_row=3
376
+ )
377
+
378
+ def test_to_arrow_start_end_col_start_row(self):
379
+ data = {
380
+ "a": [None, 1, None, 2, 3],
381
+ "b": [1.5, 2.5, None, 3.5, None],
382
+ "c": [1.5, 2.5, None, 4.5, None],
383
+ }
384
+ tbl = Table(data)
385
+ assert tbl.schema() == {"a": "integer", "b": "float", "c": "float"}
386
+ arr = tbl.view().to_arrow(start_col=1, end_col=2, start_row=2)
387
+ tbl2 = Table(arr)
388
+ assert tbl2.view().to_columns() == tbl.view().to_columns(
389
+ start_col=1, end_col=2, start_row=2
390
+ )
391
+
392
+ def test_to_arrow_start_end_col_end_row(self):
393
+ data = {
394
+ "a": [None, 1, None, 2, 3],
395
+ "b": [1.5, 2.5, None, 3.5, None],
396
+ "c": [1.5, 2.5, None, 4.5, None],
397
+ }
398
+ tbl = Table(data)
399
+ assert tbl.schema() == {"a": "integer", "b": "float", "c": "float"}
400
+ arr = tbl.view().to_arrow(start_col=1, end_col=2, end_row=2)
401
+ tbl2 = Table(arr)
402
+ assert tbl2.view().to_columns() == tbl.view().to_columns(
403
+ start_col=1, end_col=2, end_row=2
404
+ )
405
+
406
+ def test_to_arrow_one_mean(self):
407
+ data = {"a": [1, 2, 3, 4], "b": ["a", "a", "b", "b"]}
408
+
409
+ table = Table(data)
410
+ view = table.view(group_by=["b"], columns=["a"], aggregates={"a": "mean"})
411
+ arrow = view.to_arrow()
412
+
413
+ table2 = Table(arrow)
414
+ view2 = table2.view()
415
+ result = view2.to_columns()
416
+
417
+ assert result == {"b (Group by 1)": [None, "a", "b"], "a": [2.5, 1.5, 3.5]}
@@ -0,0 +1,32 @@
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
+ import perspective as psp
14
+
15
+ client = psp.Server().new_local_client()
16
+ Table = client.table
17
+
18
+
19
+ class TestToArrowLZ4(object):
20
+ def test_to_arrow_lz4_roundtrip(self, superstore):
21
+ original_tbl = Table(superstore.to_dict(orient="records"))
22
+ arrow_uncompressed = original_tbl.view().to_arrow(compression=None)
23
+
24
+ tbl = Table(arrow_uncompressed)
25
+ arr = tbl.view().to_arrow(compression="lz4")
26
+ assert len(arr) < len(arrow_uncompressed)
27
+ tbl2 = Table(arr)
28
+ arr2 = tbl2.view().to_arrow(compression=None)
29
+ assert len(arr2) > len(arr)
30
+ tbl3 = Table(arr)
31
+ arr3 = tbl3.view().to_arrow(compression="lz4")
32
+ assert len(arr3) == len(arr)