1
0

test_pandas_data_accessor.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. # Copyright 2021-2024 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. import inspect
  12. from datetime import datetime
  13. from importlib import util
  14. from unittest.mock import patch
  15. import pandas # type: ignore
  16. from flask import g
  17. from taipy.gui import Gui
  18. from taipy.gui.data.data_format import _DataFormat
  19. from taipy.gui.data.decimator import ScatterDecimator
  20. from taipy.gui.data.pandas_data_accessor import _PandasDataAccessor
  21. def test_simple_data(gui: Gui, helpers, small_dataframe):
  22. accessor = _PandasDataAccessor()
  23. pd = pandas.DataFrame(data=small_dataframe)
  24. ret_data = accessor.get_data(gui, "x", pd, {"start": 0, "end": -1}, _DataFormat.JSON)
  25. assert ret_data
  26. value = ret_data["value"]
  27. assert value
  28. assert value["rowcount"] == 3
  29. data = value["data"]
  30. assert len(data) == 3
  31. def test_simple_data_with_arrow(gui: Gui, helpers, small_dataframe):
  32. if util.find_spec("pyarrow"):
  33. accessor = _PandasDataAccessor()
  34. pd = pandas.DataFrame(data=small_dataframe)
  35. ret_data = accessor.get_data(gui, "x", pd, {"start": 0, "end": -1}, _DataFormat.APACHE_ARROW)
  36. assert ret_data
  37. value = ret_data["value"]
  38. assert value
  39. assert value["rowcount"] == 3
  40. data = value["data"]
  41. assert isinstance(data, bytes)
  42. def test_get_all_simple_data(gui: Gui, helpers, small_dataframe):
  43. accessor = _PandasDataAccessor()
  44. pd = pandas.DataFrame(data=small_dataframe)
  45. ret_data = accessor.get_data(gui, "x", pd, {"alldata": True}, _DataFormat.JSON)
  46. assert ret_data
  47. assert ret_data["alldata"] is True
  48. value = ret_data["value"]
  49. assert value
  50. data = value["data"]
  51. assert data == small_dataframe
  52. def test_slice(gui: Gui, helpers, small_dataframe):
  53. accessor = _PandasDataAccessor()
  54. pd = pandas.DataFrame(data=small_dataframe)
  55. value = accessor.get_data(gui, "x", pd, {"start": 0, "end": 1}, _DataFormat.JSON)["value"]
  56. assert value["rowcount"] == 3
  57. data = value["data"]
  58. assert len(data) == 2
  59. value = accessor.get_data(gui, "x", pd, {"start": "0", "end": "1"}, _DataFormat.JSON)["value"]
  60. data = value["data"]
  61. assert len(data) == 2
  62. def test_sort(gui: Gui, helpers, small_dataframe):
  63. accessor = _PandasDataAccessor()
  64. pd = pandas.DataFrame(data=small_dataframe)
  65. query = {"columns": ["name", "value"], "start": 0, "end": -1, "orderby": "name", "sort": "desc"}
  66. data = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)["value"]["data"]
  67. assert data[0]["name"] == "C"
  68. def test_aggregate(gui: Gui, helpers, small_dataframe):
  69. accessor = _PandasDataAccessor()
  70. pd = pandas.DataFrame(data=small_dataframe)
  71. pd = pandas.concat(
  72. [pd, pandas.DataFrame(data={"name": ["A"], "value": [4]})], axis=0, join="outer", ignore_index=True
  73. )
  74. query = {"columns": ["name", "value"], "start": 0, "end": -1, "aggregates": ["name"], "applies": {"value": "sum"}}
  75. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)["value"]
  76. assert value["rowcount"] == 3
  77. data = value["data"]
  78. assert next(v.get("value") for v in data if v.get("name") == "A") == 5
  79. def test_filters(gui: Gui, helpers, small_dataframe):
  80. accessor = _PandasDataAccessor()
  81. pd = pandas.DataFrame(data=small_dataframe)
  82. pd = pandas.concat(
  83. [pd, pandas.DataFrame(data={"name": ["A"], "value": [4]})], axis=0, join="outer", ignore_index=True
  84. )
  85. query = {
  86. "columns": ["name", "value"],
  87. "start": 0,
  88. "end": -1,
  89. "filters": [{"col": "name", "action": "!=", "value": ""}],
  90. }
  91. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  92. assert len(value["value"]["data"]) == 4
  93. query = {
  94. "columns": ["name", "value"],
  95. "start": 0,
  96. "end": -1,
  97. "filters": [{"col": "name", "action": "==", "value": ""}],
  98. }
  99. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  100. assert len(value["value"]["data"]) == 0
  101. query = {
  102. "columns": ["name", "value"],
  103. "start": 0,
  104. "end": -1,
  105. "filters": [{"col": "name", "action": "==", "value": "A"}],
  106. }
  107. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  108. assert len(value["value"]["data"]) == 2
  109. query = {
  110. "columns": ["name", "value"],
  111. "start": 0,
  112. "end": -1,
  113. "filters": [{"col": "name", "action": "==", "value": "A"}, {"col": "value", "action": "==", "value": 2}],
  114. }
  115. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  116. assert len(value["value"]["data"]) == 0
  117. query = {
  118. "columns": ["name", "value"],
  119. "start": 0,
  120. "end": -1,
  121. "filters": [{"col": "name", "action": "!=", "value": "A"}, {"col": "value", "action": "==", "value": 2}],
  122. }
  123. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  124. assert len(value["value"]["data"]) == 1
  125. assert value["value"]["data"][0]["_tp_index"] == 1
  126. def test_filter_by_date(gui: Gui, helpers, small_dataframe):
  127. accessor = _PandasDataAccessor()
  128. pd = pandas.DataFrame(data=small_dataframe)
  129. pd["a date"] = [
  130. datetime.fromisocalendar(2022, 28, 1),
  131. datetime.fromisocalendar(2022, 28, 2),
  132. datetime.fromisocalendar(2022, 28, 3),
  133. ]
  134. query = {
  135. "columns": ["name", "value"],
  136. "start": 0,
  137. "end": -1,
  138. "filters": [{"col": "a date", "action": ">", "value": datetime.fromisocalendar(2022, 28, 3).isoformat() + "Z"}],
  139. }
  140. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  141. assert len(value["value"]["data"]) == 0
  142. query = {
  143. "columns": ["name", "value"],
  144. "start": 0,
  145. "end": -1,
  146. "filters": [{"col": "a date", "action": ">", "value": datetime.fromisocalendar(2022, 28, 2).isoformat() + "Z"}],
  147. }
  148. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  149. assert len(value["value"]["data"]) == 1
  150. query = {
  151. "columns": ["name", "value"],
  152. "start": 0,
  153. "end": -1,
  154. "filters": [{"col": "a date", "action": "<", "value": datetime.fromisocalendar(2022, 28, 3).isoformat() + "Z"}],
  155. }
  156. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  157. assert len(value["value"]["data"]) == 2
  158. query = {
  159. "columns": ["name", "value"],
  160. "start": 0,
  161. "end": -1,
  162. "filters": [
  163. {"col": "a date", "action": "<", "value": datetime.fromisocalendar(2022, 28, 2).isoformat() + "Z"},
  164. {"col": "a date", "action": ">", "value": datetime.fromisocalendar(2022, 28, 2).isoformat() + "Z"},
  165. ],
  166. }
  167. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  168. assert len(value["value"]["data"]) == 0
  169. query = {
  170. "columns": ["name", "value"],
  171. "start": 0,
  172. "end": -1,
  173. "filters": [
  174. {"col": "a date", "action": "<", "value": datetime.fromisocalendar(2022, 28, 3).isoformat() + "Z"},
  175. {"col": "a date", "action": ">", "value": datetime.fromisocalendar(2022, 28, 1).isoformat() + "Z"},
  176. ],
  177. }
  178. value = accessor.get_data(gui, "x", pd, query, _DataFormat.JSON)
  179. assert len(value["value"]["data"]) == 1
  180. def test_decimator(gui: Gui, helpers, small_dataframe):
  181. a_decimator = ScatterDecimator() # noqa: F841
  182. accessor = _PandasDataAccessor()
  183. pd = pandas.DataFrame(data=small_dataframe)
  184. # set gui frame
  185. gui._set_frame(inspect.currentframe())
  186. gui.add_page("test", "<|Hello {a_decimator}|button|id={btn_id}|>")
  187. with patch("sys.argv", ["prog"]):
  188. gui.run(run_server=False)
  189. flask_client = gui._server.test_client()
  190. cid = helpers.create_scope_and_get_sid(gui)
  191. # Get the jsx once so that the page will be evaluated -> variable will be registered
  192. flask_client.get(f"/taipy-jsx/test?client_id={cid}")
  193. with gui.get_flask_app().test_request_context(f"/taipy-jsx/test/?client_id={cid}", data={"client_id": cid}):
  194. g.client_id = cid
  195. ret_data = accessor.get_data(
  196. gui,
  197. "x",
  198. pd,
  199. {
  200. "start": 0,
  201. "end": -1,
  202. "alldata": True,
  203. "decimatorPayload": {
  204. "decimators": [{"decimator": "a_decimator", "chartMode": "markers"}],
  205. "width": 100,
  206. },
  207. },
  208. _DataFormat.JSON,
  209. )
  210. assert ret_data
  211. value = ret_data["value"]
  212. assert value
  213. data = value["data"]
  214. assert len(data) == 2