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.
- perspective/__init__.py +396 -0
- perspective/extension/finos-perspective-nbextension.json +5 -0
- perspective/handlers/__init__.py +11 -0
- perspective/handlers/aiohttp.py +61 -0
- perspective/handlers/starlette.py +55 -0
- perspective/handlers/tornado.py +184 -0
- perspective/perspective.pyd +0 -0
- perspective/templates/exported_widget.html.template +35 -0
- perspective/tests/__init__.py +11 -0
- perspective/tests/async/test_async_client.py +83 -0
- perspective/tests/async/test_websocket_client.py +124 -0
- perspective/tests/conftest.py +272 -0
- perspective/tests/core/__init__.py +11 -0
- perspective/tests/core/test_async.py +351 -0
- perspective/tests/multi_threaded/__init__.py +11 -0
- perspective/tests/multi_threaded/test_multi_threaded.py +201 -0
- perspective/tests/server/__init__.py +11 -0
- perspective/tests/server/test_server.py +1016 -0
- perspective/tests/server/test_session.py +110 -0
- perspective/tests/table/__init__.py +11 -0
- perspective/tests/table/arrow/date32.arrow +0 -0
- perspective/tests/table/arrow/date64.arrow +0 -0
- perspective/tests/table/arrow/dict.arrow +0 -0
- perspective/tests/table/arrow/dict_update.arrow +0 -0
- perspective/tests/table/arrow/int_float_str.arrow +0 -0
- perspective/tests/table/arrow/int_float_str_file.arrow +0 -0
- perspective/tests/table/arrow/int_float_str_update.arrow +0 -0
- perspective/tests/table/object_sequence.py +402 -0
- perspective/tests/table/test_column_paths.py +89 -0
- perspective/tests/table/test_delete.py +124 -0
- perspective/tests/table/test_exception.py +65 -0
- perspective/tests/table/test_leaks.py +54 -0
- perspective/tests/table/test_ports.py +178 -0
- perspective/tests/table/test_remove.py +102 -0
- perspective/tests/table/test_table.py +641 -0
- perspective/tests/table/test_table_arrow.py +503 -0
- perspective/tests/table/test_table_datetime.py +2409 -0
- perspective/tests/table/test_table_infer.py +201 -0
- perspective/tests/table/test_table_limit.py +45 -0
- perspective/tests/table/test_table_numpy.py +1022 -0
- perspective/tests/table/test_table_pandas.py +1018 -0
- perspective/tests/table/test_table_polars.py +251 -0
- perspective/tests/table/test_table_view_table.py +130 -0
- perspective/tests/table/test_to_arrow.py +417 -0
- perspective/tests/table/test_to_arrow_lz4.py +32 -0
- perspective/tests/table/test_to_format.py +1024 -0
- perspective/tests/table/test_to_polars.py +26 -0
- perspective/tests/table/test_update.py +545 -0
- perspective/tests/table/test_update_arrow.py +980 -0
- perspective/tests/table/test_update_pandas.py +211 -0
- perspective/tests/table/test_view.py +2261 -0
- perspective/tests/table/test_view_expression.py +1940 -0
- perspective/tests/test_dependencies.py +53 -0
- perspective/tests/viewer/__init__.py +11 -0
- perspective/tests/viewer/test_viewer.py +246 -0
- perspective/tests/widget/__init__.py +11 -0
- perspective/tests/widget/test_widget.py +278 -0
- perspective/tests/widget/test_widget_pandas.py +453 -0
- perspective/virtual_servers/__init__.py +134 -0
- perspective/virtual_servers/clickhouse.py +245 -0
- perspective/virtual_servers/duckdb.py +236 -0
- perspective/widget/__init__.py +349 -0
- perspective/widget/viewer/__init__.py +15 -0
- perspective/widget/viewer/validate.py +22 -0
- perspective/widget/viewer/viewer.py +343 -0
- perspective/widget/viewer/viewer_traitlets.py +101 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/install.json +5 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json +71 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/253.5f5c9e80605aa4106a28.js +2 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/253.5f5c9e80605aa4106a28.js.LICENSE.txt +25 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/523.c030af5d3c4f67ff83f6.js +1 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/remoteEntry.95a8ea1b44d96032833f.js +1 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/style.js +4 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/third-party-licenses.json +16 -0
- perspective_python-4.2.0.dist-info/METADATA +27 -0
- perspective_python-4.2.0.dist-info/RECORD +79 -0
- perspective_python-4.2.0.dist-info/WHEEL +4 -0
- perspective_python-4.2.0.dist-info/licenses/LICENSE.md +193 -0
- 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)
|