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,201 @@
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 perspective import Server
14
+
15
+ import asyncio
16
+ import random
17
+ import threading
18
+
19
+ from random import sample
20
+ from string import ascii_letters
21
+ from threading import Thread
22
+ from time import sleep
23
+
24
+ class TestServer(object):
25
+ def test_sync_updates_with_loop_callback_are_sync(self):
26
+ def feed(table):
27
+ y = 1000
28
+ while y > 0:
29
+ y -= 1
30
+ table.update([{"a": random.randint(0, 10), "index": y}])
31
+
32
+ perspective_server = Server()
33
+ loop = asyncio.new_event_loop()
34
+ thread = threading.Thread(target=loop.run_forever)
35
+ thread.start()
36
+
37
+ client = perspective_server.new_local_client()
38
+ table = client.table(
39
+ {"a": "integer", "index": "integer"}, index="index", name="test"
40
+ )
41
+
42
+ view = table.view()
43
+ global count
44
+ count = 0
45
+
46
+ def update(x):
47
+ global count
48
+ count += 1
49
+
50
+ view.on_update(update)
51
+ feed(table)
52
+ assert table.size() == 1000
53
+ assert count == 1000
54
+ loop.call_soon_threadsafe(loop.stop)
55
+ thread.join()
56
+ loop.close()
57
+
58
+ def test_concurrent_updates(self):
59
+ async def feed(table, loop):
60
+ y = 1000
61
+ while y > 0:
62
+ y -= 1
63
+ table.update([{"a": random.randint(0, 10), "index": y}])
64
+ await asyncio.sleep(0.001)
65
+
66
+ perspective_server = Server()
67
+ loop = asyncio.new_event_loop()
68
+ thread = threading.Thread(target=loop.run_forever)
69
+ thread.start()
70
+
71
+ client = perspective_server.new_local_client()
72
+ table = client.table(
73
+ {"a": "integer", "index": "integer"}, index="index", name="test"
74
+ )
75
+
76
+ view = table.view()
77
+ global count
78
+ count = 0
79
+
80
+ def update(x):
81
+ global count
82
+ count += 1
83
+
84
+ view.on_update(update)
85
+ asyncio.run_coroutine_threadsafe(feed(table, loop), loop).result()
86
+ assert table.size() == 1000
87
+ assert count == 1000
88
+ loop.call_soon_threadsafe(loop.stop)
89
+ thread.join()
90
+ loop.close()
91
+
92
+ def test_concurrent_updates_with_limit_tables_are_threadsafe(self):
93
+ TEST_ITERATIONS = 100
94
+ global running
95
+ perspective_server = Server()
96
+ client = perspective_server.new_local_client()
97
+ table = client.table(
98
+ {"col{}".format(i): "integer" for i in range(100)}, limit=100
99
+ )
100
+
101
+ running = True
102
+
103
+ # Create an updating thread that overlaps the index alot
104
+ def feed(table):
105
+ row = {"col{}".format(i): random.randint(0, 100) for i in range(100)}
106
+ while running:
107
+ table.update([row for _ in range(100)])
108
+
109
+ thread = threading.Thread(target=feed, args=(table,))
110
+ thread.start()
111
+
112
+ results = []
113
+
114
+ # Create a thread that serialized the table alot, checking for nulls
115
+ def feed2(table):
116
+ global running
117
+ view = table.view()
118
+ while len(results) < TEST_ITERATIONS:
119
+ arr = view.to_arrow()
120
+ table2 = client.table(arr)
121
+ view2 = table2.view()
122
+ json = view2.to_json(end_row=1)
123
+ view2.delete()
124
+ table2.delete()
125
+ results.append(json)
126
+
127
+ view.delete()
128
+ running = False
129
+
130
+ thread2 = threading.Thread(target=feed2, args=(table,))
131
+ thread2.start()
132
+
133
+ thread.join()
134
+ thread2.join()
135
+
136
+ assert table.size() == 100
137
+ for result in results:
138
+ for row in result:
139
+ for col, val in row.items():
140
+ assert val is not None
141
+
142
+ table.delete()
143
+
144
+ def test_concurrent_view_creation_on_separate_servers_are_threadsafe(self):
145
+ def run_perspective():
146
+ x = 1000
147
+ s = Server()
148
+ c = s.new_local_client()
149
+ t = c.table({"a": "string", "b": int})
150
+ t.view(expressions=["//tmp\nfalse"])
151
+ while x > 0:
152
+ t.update([{"a": "foo", "b": 42}])
153
+ x -= 1
154
+
155
+ thread1 = threading.Thread(target=run_perspective, daemon=True)
156
+ thread2 = threading.Thread(target=run_perspective, daemon=True)
157
+ thread1.start()
158
+ thread2.start()
159
+ thread1.join()
160
+ thread2.join()
161
+
162
+ def test_concurrent_view_creation_with_updates_are_threadsafe(self):
163
+ global running
164
+ s = Server()
165
+ schema = {
166
+ "a": "string",
167
+ "b": "string",
168
+ "c": "string",
169
+ }
170
+
171
+ group_bys = ["a", "b", "c"]
172
+ c = s.new_local_client()
173
+ t = c.table(schema, limit=10000)
174
+ running = True
175
+
176
+ def gen_views():
177
+ global running
178
+ for _ in range(100):
179
+ t.view(columns=list(schema.keys()), group_by=group_bys)
180
+ sleep(0.01)
181
+ running = False
182
+
183
+ def run_psp():
184
+ global running
185
+ while running:
186
+ t.update(
187
+ [
188
+ {
189
+ "a": "".join(sample(ascii_letters, 4)),
190
+ "b": "".join(sample(ascii_letters, 4)),
191
+ "c": "".join(sample(ascii_letters, 4)),
192
+ }
193
+ ]
194
+ )
195
+
196
+ thread1 = Thread(target=run_psp, daemon=True)
197
+ thread2 = Thread(target=gen_views, daemon=True)
198
+ thread1.start()
199
+ thread2.start()
200
+ thread1.join()
201
+ thread2.join()
@@ -0,0 +1,11 @@
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
+ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛