perspective-python 3.0.0rc1__cp39-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 (70) hide show
  1. perspective/__init__.py +78 -0
  2. perspective/extension/finos-perspective-nbextension.json +5 -0
  3. perspective/handlers/__init__.py +26 -0
  4. perspective/handlers/aiohttp.py +54 -0
  5. perspective/handlers/starlette.py +51 -0
  6. perspective/handlers/tornado.py +61 -0
  7. perspective/perspective.pyd +0 -0
  8. perspective/templates/exported_widget.html.jinja +35 -0
  9. perspective/tests/__init__.py +11 -0
  10. perspective/tests/conftest.py +268 -0
  11. perspective/tests/core/__init__.py +11 -0
  12. perspective/tests/core/test_async.py +436 -0
  13. perspective/tests/core/test_threadpool.py +48 -0
  14. perspective/tests/server/__init__.py +11 -0
  15. perspective/tests/server/test_server.py +1062 -0
  16. perspective/tests/server/test_session.py +55 -0
  17. perspective/tests/single_threaded/test_single_threaded.py +61 -0
  18. perspective/tests/table/__init__.py +11 -0
  19. perspective/tests/table/arrow/date32.arrow +0 -0
  20. perspective/tests/table/arrow/date64.arrow +0 -0
  21. perspective/tests/table/arrow/dict.arrow +0 -0
  22. perspective/tests/table/arrow/dict_update.arrow +0 -0
  23. perspective/tests/table/arrow/int_float_str.arrow +0 -0
  24. perspective/tests/table/arrow/int_float_str_file.arrow +0 -0
  25. perspective/tests/table/arrow/int_float_str_update.arrow +0 -0
  26. perspective/tests/table/object_sequence.py +402 -0
  27. perspective/tests/table/test_delete.py +124 -0
  28. perspective/tests/table/test_exception.py +53 -0
  29. perspective/tests/table/test_leaks.py +54 -0
  30. perspective/tests/table/test_ports.py +178 -0
  31. perspective/tests/table/test_remove.py +102 -0
  32. perspective/tests/table/test_table.py +610 -0
  33. perspective/tests/table/test_table_arrow.py +452 -0
  34. perspective/tests/table/test_table_datetime.py +2409 -0
  35. perspective/tests/table/test_table_infer.py +201 -0
  36. perspective/tests/table/test_table_limit.py +43 -0
  37. perspective/tests/table/test_table_numpy.py +1022 -0
  38. perspective/tests/table/test_table_pandas.py +1018 -0
  39. perspective/tests/table/test_to_arrow.py +414 -0
  40. perspective/tests/table/test_to_arrow_lz4.py +33 -0
  41. perspective/tests/table/test_to_format.py +1024 -0
  42. perspective/tests/table/test_update.py +545 -0
  43. perspective/tests/table/test_update_arrow.py +980 -0
  44. perspective/tests/table/test_update_numpy.py +252 -0
  45. perspective/tests/table/test_update_pandas.py +211 -0
  46. perspective/tests/table/test_view.py +2235 -0
  47. perspective/tests/table/test_view_expression.py +1940 -0
  48. perspective/tests/viewer/__init__.py +11 -0
  49. perspective/tests/viewer/test_validate.py +70 -0
  50. perspective/tests/viewer/test_viewer.py +245 -0
  51. perspective/tests/widget/__init__.py +11 -0
  52. perspective/tests/widget/test_widget.py +278 -0
  53. perspective/tests/widget/test_widget_pandas.py +453 -0
  54. perspective/viewer/__init__.py +15 -0
  55. perspective/viewer/validate.py +22 -0
  56. perspective/viewer/viewer.py +331 -0
  57. perspective/viewer/viewer_traitlets.py +101 -0
  58. perspective/widget/__init__.py +16 -0
  59. perspective/widget/widget.py +269 -0
  60. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/install.json +5 -0
  61. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/package.json +81 -0
  62. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/static/253.6f17b87bb4eb1e656365.js +18 -0
  63. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/static/253.6f17b87bb4eb1e656365.js.LICENSE.txt +59 -0
  64. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/static/905.d3bbc3d5954582d507bb.js +1 -0
  65. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/static/remoteEntry.7044010cbbf2a7208035.js +1 -0
  66. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/static/style.js +4 -0
  67. perspective.data/data/share/jupyter/labextensions/@finos/perspective-jupyterlab/static/third-party-licenses.json +16 -0
  68. perspective_python-3.0.0rc1.dist-info/METADATA +13 -0
  69. perspective_python-3.0.0rc1.dist-info/RECORD +70 -0
  70. perspective_python-3.0.0rc1.dist-info/WHEEL +4 -0
@@ -0,0 +1,252 @@
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 numpy as np
14
+ from datetime import date, datetime
15
+ from pytest import mark
16
+ import pytest
17
+ import perspective as psp
18
+
19
+ client = psp.Server().new_local_client()
20
+ Table = client.table
21
+
22
+
23
+ @mark.skip
24
+ class TestUpdateNumpy(object):
25
+ def test_update_np(self):
26
+ tbl = Table({"a": [1, 2, 3, 4]})
27
+ tbl.update({"a": np.array([5, 6, 7, 8])})
28
+ assert tbl.view().to_columns() == {"a": [1, 2, 3, 4, 5, 6, 7, 8]}
29
+
30
+ def test_update_np_one_col(self):
31
+ tbl = Table({"a": np.array([1, 2, 3, 4]), "b": np.array([2, 3, 4, 5])})
32
+ tbl.update({"a": np.array([5, 6, 7, 8])})
33
+ assert tbl.view().to_columns() == {
34
+ "a": [1, 2, 3, 4, 5, 6, 7, 8],
35
+ "b": [2, 3, 4, 5, None, None, None, None],
36
+ }
37
+
38
+ def test_update_np_bool_str(self):
39
+ tbl = Table({"a": [True]})
40
+
41
+ assert tbl.schema() == {"a": "boolean"}
42
+
43
+ tbl.update({"a": np.array(["False"])})
44
+
45
+ assert tbl.view().to_columns() == {"a": [True, False]}
46
+
47
+ def test_update_np_date(self):
48
+ tbl = Table({"a": [date(2019, 7, 11)]})
49
+
50
+ assert tbl.schema() == {"a": "date"}
51
+
52
+ tbl.update({"a": np.array([date(2019, 7, 12)])})
53
+
54
+ assert tbl.view().to_columns() == {
55
+ "a": [datetime(2019, 7, 11), datetime(2019, 7, 12)]
56
+ }
57
+
58
+ def test_update_np_date_timestamp(self, util):
59
+ tbl = Table({"a": [date(2019, 7, 11)]})
60
+
61
+ assert tbl.schema() == {"a": "date"}
62
+
63
+ ts = util.to_timestamp(datetime(2019, 7, 12))
64
+
65
+ tbl.update({"a": np.array([ts])})
66
+
67
+ assert tbl.view().to_columns() == {
68
+ "a": [datetime(2019, 7, 11), datetime(2019, 7, 12)]
69
+ }
70
+
71
+ def test_update_np_datetime(self):
72
+ tbl = Table({"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))]})
73
+
74
+ tbl.update({"a": np.array([datetime(2019, 7, 12, 11, 0)], dtype=datetime)})
75
+
76
+ assert tbl.view().to_columns() == {
77
+ "a": [datetime(2019, 7, 11, 11, 0), datetime(2019, 7, 12, 11, 0)]
78
+ }
79
+
80
+ def test_update_np_datetime_str(self):
81
+ tbl = Table({"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))]})
82
+
83
+ tbl.update({"a": np.array(["2019/7/12 11:00:00"])})
84
+
85
+ assert tbl.view().to_columns() == {
86
+ "a": [datetime(2019, 7, 11, 11, 0), datetime(2019, 7, 12, 11, 0)]
87
+ }
88
+
89
+ def test_update_np_datetime_timestamp_s(self, util):
90
+ tbl = Table({"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))]})
91
+
92
+ tbl.update({"a": np.array([util.to_timestamp(datetime(2019, 7, 12, 11, 0))])})
93
+
94
+ assert tbl.view().to_columns() == {
95
+ "a": [datetime(2019, 7, 11, 11, 0), datetime(2019, 7, 12, 11, 0)]
96
+ }
97
+
98
+ def test_update_np_datetime_timestamp_ms(self, util):
99
+ tbl = Table({"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))]})
100
+
101
+ tbl.update(
102
+ {"a": np.array([util.to_timestamp(datetime(2019, 7, 12, 11, 0)) * 1000])}
103
+ )
104
+
105
+ assert tbl.view().to_columns() == {
106
+ "a": [datetime(2019, 7, 11, 11, 0), datetime(2019, 7, 12, 11, 0)]
107
+ }
108
+
109
+ def test_update_np_partial(self):
110
+ tbl = Table({"a": [1, 2, 3, 4], "b": ["a", "b", "c", "d"]}, index="b")
111
+
112
+ tbl.update(
113
+ {
114
+ "a": np.array([5, 6, 7, 8]),
115
+ "b": np.array(["a", "b", "c", "d"], dtype=object),
116
+ }
117
+ )
118
+
119
+ assert tbl.view().to_columns() == {"a": [5, 6, 7, 8], "b": ["a", "b", "c", "d"]}
120
+
121
+ def test_update_np_partial_implicit(self):
122
+ tbl = Table({"a": [1, 2, 3, 4]})
123
+
124
+ tbl.update({"a": np.array([5, 6, 7, 8]), "__INDEX__": np.array([0, 1, 2, 3])})
125
+
126
+ assert tbl.view().to_columns() == {"a": [5, 6, 7, 8]}
127
+
128
+ def test_update_np_datetime_partial_implicit_timestamp_s(self, util):
129
+ tbl = Table({"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))]})
130
+
131
+ tbl.update(
132
+ {
133
+ "a": np.array([util.to_timestamp(datetime(2019, 7, 12, 11, 0))]),
134
+ "__INDEX__": np.array([0]),
135
+ }
136
+ )
137
+
138
+ assert tbl.view().to_columns() == {
139
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
140
+ }
141
+
142
+ def test_update_np_datetime_partial_implicit_timestamp_ms(self, util):
143
+ tbl = Table({"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))]})
144
+
145
+ tbl.update(
146
+ {
147
+ "a": np.array([util.to_timestamp(datetime(2019, 7, 12, 11, 0)) * 1000]),
148
+ "__INDEX__": np.array([0]),
149
+ }
150
+ )
151
+
152
+ assert tbl.view().to_columns() == {
153
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))]
154
+ }
155
+
156
+ def test_update_np_datetime_partial(self, util):
157
+ tbl = Table(
158
+ {"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))], "b": [1]}, index="b"
159
+ )
160
+
161
+ tbl.update(
162
+ {
163
+ "a": np.array([datetime(2019, 7, 12, 11, 0)], dtype=datetime),
164
+ "b": np.array([1]),
165
+ }
166
+ )
167
+
168
+ assert tbl.view().to_columns() == {
169
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))],
170
+ "b": [1],
171
+ }
172
+
173
+ def test_update_np_datetime_partial_timestamp_s(self, util):
174
+ tbl = Table(
175
+ {"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))], "idx": [1]},
176
+ index="idx",
177
+ )
178
+
179
+ tbl.update(
180
+ {
181
+ "a": np.array([util.to_timestamp(datetime(2019, 7, 12, 11, 0))]),
182
+ "idx": np.array([1]),
183
+ }
184
+ )
185
+
186
+ assert tbl.view().to_columns() == {
187
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))],
188
+ "idx": [1],
189
+ }
190
+
191
+ def test_update_np_datetime_partial_timestamp_ms(self, util):
192
+ tbl = Table(
193
+ {"a": [np.datetime64(datetime(2019, 7, 11, 11, 0))], "idx": [1]},
194
+ index="idx",
195
+ )
196
+
197
+ tbl.update(
198
+ {
199
+ "a": np.array([util.to_timestamp(datetime(2019, 7, 12, 11, 0)) * 1000]),
200
+ "idx": np.array([1]),
201
+ }
202
+ )
203
+
204
+ assert tbl.view().to_columns() == {
205
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))],
206
+ "idx": [1],
207
+ }
208
+
209
+ @pytest.mark.skip
210
+ def test_update_np_nonseq_partial(self):
211
+ tbl = Table({"a": [1, 2, 3, 4], "b": ["a", "b", "c", "d"]}, index="b")
212
+ tbl.update(
213
+ {"a": np.array([5, 6, 7]), "b": np.array(["a", "c", "d"], dtype=object)}
214
+ )
215
+
216
+ assert tbl.view().to_columns() == {"a": [5, 2, 6, 7], "b": ["a", "b", "c", "d"]}
217
+
218
+ @pytest.mark.skip
219
+ def test_update_np_with_none_partial(self):
220
+ tbl = Table({"a": [1, np.nan, 3], "b": ["a", None, "d"]}, index="b")
221
+ tbl.update({"a": np.array([4, 5]), "b": np.array(["a", "d"], dtype=object)})
222
+ assert tbl.view().to_columns() == {
223
+ "a": [None, 4, 5],
224
+ "b": [None, "a", "d"],
225
+ } # pkeys are ordered
226
+
227
+ @pytest.mark.skip
228
+ def test_update_np_unset_partial(self):
229
+ tbl = Table({"a": [1, 2, 3], "b": ["a", "b", "c"]}, index="b")
230
+ tbl.update(
231
+ {"a": np.array([None, None]), "b": np.array(["a", "c"], dtype=object)}
232
+ )
233
+
234
+ assert tbl.view().to_columns() == {"a": [None, 2, None], "b": ["a", "b", "c"]}
235
+
236
+ @pytest.mark.skip
237
+ def test_update_np_nan_partial(self):
238
+ tbl = Table({"a": [1, 2, 3], "b": ["a", "b", "c"]}, index="b")
239
+ tbl.update(
240
+ {"a": np.array([None, None]), "b": np.array(["a", "c"], dtype=object)}
241
+ )
242
+
243
+ assert tbl.view().to_columns() == {"a": [None, 2, None], "b": ["a", "b", "c"]}
244
+
245
+ def test_numpy_dict(self):
246
+ x = {"index": [1], "a": np.empty((1,), str)}
247
+ tbl = Table({"index": "integer", "a": "string"}, index="index")
248
+ tbl.update({"index": np.arange(5)})
249
+ assert tbl.view().to_columns() == {
250
+ "index": list(range(5)),
251
+ "a": [None for _ in range(5)],
252
+ }
@@ -0,0 +1,211 @@
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 numpy as np
14
+ import pandas as pd
15
+ from datetime import date, datetime
16
+ from pytest import mark
17
+ import pytest
18
+ import perspective as psp
19
+
20
+ client = psp.Server().new_local_client()
21
+ Table = client.table
22
+
23
+
24
+ class TestUpdatePandas(object):
25
+ def test_update_df(self):
26
+ tbl = Table({"a": [1, 2, 3, 4]})
27
+
28
+ update_data = pd.DataFrame({"a": [5, 6, 7, 8]})
29
+
30
+ tbl.update(update_data)
31
+
32
+ assert tbl.view().to_columns() == {"a": [1, 2, 3, 4, 5, 6, 7, 8]}
33
+
34
+ def test_update_df_i32_vs_i64(self):
35
+ tbl = Table({"a": "integer"})
36
+
37
+ update_data = pd.DataFrame({"a": np.array([5, 6, 7, 8], dtype="int64")})
38
+
39
+ tbl.update(update_data)
40
+
41
+ assert tbl.view().to_columns() == {"a": [5, 6, 7, 8]}
42
+
43
+ def test_update_df_bool(self):
44
+ tbl = Table({"a": [True, False, True, False]})
45
+
46
+ update_data = pd.DataFrame({"a": [True, False, True, False]})
47
+
48
+ tbl.update(update_data)
49
+
50
+ assert tbl.view().to_columns() == {
51
+ "a": [True, False, True, False, True, False, True, False]
52
+ }
53
+
54
+ def test_update_df_str(self):
55
+ tbl = Table({"a": ["a", "b", "c", "d"]})
56
+
57
+ update_data = pd.DataFrame({"a": ["a", "b", "c", "d"]})
58
+
59
+ tbl.update(update_data)
60
+
61
+ assert tbl.view().to_columns() == {
62
+ "a": ["a", "b", "c", "d", "a", "b", "c", "d"]
63
+ }
64
+
65
+ def test_update_df_date(self, util):
66
+ # set_global_serializer(serializer)
67
+ tbl = Table({"a": [date(2019, 7, 11)]})
68
+
69
+ assert tbl.schema() == {"a": "date"}
70
+
71
+ update_data = pd.DataFrame({"a": [date(2019, 7, 12)]})
72
+
73
+ tbl.update(update_data)
74
+ assert tbl.view().to_columns() == {
75
+ "a": [
76
+ util.to_timestamp(d)
77
+ for d in [datetime(2019, 7, 11), datetime(2019, 7, 12)]
78
+ ]
79
+ }
80
+
81
+ @mark.skip(reason="this test relies on a lossy conversion from datetime -> date.")
82
+ def test_update_df_date_timestamp(self, util):
83
+ tbl = Table({"a": [date(2019, 7, 11)]})
84
+
85
+ assert tbl.schema() == {"a": "date"}
86
+
87
+ update_data = pd.DataFrame({"a": [datetime(2019, 7, 12, 0, 0, 0)]})
88
+
89
+ tbl.update(update_data)
90
+ assert tbl.view().to_columns() == {
91
+ "a": [
92
+ util.to_timestamp(datetime(2019, 7, 11)),
93
+ util.to_timestamp(datetime(2019, 7, 12)),
94
+ ]
95
+ }
96
+
97
+ def test_update_df_datetime(self, util):
98
+ tbl = Table({"a": [datetime(2019, 7, 11, 11, 0)]})
99
+
100
+ update_data = pd.DataFrame({"a": [datetime(2019, 7, 12, 11, 0)]})
101
+
102
+ tbl.update(update_data)
103
+ assert tbl.view().to_columns() == {
104
+ "a": [
105
+ util.to_timestamp(datetime(2019, 7, 11, 11, 0)),
106
+ util.to_timestamp(datetime(2019, 7, 12, 11, 0)),
107
+ ]
108
+ }
109
+
110
+ def test_update_df_datetime_timestamp_seconds(self, util):
111
+ tbl = Table({"a": [datetime(2019, 7, 11, 11, 0)]})
112
+
113
+ update_data = pd.DataFrame({"a": [datetime(2019, 7, 12, 11, 0)]})
114
+
115
+ tbl.update(update_data)
116
+ assert tbl.view().to_columns() == {
117
+ "a": [
118
+ util.to_timestamp(datetime(2019, 7, 11, 11, 0)),
119
+ util.to_timestamp(datetime(2019, 7, 12, 11, 0)),
120
+ ]
121
+ }
122
+
123
+ def test_update_df_datetime_timestamp_ms(self, util):
124
+ tbl = Table({"a": [datetime(2019, 7, 11, 11, 0)]})
125
+
126
+ update_data = pd.DataFrame({"a": [datetime(2019, 7, 12, 11, 0)]})
127
+
128
+ tbl.update(update_data)
129
+ assert tbl.view().to_columns() == {
130
+ "a": [
131
+ util.to_timestamp(datetime(2019, 7, 11, 11, 0)),
132
+ util.to_timestamp(datetime(2019, 7, 12, 11, 0)),
133
+ ]
134
+ }
135
+
136
+ def test_update_df_partial(self):
137
+ tbl = Table({"a": [1, 2, 3, 4], "b": ["a", "b", "c", "d"]}, index="b")
138
+
139
+ update_data = pd.DataFrame({"a": [5, 6, 7, 8], "b": ["a", "b", "c", "d"]})
140
+
141
+ tbl.update(update_data)
142
+
143
+ assert tbl.view().to_columns() == {"a": [5, 6, 7, 8], "b": ["a", "b", "c", "d"]}
144
+
145
+ def test_df_update_index(self):
146
+ tbl = Table(pd.DataFrame({"a": [1, 2, 3, 4]}))
147
+ update_data = pd.DataFrame({"a": [5, 6, 7, 8], "__INDEX__": [0, 1, 2, 3]})
148
+ tbl.update(update_data)
149
+ assert tbl.view().to_columns() == {"a": [5, 6, 7, 8], "index": [0, 1, 2, 3]}
150
+
151
+ def test_update_df_partial_implicit(self):
152
+ tbl = Table({"a": [1, 2, 3, 4]})
153
+
154
+ update_data = pd.DataFrame({"a": [5, 6, 7, 8], "__INDEX__": [0, 1, 2, 3]})
155
+
156
+ tbl.update(update_data)
157
+
158
+ assert tbl.view().to_columns() == {"a": [5, 6, 7, 8]}
159
+
160
+ def test_update_df_datetime_partial(self, util):
161
+ tbl = Table({"a": [datetime(2019, 7, 11, 11, 0)], "b": [1]}, index="b")
162
+
163
+ update_data = pd.DataFrame({"a": [datetime(2019, 7, 12, 11, 0)], "b": [1]})
164
+
165
+ tbl.update(update_data)
166
+
167
+ assert tbl.view().to_columns() == {
168
+ "a": [util.to_timestamp(datetime(2019, 7, 12, 11, 0))],
169
+ "b": [1],
170
+ }
171
+
172
+ def test_update_df_one_col(self):
173
+ tbl = Table({"a": [1, 2, 3, 4], "b": ["a", "b", "c", "d"]})
174
+ update_data = pd.DataFrame({"a": [5, 6, 7]})
175
+ tbl.update(update_data)
176
+ assert tbl.view().to_columns() == {
177
+ "a": [1, 2, 3, 4, 5, 6, 7],
178
+ "b": ["a", "b", "c", "d", None, None, None],
179
+ }
180
+
181
+ def test_update_df_nonseq_partial(self):
182
+ tbl = Table({"a": [1, 2, 3, 4], "b": ["a", "b", "c", "d"]}, index="b")
183
+ update_data = pd.DataFrame({"a": [5, 6, 7], "b": ["a", "c", "d"]})
184
+ tbl.update(update_data)
185
+ assert tbl.view().to_columns() == {"a": [5, 2, 6, 7], "b": ["a", "b", "c", "d"]}
186
+
187
+ @pytest.mark.skip
188
+ def test_update_df_with_none_partial(self):
189
+ tbl = Table({"a": [1, float("nan"), 3], "b": ["a", None, "d"]}, index="b")
190
+ update_data = pd.DataFrame({"a": [4, 5], "b": ["a", "d"]})
191
+ tbl.update(update_data)
192
+ assert tbl.view().to_columns() == {
193
+ "a": [None, 4, 5],
194
+ "b": [None, "a", "d"],
195
+ } # pkeys are ordered
196
+
197
+ def test_update_df_unset_partial(self):
198
+ tbl = Table({"a": [1, 2, 3], "b": ["a", "b", "c"]}, index="b")
199
+ update_data = pd.DataFrame(
200
+ {"a": pd.Series([None, None], dtype=pd.Int32Dtype()), "b": ["a", "c"]}
201
+ )
202
+ tbl.update(update_data)
203
+ assert tbl.view().to_columns() == {"a": [None, 2, None], "b": ["a", "b", "c"]}
204
+
205
+ def test_update_df_nan_partial(self):
206
+ tbl = Table({"a": [1, 2, 3], "b": ["a", "b", "c"]}, index="b")
207
+ update_data = pd.DataFrame(
208
+ {"a": pd.Series([None, None], dtype=pd.Int32Dtype()), "b": ["a", "c"]}
209
+ )
210
+ tbl.update(update_data)
211
+ assert tbl.view().to_columns() == {"a": [None, 2, None], "b": ["a", "b", "c"]}