dycw-utilities 0.165.2__tar.gz → 0.166.0__tar.gz

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 (211) hide show
  1. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/PKG-INFO +1 -1
  2. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/pyproject.toml +2 -2
  3. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_polars.py +165 -74
  4. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/__init__.py +1 -1
  5. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/polars.py +97 -20
  6. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/.gitignore +0 -0
  7. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/LICENSE +0 -0
  8. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/README.md +0 -0
  9. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/__init__.py +0 -0
  10. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/conftest.py +0 -0
  11. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/__init__.py +0 -0
  12. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_missing/__init__.py +0 -0
  13. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_missing/module.py +0 -0
  14. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/__init__.py +0 -0
  15. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/outer_1.py +0 -0
  16. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/outer_2.py +0 -0
  17. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  18. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  19. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  20. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  21. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_without/__init__.py +0 -0
  22. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_without/module_1.py +0 -0
  23. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/package_without/module_2.py +0 -0
  24. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/standalone.py +0 -0
  25. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/modules/with_imports.py +0 -0
  26. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  27. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  28. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  29. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  30. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  31. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  32. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  33. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  34. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_aeventkit.py +0 -0
  35. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_altair.py +0 -0
  36. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_asyncio.py +0 -0
  37. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_atomicwrites.py +0 -0
  38. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_atools.py +0 -0
  39. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_cachetools.py +0 -0
  40. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_click.py +0 -0
  41. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_concurrent.py +0 -0
  42. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_contextlib.py +0 -0
  43. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_contextvars.py +0 -0
  44. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_cryptography.py +0 -0
  45. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_cvxpy.py +0 -0
  46. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_dataclasses.py +0 -0
  47. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_enum.py +0 -0
  48. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_errors.py +0 -0
  49. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_fastapi.py +0 -0
  50. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_fpdf2.py +0 -0
  51. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_functions.py +0 -0
  52. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_functools.py +0 -0
  53. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_getpass.py +0 -0
  54. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_gzip.py +0 -0
  55. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_hashlib.py +0 -0
  56. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_http.py +0 -0
  57. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_hypothesis.py +0 -0
  58. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_importlib.py +0 -0
  59. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_inflect.py +0 -0
  60. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_ipython.py +0 -0
  61. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_iterables.py +0 -0
  62. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_json.py +0 -0
  63. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_jupyter.py +0 -0
  64. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_libcst.py +0 -0
  65. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_lightweight_charts.py +0 -0
  66. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_logging.py +0 -0
  67. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_math.py +0 -0
  68. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_memory_profiler.py +0 -0
  69. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_modules.py +0 -0
  70. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_more_itertools.py +0 -0
  71. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_numpy.py +0 -0
  72. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_objects/__init__.py +0 -0
  73. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_objects/objects.py +0 -0
  74. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_operator.py +0 -0
  75. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_optuna.py +0 -0
  76. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_orjson.py +0 -0
  77. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_os.py +0 -0
  78. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_parse.py +0 -0
  79. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pathlib.py +0 -0
  80. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pickle.py +0 -0
  81. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_platform.py +0 -0
  82. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_polars_ols.py +0 -0
  83. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_postgres.py +0 -0
  84. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pottery.py +0 -0
  85. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pqdm.py +0 -0
  86. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_psutil.py +0 -0
  87. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pyinstrument.py +0 -0
  88. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pytest.py +0 -0
  89. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pytest_randomly.py +0 -0
  90. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_pytest_regressions.py +0 -0
  91. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_random.py +0 -0
  92. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_re.py +0 -0
  93. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_redis.py +0 -0
  94. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_reprlib.py +0 -0
  95. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_scipy.py +0 -0
  96. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_sentinel.py +0 -0
  97. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_shelve.py +0 -0
  98. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_slack_sdk.py +0 -0
  99. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_socket.py +0 -0
  100. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_sqlalchemy.py +0 -0
  101. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_sqlalchemy_polars.py +0 -0
  102. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_statsmodels.py +0 -0
  103. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_string.py +0 -0
  104. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_tempfile.py +0 -0
  105. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_testbook.py +0 -0
  106. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_text.py +0 -0
  107. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_threading.py +0 -0
  108. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_timer.py +0 -0
  109. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_traceback.py +0 -0
  110. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_typed_settings.py +0 -0
  111. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_types.py +0 -0
  112. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_typing.py +0 -0
  113. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_typing_funcs/__init__.py +0 -0
  114. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_typing_funcs/no_future.py +0 -0
  115. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_typing_funcs/with_future.py +0 -0
  116. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_tzdata.py +0 -0
  117. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_tzlocal.py +0 -0
  118. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_uuid.py +0 -0
  119. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_version.py +0 -0
  120. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_warnings.py +0 -0
  121. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_whenever.py +0 -0
  122. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_zipfile.py +0 -0
  123. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/tests/test_zoneinfo.py +0 -0
  124. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/aeventkit.py +0 -0
  125. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/altair.py +0 -0
  126. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/asyncio.py +0 -0
  127. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/atomicwrites.py +0 -0
  128. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/atools.py +0 -0
  129. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/cachetools.py +0 -0
  130. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/click.py +0 -0
  131. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/concurrent.py +0 -0
  132. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/contextlib.py +0 -0
  133. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/contextvars.py +0 -0
  134. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/cryptography.py +0 -0
  135. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/cvxpy.py +0 -0
  136. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/dataclasses.py +0 -0
  137. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/enum.py +0 -0
  138. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/errors.py +0 -0
  139. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/fastapi.py +0 -0
  140. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/fpdf2.py +0 -0
  141. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/functions.py +0 -0
  142. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/functools.py +0 -0
  143. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/getpass.py +0 -0
  144. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/gzip.py +0 -0
  145. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/hashlib.py +0 -0
  146. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/http.py +0 -0
  147. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/hypothesis.py +0 -0
  148. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/importlib.py +0 -0
  149. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/inflect.py +0 -0
  150. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/ipython.py +0 -0
  151. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/iterables.py +0 -0
  152. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/json.py +0 -0
  153. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/jupyter.py +0 -0
  154. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/libcst.py +0 -0
  155. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/lightweight_charts.py +0 -0
  156. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/logging.py +0 -0
  157. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/math.py +0 -0
  158. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/memory_profiler.py +0 -0
  159. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/modules.py +0 -0
  160. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/more_itertools.py +0 -0
  161. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/numpy.py +0 -0
  162. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/operator.py +0 -0
  163. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/optuna.py +0 -0
  164. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/orjson.py +0 -0
  165. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/os.py +0 -0
  166. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/parse.py +0 -0
  167. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pathlib.py +0 -0
  168. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pickle.py +0 -0
  169. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/platform.py +0 -0
  170. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/polars_ols.py +0 -0
  171. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/postgres.py +0 -0
  172. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pottery.py +0 -0
  173. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pqdm.py +0 -0
  174. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/psutil.py +0 -0
  175. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/py.typed +0 -0
  176. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pyinstrument.py +0 -0
  177. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pytest.py +0 -0
  178. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pytest_plugins/__init__.py +0 -0
  179. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pytest_plugins/pytest_randomly.py +0 -0
  180. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pytest_plugins/pytest_regressions.py +0 -0
  181. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/pytest_regressions.py +0 -0
  182. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/random.py +0 -0
  183. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/re.py +0 -0
  184. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/redis.py +0 -0
  185. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/reprlib.py +0 -0
  186. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/scipy.py +0 -0
  187. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/sentinel.py +0 -0
  188. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/shelve.py +0 -0
  189. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/slack_sdk.py +0 -0
  190. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/socket.py +0 -0
  191. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/sqlalchemy.py +0 -0
  192. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/sqlalchemy_polars.py +0 -0
  193. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/statsmodels.py +0 -0
  194. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/string.py +0 -0
  195. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/tempfile.py +0 -0
  196. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/testbook.py +0 -0
  197. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/text.py +0 -0
  198. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/threading.py +0 -0
  199. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/timer.py +0 -0
  200. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/traceback.py +0 -0
  201. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/typed_settings.py +0 -0
  202. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/types.py +0 -0
  203. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/typing.py +0 -0
  204. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/tzdata.py +0 -0
  205. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/tzlocal.py +0 -0
  206. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/uuid.py +0 -0
  207. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/version.py +0 -0
  208. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/warnings.py +0 -0
  209. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/whenever.py +0 -0
  210. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/zipfile.py +0 -0
  211. {dycw_utilities-0.165.2 → dycw_utilities-0.166.0}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.165.2
3
+ Version: 0.166.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -233,7 +233,7 @@ dependencies = [
233
233
  name = "dycw-utilities"
234
234
  readme = "README.md"
235
235
  requires-python = ">= 3.12"
236
- version = "0.165.2"
236
+ version = "0.166.0"
237
237
 
238
238
  [project.entry-points.pytest11]
239
239
  pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
@@ -266,7 +266,7 @@ test = [
266
266
  # bump-my-version
267
267
  [tool.bumpversion]
268
268
  allow_dirty = true
269
- current_version = "0.165.2"
269
+ current_version = "0.166.0"
270
270
 
271
271
  [[tool.bumpversion.files]]
272
272
  filename = "src/utilities/__init__.py"
@@ -83,7 +83,6 @@ from utilities.hypothesis import (
83
83
  from utilities.numpy import DEFAULT_RNG
84
84
  from utilities.pathlib import PWD
85
85
  from utilities.polars import (
86
- AppendDataClassError,
87
86
  BooleanValueCountsError,
88
87
  ColumnsToDictError,
89
88
  DatePeriodDType,
@@ -102,6 +101,10 @@ from utilities.polars import (
102
101
  SelectExactError,
103
102
  SetFirstRowAsColumnsError,
104
103
  TimePeriodDType,
104
+ _AppendRowExtraKeysError,
105
+ _AppendRowMissingKeysError,
106
+ _AppendRowNullColumnsError,
107
+ _AppendRowPredicateError,
105
108
  _check_polars_dataframe_predicates,
106
109
  _check_polars_dataframe_schema_list,
107
110
  _check_polars_dataframe_schema_set,
@@ -145,7 +148,7 @@ from utilities.polars import (
145
148
  all_series,
146
149
  any_dataframe_columns,
147
150
  any_series,
148
- append_dataclass,
151
+ append_row,
149
152
  are_frames_equal,
150
153
  bernoulli,
151
154
  boolean_value_counts,
@@ -194,6 +197,7 @@ from utilities.polars import (
194
197
  reify_exprs,
195
198
  replace_time_zone,
196
199
  round_to_float,
200
+ search_period,
197
201
  select_exact,
198
202
  serialize_dataframe,
199
203
  serialize_series,
@@ -224,6 +228,7 @@ from utilities.whenever import (
224
228
  get_now,
225
229
  get_now_plain,
226
230
  get_today,
231
+ to_zoned_date_time,
227
232
  )
228
233
  from utilities.zoneinfo import UTC, to_time_zone_name
229
234
 
@@ -358,91 +363,89 @@ class TestAnyAllDataFrameColumnsSeries:
358
363
  assert_series_equal(result, self.exp_any)
359
364
 
360
365
 
361
- class TestAppendDataClass:
362
- @given(
363
- data=fixed_dictionaries({
364
- "a": int64s() | none(),
365
- "b": floats() | none(),
366
- "c": text_ascii() | none(),
367
- })
368
- )
369
- def test_columns_and_fields_equal(self, *, data: StrMapping) -> None:
370
- df = DataFrame(schema={"a": Int64, "b": Float64, "c": String})
371
-
372
- @dataclass(kw_only=True, slots=True)
373
- class Row:
374
- a: int | None = None
375
- b: float | None = None
376
- c: str | None = None
377
-
378
- row = Row(**data)
379
- result = append_dataclass(df, row)
380
- height = 0 if (row.a is None) and (row.b is None) and (row.c is None) else 1
381
- check_polars_dataframe(result, height=height, schema_list=df.schema)
382
-
383
- @given(data=fixed_dictionaries({"a": int64s() | none(), "b": floats() | none()}))
384
- def test_extra_column(self, *, data: StrMapping) -> None:
385
- df = DataFrame(schema={"a": Int64, "b": Float64, "c": String})
366
+ class TestAppendRow:
367
+ rows: ClassVar[list[tuple[int, int]]] = [(i, 2 * i) for i in range(3)]
368
+ schema: ClassVar[SchemaDict] = {"x": Int64, "y": Int64}
369
+ df: ClassVar[DataFrame] = DataFrame(data=rows, schema=schema, orient="row")
386
370
 
387
- @dataclass(kw_only=True, slots=True)
388
- class Row:
389
- a: int | None = None
390
- b: float | None = None
371
+ @mark.parametrize(
372
+ "row", [param({"x": 3, "y": 6}), param({"x": 3, "y": 6, "z": None})]
373
+ )
374
+ def test_main(self, *, row: StrMapping) -> None:
375
+ result = append_row(self.df, row)
376
+ expected = DataFrame(
377
+ data=[*self.rows, (3, 6)], schema=self.schema, orient="row"
378
+ )
379
+ assert_frame_equal(result, expected)
391
380
 
392
- row = Row(**data)
393
- result = append_dataclass(df, row)
394
- height = 0 if (row.a is None) and (row.b is None) else 1
395
- check_polars_dataframe(result, height=height, schema_list=df.schema)
381
+ def test_missing_key(self) -> None:
382
+ row = {"x": 3}
383
+ result = append_row(self.df, row)
384
+ expected = DataFrame(
385
+ data=[*self.rows, (3, None)], schema=self.schema, orient="row"
386
+ )
387
+ assert_frame_equal(result, expected)
396
388
 
397
- @given(data=fixed_dictionaries({"a": int64s() | none(), "b": floats() | none()}))
398
- def test_extra_field_but_none(self, *, data: StrMapping) -> None:
399
- df = DataFrame(schema={"a": Int64, "b": Float64})
389
+ def test_disallow_missing_selected(self) -> None:
390
+ row = {"x": 3}
391
+ result = append_row(self.df, row, disallow_missing="x")
392
+ expected = DataFrame(
393
+ data=[*self.rows, (3, None)], schema=self.schema, orient="row"
394
+ )
395
+ assert_frame_equal(result, expected)
400
396
 
401
- @dataclass(kw_only=True, slots=True)
402
- class Row:
403
- a: int | None = None
404
- b: float | None = None
405
- c: str | None = None
397
+ def test_disallow_null_selected(self) -> None:
398
+ row = {"x": 3, "y": None}
399
+ result = append_row(self.df, row, disallow_null="x")
400
+ expected = DataFrame(
401
+ data=[*self.rows, (3, None)], schema=self.schema, orient="row"
402
+ )
403
+ assert_frame_equal(result, expected)
406
404
 
407
- row = Row(**data)
408
- result = append_dataclass(df, row)
409
- height = 0 if (row.a is None) and (row.b is None) else 1
410
- check_polars_dataframe(result, height=height, schema_list=df.schema)
405
+ def test_in_place(self) -> None:
406
+ df = DataFrame(data=self.rows, schema=self.schema, orient="row")
407
+ assert df.height == 3
408
+ row = {"x": 3, "y": 6}
409
+ _ = append_row(df, row, in_place=True)
410
+ assert df.height == 4
411
411
 
412
- @given(data=fixed_dictionaries({"datetime": zoned_date_times()}))
413
- def test_zoned_datetime(self, *, data: StrMapping) -> None:
414
- df = DataFrame(schema={"datetime": DatetimeUTC})
412
+ def test_error_predicate(self) -> None:
413
+ row = {"x": 3}
414
+ with raises(_AppendRowPredicateError, match="Predicate failed; got {'x': 3}"):
415
+ _ = append_row(self.df, row, predicate=lambda row: "y" in row)
415
416
 
416
- @dataclass(kw_only=True, slots=True)
417
- class Row:
418
- datetime: ZonedDateTime
417
+ def test_error_disallow_extra(self) -> None:
418
+ row = {"x": 3, "y": 6, "z": None}
419
+ with raises(_AppendRowExtraKeysError, match=r"Extra key\(s\) found; got {'z'}"):
420
+ _ = append_row(self.df, row, disallow_extra=True)
419
421
 
420
- row = Row(**data)
421
- result = append_dataclass(df, row)
422
- check_polars_dataframe(result, height=1, schema_list=df.schema)
422
+ def test_error_disallow_missing_all(self) -> None:
423
+ with raises(
424
+ _AppendRowMissingKeysError,
425
+ match=r"Missing key\(s\) found; got {'[xy]', '[xy]'}",
426
+ ):
427
+ _ = append_row(self.df, {}, disallow_missing=True)
423
428
 
424
- @given(
425
- data=fixed_dictionaries({
426
- "a": int64s() | none(),
427
- "b": floats() | none(),
428
- "c": text_ascii(),
429
- })
430
- )
431
- def test_error(self, *, data: StrMapping) -> None:
432
- df = DataFrame(schema={"a": Int64, "b": Float64})
429
+ def test_error_disallow_missing_selected(self) -> None:
430
+ with raises(
431
+ _AppendRowMissingKeysError, match=r"Missing key\(s\) found; got {'x'}"
432
+ ):
433
+ _ = append_row(self.df, {}, disallow_missing="x")
433
434
 
434
- @dataclass(kw_only=True, slots=True)
435
- class Row:
436
- a: int | None = None
437
- b: float | None = None
438
- c: str
435
+ def test_error_disallow_null_all(self) -> None:
436
+ row = {"x": None, "y": None}
437
+ with raises(
438
+ _AppendRowNullColumnsError,
439
+ match=r"Null column\(s\) found; got {'[xy]', '[xy]'}",
440
+ ):
441
+ _ = append_row(self.df, row, disallow_null=True)
439
442
 
440
- row = Row(**data)
443
+ def test_error_disallow_null_selected(self) -> None:
444
+ row = {"x": None, "y": None}
441
445
  with raises(
442
- AppendDataClassError,
443
- match="Dataclass fields .* must be a subset of DataFrame columns .*; dataclass had extra items .*",
446
+ _AppendRowNullColumnsError, match=r"Null column\(s\) found; got {'x'}"
444
447
  ):
445
- _ = append_dataclass(df, row)
448
+ _ = append_row(self.df, row, disallow_null="x")
446
449
 
447
450
 
448
451
  class TestAreFramesEqual:
@@ -2474,6 +2477,94 @@ class TestRoundToFloat:
2474
2477
  _ = round_to_float(cast("Any", x), cast("Any", y))
2475
2478
 
2476
2479
 
2480
+ class TestSearchPeriod:
2481
+ @mark.parametrize(
2482
+ ("time", "exp_start", "exp_end"),
2483
+ [
2484
+ param(whenever.Time(8, 58), None, None),
2485
+ param(whenever.Time(8, 59), None, None),
2486
+ param(whenever.Time(9), 0, None),
2487
+ param(whenever.Time(9, 1), 0, 0),
2488
+ param(whenever.Time(9, 59), 0, 0),
2489
+ param(whenever.Time(10), 1, 0),
2490
+ param(whenever.Time(10, 1), 1, 1),
2491
+ param(whenever.Time(10, 59), 1, 1),
2492
+ param(whenever.Time(11), 2, 1),
2493
+ param(whenever.Time(11, 1), 2, 2),
2494
+ param(whenever.Time(11, 59), 2, 2),
2495
+ param(whenever.Time(12), None, 2),
2496
+ param(whenever.Time(12, 1), None, None),
2497
+ param(whenever.Time(12, 59), None, None),
2498
+ param(whenever.Time(13), 3, None),
2499
+ param(whenever.Time(13, 1), 3, 3),
2500
+ param(whenever.Time(13, 59), 3, 3),
2501
+ param(whenever.Time(14), None, 3),
2502
+ param(whenever.Time(14, 1), None, None),
2503
+ param(whenever.Time(14, 59), None, None),
2504
+ param(whenever.Time(15), 4, None),
2505
+ param(whenever.Time(15, 1), 4, 4),
2506
+ param(whenever.Time(15, 59), 4, 4),
2507
+ param(whenever.Time(16), None, 4),
2508
+ param(whenever.Time(16, 1), None, None),
2509
+ param(whenever.Time(16, 2), None, None),
2510
+ ],
2511
+ )
2512
+ @mark.parametrize("start_or_end", [param("start"), param("end")])
2513
+ def test_main(
2514
+ self,
2515
+ *,
2516
+ time: whenever.Time,
2517
+ start_or_end: Literal["start", "end"],
2518
+ exp_start: int | None,
2519
+ exp_end: int | None,
2520
+ ) -> None:
2521
+ date = whenever.Date(2000, 1, 1)
2522
+ sr = DataFrame(
2523
+ data=[
2524
+ (
2525
+ date.at(whenever.Time(s)).py_datetime(),
2526
+ date.at(whenever.Time(e)).py_datetime(),
2527
+ )
2528
+ for s, e in [(9, 10), (10, 11), (11, 12), (13, 14), (15, 16)]
2529
+ ],
2530
+ schema={"start": DatetimeUTC, "end": DatetimeUTC},
2531
+ orient="row",
2532
+ ).with_columns(datetime=struct("start", "end"))["datetime"]
2533
+ assert len(sr) == 5
2534
+ date_time = date.at(time).assume_tz(UTC.key)
2535
+ match start_or_end:
2536
+ case "start":
2537
+ expected = exp_start
2538
+ case "end":
2539
+ expected = exp_end
2540
+ case never:
2541
+ assert_never(never)
2542
+ index = search_period(sr, date_time, start_or_end=start_or_end)
2543
+ if expected is None:
2544
+ assert index is None
2545
+ else:
2546
+ assert index is not None
2547
+ assert 0 <= index <= (len(sr) - 1)
2548
+ start, end = map(
2549
+ to_zoned_date_time, cast("Iterable[dt.datetime]", sr[index].values())
2550
+ )
2551
+ match start_or_end:
2552
+ case "start":
2553
+ assert start <= date_time < end
2554
+ case "end":
2555
+ assert start < date_time <= end
2556
+ case never:
2557
+ assert_never(never)
2558
+ if index > 0:
2559
+ prev_end = to_zoned_date_time(cast("dt.datetime", sr[index - 1]["end"]))
2560
+ assert prev_end <= date_time
2561
+ if index < (len(sr) - 1):
2562
+ next_start = to_zoned_date_time(
2563
+ cast("dt.datetime", sr[index + 1]["start"])
2564
+ )
2565
+ assert date_time <= next_start
2566
+
2567
+
2477
2568
  class TestSelectExact:
2478
2569
  df: ClassVar[DataFrame] = DataFrame(
2479
2570
  data=[(True, False), (False, None), (None, True)],
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.165.2"
3
+ __version__ = "0.166.0"
@@ -61,14 +61,12 @@ from utilities.gzip import read_binary
61
61
  from utilities.iterables import (
62
62
  CheckIterablesEqualError,
63
63
  CheckMappingsEqualError,
64
- CheckSubSetError,
65
64
  CheckSuperMappingError,
66
65
  OneEmptyError,
67
66
  OneNonUniqueError,
68
67
  always_iterable,
69
68
  check_iterables_equal,
70
69
  check_mappings_equal,
71
- check_subset,
72
70
  check_supermapping,
73
71
  is_iterable_not_str,
74
72
  one,
@@ -105,6 +103,7 @@ from utilities.whenever import (
105
103
  from utilities.zoneinfo import UTC, to_time_zone_name
106
104
 
107
105
  if TYPE_CHECKING:
106
+ import datetime as dt
108
107
  from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
109
108
  from collections.abc import Set as AbstractSet
110
109
 
@@ -300,29 +299,77 @@ def any_series(series: Series, /, *columns: ExprOrSeries) -> Series:
300
299
  ##
301
300
 
302
301
 
303
- def append_dataclass(df: DataFrame, obj: Dataclass, /) -> DataFrame:
304
- """Append a dataclass object to a DataFrame."""
305
- non_null_fields = {k: v for k, v in asdict(obj).items() if v is not None}
306
- try:
307
- check_subset(non_null_fields, df.columns)
308
- except CheckSubSetError as error:
309
- raise AppendDataClassError(
310
- left=error.left, right=error.right, extra=error.extra
311
- ) from None
312
- row_cols = set(df.columns) & set(non_null_fields)
313
- row = dataclass_to_dataframe(obj).select(*row_cols)
314
- return concat([df, row], how="diagonal")
302
+ def append_row(
303
+ df: DataFrame,
304
+ row: StrMapping,
305
+ /,
306
+ *,
307
+ predicate: Callable[[StrMapping], bool] | None = None,
308
+ disallow_extra: bool = False,
309
+ disallow_missing: bool | MaybeIterable[str] = False,
310
+ disallow_null: bool | MaybeIterable[str] = False,
311
+ in_place: bool = False,
312
+ ) -> DataFrame:
313
+ """Append a row to a DataFrame."""
314
+ if (predicate is not None) and not predicate(row):
315
+ raise _AppendRowPredicateError(df=df, row=row)
316
+ if disallow_extra and (len(extra := set(row) - set(df.columns)) >= 1):
317
+ raise _AppendRowExtraKeysError(df=df, row=row, extra=extra)
318
+ if disallow_missing is not False:
319
+ missing = set(df.columns) - set(row)
320
+ if disallow_missing is not True:
321
+ missing &= set(always_iterable(disallow_missing))
322
+ if len(missing) >= 1:
323
+ raise _AppendRowMissingKeysError(df=df, row=row, missing=missing)
324
+ other = DataFrame(data=[row], schema=df.schema)
325
+ if disallow_null:
326
+ other_null = other.select(col(c).is_null().any() for c in other.columns)
327
+ null = {k for k, v in other_null.row(0, named=True).items() if v}
328
+ if disallow_null is not True:
329
+ null &= set(always_iterable(disallow_null))
330
+ if len(null) >= 1:
331
+ raise _AppendRowNullColumnsError(df=df, row=row, columns=null)
332
+ return df.extend(other) if in_place else df.vstack(other)
333
+
334
+
335
+ @dataclass(kw_only=True, slots=True)
336
+ class AppendRowError(Exception):
337
+ df: DataFrame
338
+ row: StrMapping
339
+
340
+
341
+ @dataclass(kw_only=True, slots=True)
342
+ class _AppendRowPredicateError(AppendRowError):
343
+ @override
344
+ def __str__(self) -> str:
345
+ return f"Predicate failed; got {get_repr(self.row)}"
346
+
347
+
348
+ @dataclass(kw_only=True, slots=True)
349
+ class _AppendRowExtraKeysError(AppendRowError):
350
+ extra: AbstractSet[str]
351
+
352
+ @override
353
+ def __str__(self) -> str:
354
+ return f"Extra key(s) found; got {get_repr(self.extra)}"
355
+
356
+
357
+ @dataclass(kw_only=True, slots=True)
358
+ class _AppendRowMissingKeysError(AppendRowError):
359
+ missing: AbstractSet[str]
360
+
361
+ @override
362
+ def __str__(self) -> str:
363
+ return f"Missing key(s) found; got {get_repr(self.missing)}"
315
364
 
316
365
 
317
366
  @dataclass(kw_only=True, slots=True)
318
- class AppendDataClassError[T](Exception):
319
- left: AbstractSet[T]
320
- right: AbstractSet[T]
321
- extra: AbstractSet[T]
367
+ class _AppendRowNullColumnsError(AppendRowError):
368
+ columns: AbstractSet[str]
322
369
 
323
370
  @override
324
371
  def __str__(self) -> str:
325
- return f"Dataclass fields {get_repr(self.left)} must be a subset of DataFrame columns {get_repr(self.right)}; dataclass had extra items {get_repr(self.extra)}"
372
+ return f"Null column(s) found; got {get_repr(self.columns)}"
326
373
 
327
374
 
328
375
  ##
@@ -2460,6 +2507,34 @@ class RoundToFloatError(Exception):
2460
2507
  ##
2461
2508
 
2462
2509
 
2510
+ def search_period(
2511
+ series: Series,
2512
+ date_time: ZonedDateTime,
2513
+ /,
2514
+ *,
2515
+ start_or_end: Literal["start", "end"] = "end",
2516
+ ) -> int | None:
2517
+ """Search a series of periods for the one containing a given date-time."""
2518
+ end = series.struct["end"]
2519
+ py_date_time = date_time.py_datetime()
2520
+ match start_or_end:
2521
+ case "start":
2522
+ index = end.search_sorted(py_date_time, side="right")
2523
+ if index >= len(series):
2524
+ return None
2525
+ item: dt.datetime = series[index]["start"]
2526
+ return index if py_date_time >= item else None
2527
+ case "end":
2528
+ index = end.search_sorted(py_date_time, side="left")
2529
+ if index >= len(series):
2530
+ return None
2531
+ item: dt.datetime = series[index]["start"]
2532
+ return index if py_date_time > item else None
2533
+
2534
+
2535
+ ##
2536
+
2537
+
2463
2538
  def select_exact(
2464
2539
  df: DataFrame, /, *columns: IntoExprColumn, drop: MaybeIterable[str] | None = None
2465
2540
  ) -> DataFrame:
@@ -2672,6 +2747,7 @@ def zoned_date_time_period_dtype(
2672
2747
 
2673
2748
 
2674
2749
  __all__ = [
2750
+ "AppendRowError",
2675
2751
  "BooleanValueCountsError",
2676
2752
  "CheckPolarsDataFrameError",
2677
2753
  "ColumnsToDictError",
@@ -2702,7 +2778,7 @@ __all__ = [
2702
2778
  "all_series",
2703
2779
  "any_dataframe_columns",
2704
2780
  "any_series",
2705
- "append_dataclass",
2781
+ "append_row",
2706
2782
  "are_frames_equal",
2707
2783
  "bernoulli",
2708
2784
  "boolean_value_counts",
@@ -2750,6 +2826,7 @@ __all__ = [
2750
2826
  "read_series",
2751
2827
  "replace_time_zone",
2752
2828
  "round_to_float",
2829
+ "search_period",
2753
2830
  "select_exact",
2754
2831
  "serialize_dataframe",
2755
2832
  "set_first_row_as_columns",