dycw-utilities 0.109.12__tar.gz → 0.109.14__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 (226) hide show
  1. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/PKG-INFO +1 -1
  2. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/pyproject.toml +3 -2
  3. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_iterables.py +15 -1
  4. dycw_utilities-0.109.14/src/tests/test_lightweight_charts.py +64 -0
  5. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_polars.py +1 -1
  6. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/__init__.py +1 -1
  7. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/altair.py +1 -2
  8. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/iterables.py +26 -6
  9. dycw_utilities-0.109.14/src/utilities/lightweight_charts.py +96 -0
  10. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/polars.py +1 -1
  11. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/.gitignore +0 -0
  12. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/LICENSE +0 -0
  13. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/README.md +0 -0
  14. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/__init__.py +0 -0
  15. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/conftest.py +0 -0
  16. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/__init__.py +0 -0
  17. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_missing/__init__.py +0 -0
  18. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_missing/module.py +0 -0
  19. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/__init__.py +0 -0
  20. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/outer_1.py +0 -0
  21. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/outer_2.py +0 -0
  22. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  23. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  24. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  25. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  26. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_without/__init__.py +0 -0
  27. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_without/module_1.py +0 -0
  28. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/package_without/module_2.py +0 -0
  29. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/standalone.py +0 -0
  30. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/modules/with_imports.py +0 -0
  31. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  32. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  33. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  34. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  35. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  36. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  37. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  38. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  39. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/__init__.py +0 -0
  40. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/test_async_service/__init__.py +0 -0
  41. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/test_async_service/__main__.py +0 -0
  42. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/test_async_service/run.sh +0 -0
  43. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
  44. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
  45. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/scripts/test_queue_processor/run.sh +0 -0
  46. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_altair.py +0 -0
  47. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_astor.py +0 -0
  48. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_asyncio.py +0 -0
  49. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_atomicwrites.py +0 -0
  50. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_atools.py +0 -0
  51. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_cachetools.py +0 -0
  52. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_click.py +0 -0
  53. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_concurrent.py +0 -0
  54. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_contextlib.py +0 -0
  55. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_contextvars.py +0 -0
  56. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_cryptography.py +0 -0
  57. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_cvxpy.py +0 -0
  58. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_dataclasses.py +0 -0
  59. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_datetime.py +0 -0
  60. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_enum.py +0 -0
  61. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_errors.py +0 -0
  62. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_eventkit.py +0 -0
  63. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_fastapi.py +0 -0
  64. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_fpdf2.py +0 -0
  65. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_functions.py +0 -0
  66. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_functools.py +0 -0
  67. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_getpass.py +0 -0
  68. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_git.py +0 -0
  69. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_hashlib.py +0 -0
  70. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_http.py +0 -0
  71. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_hypothesis.py +0 -0
  72. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_ipython.py +0 -0
  73. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_jupyter.py +0 -0
  74. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_logging.py +0 -0
  75. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_loguru.py +0 -0
  76. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_luigi.py +0 -0
  77. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_math.py +0 -0
  78. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_memory_profiler.py +0 -0
  79. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_modules.py +0 -0
  80. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_more_itertools.py +0 -0
  81. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_numpy.py +0 -0
  82. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_operator.py +0 -0
  83. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_optuna.py +0 -0
  84. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_orjson.py +0 -0
  85. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_os.py +0 -0
  86. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_parse.py +0 -0
  87. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pathlib.py +0 -0
  88. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_period.py +0 -0
  89. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pickle.py +0 -0
  90. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_platform.py +0 -0
  91. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_polars_ols.py +0 -0
  92. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pqdm.py +0 -0
  93. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pydantic.py +0 -0
  94. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pyinstrument.py +0 -0
  95. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pyrsistent.py +0 -0
  96. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pytest.py +0 -0
  97. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_pytest_regressions.py +0 -0
  98. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_python_dotenv.py +0 -0
  99. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_random.py +0 -0
  100. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_re.py +0 -0
  101. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_redis.py +0 -0
  102. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_reprlib.py +0 -0
  103. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_rich.py +0 -0
  104. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_scipy.py +0 -0
  105. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_sentinel.py +0 -0
  106. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_shelve.py +0 -0
  107. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_slack_sdk.py +0 -0
  108. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_socket.py +0 -0
  109. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_sqlalchemy.py +0 -0
  110. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_sqlalchemy_polars.py +0 -0
  111. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_streamlit.py +0 -0
  112. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_sys.py +0 -0
  113. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_tempfile.py +0 -0
  114. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_tenacity.py +0 -0
  115. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_text.py +0 -0
  116. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_threading.py +0 -0
  117. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_timer.py +0 -0
  118. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback.py +0 -0
  119. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/__init__.py +0 -0
  120. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/chain.py +0 -0
  121. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  122. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  123. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  124. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/many.py +0 -0
  125. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/one.py +0 -0
  126. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/recursive.py +0 -0
  127. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  128. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  129. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/two.py +0 -0
  130. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_traceback_funcs/untraced.py +0 -0
  131. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_types.py +0 -0
  132. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_typing.py +0 -0
  133. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_typing_funcs/__init__.py +0 -0
  134. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_typing_funcs/no_future.py +0 -0
  135. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_typing_funcs/with_future.py +0 -0
  136. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_tzdata.py +0 -0
  137. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_tzlocal.py +0 -0
  138. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_uuid.py +0 -0
  139. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_version.py +0 -0
  140. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_warnings.py +0 -0
  141. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_whenever.py +0 -0
  142. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_zipfile.py +0 -0
  143. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/tests/test_zoneinfo.py +0 -0
  144. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/astor.py +0 -0
  145. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/asyncio.py +0 -0
  146. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/atomicwrites.py +0 -0
  147. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/atools.py +0 -0
  148. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/cachetools.py +0 -0
  149. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/click.py +0 -0
  150. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/concurrent.py +0 -0
  151. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/contextlib.py +0 -0
  152. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/contextvars.py +0 -0
  153. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/cryptography.py +0 -0
  154. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/cvxpy.py +0 -0
  155. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/dataclasses.py +0 -0
  156. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/datetime.py +0 -0
  157. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/enum.py +0 -0
  158. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/errors.py +0 -0
  159. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/eventkit.py +0 -0
  160. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/fastapi.py +0 -0
  161. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/fpdf2.py +0 -0
  162. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/functions.py +0 -0
  163. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/functools.py +0 -0
  164. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/getpass.py +0 -0
  165. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/git.py +0 -0
  166. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/hashlib.py +0 -0
  167. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/http.py +0 -0
  168. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/hypothesis.py +0 -0
  169. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/ipython.py +0 -0
  170. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/jupyter.py +0 -0
  171. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/logging.py +0 -0
  172. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/loguru.py +0 -0
  173. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/luigi.py +0 -0
  174. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/math.py +0 -0
  175. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/memory_profiler.py +0 -0
  176. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/modules.py +0 -0
  177. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/more_itertools.py +0 -0
  178. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/numpy.py +0 -0
  179. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/operator.py +0 -0
  180. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/optuna.py +0 -0
  181. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/orjson.py +0 -0
  182. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/os.py +0 -0
  183. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/parse.py +0 -0
  184. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pathlib.py +0 -0
  185. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/period.py +0 -0
  186. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pickle.py +0 -0
  187. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/platform.py +0 -0
  188. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/polars_ols.py +0 -0
  189. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pqdm.py +0 -0
  190. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/py.typed +0 -0
  191. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pydantic.py +0 -0
  192. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pyinstrument.py +0 -0
  193. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pyrsistent.py +0 -0
  194. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pytest.py +0 -0
  195. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/pytest_regressions.py +0 -0
  196. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/python_dotenv.py +0 -0
  197. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/random.py +0 -0
  198. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/re.py +0 -0
  199. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/redis.py +0 -0
  200. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/reprlib.py +0 -0
  201. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/rich.py +0 -0
  202. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/scipy.py +0 -0
  203. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/sentinel.py +0 -0
  204. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/shelve.py +0 -0
  205. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/slack_sdk.py +0 -0
  206. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/socket.py +0 -0
  207. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/sqlalchemy.py +0 -0
  208. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/sqlalchemy_polars.py +0 -0
  209. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/streamlit.py +0 -0
  210. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/sys.py +0 -0
  211. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/tempfile.py +0 -0
  212. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/tenacity.py +0 -0
  213. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/text.py +0 -0
  214. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/threading.py +0 -0
  215. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/timer.py +0 -0
  216. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/traceback.py +0 -0
  217. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/types.py +0 -0
  218. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/typing.py +0 -0
  219. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/tzdata.py +0 -0
  220. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/tzlocal.py +0 -0
  221. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/uuid.py +0 -0
  222. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/version.py +0 -0
  223. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/warnings.py +0 -0
  224. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/whenever.py +0 -0
  225. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/zipfile.py +0 -0
  226. {dycw_utilities-0.109.12 → dycw_utilities-0.109.14}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.109.12
3
+ Version: 0.109.14
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -29,6 +29,7 @@ dev = [
29
29
  "httpx >= 0.28.1, < 0.29", # for fastapi
30
30
  "hypothesis >= 6.131.7, < 6.132",
31
31
  "img2pdf >= 0.6.0, < 0.7",
32
+ "lightweight-charts >= 2.1, < 2.2",
32
33
  "loguru >= 0.7.3, < 0.8",
33
34
  "luigi >= 3.6.0, < 3.7",
34
35
  "memory-profiler >= 0.61.0, < 0.62",
@@ -91,7 +92,7 @@ dependencies = [
91
92
  name = "dycw-utilities"
92
93
  readme = "README.md"
93
94
  requires-python = ">= 3.12"
94
- version = "0.109.12"
95
+ version = "0.109.14"
95
96
 
96
97
  [project.optional-dependencies]
97
98
  test = [
@@ -334,7 +335,7 @@ zzz-test-zoneinfo = [
334
335
  # bump-my-version
335
336
  [tool.bumpversion]
336
337
  allow_dirty = true
337
- current_version = "0.109.12"
338
+ current_version = "0.109.14"
338
339
 
339
340
  [[tool.bumpversion.files]]
340
341
  filename = "src/utilities/__init__.py"
@@ -97,6 +97,7 @@ from utilities.iterables import (
97
97
  ensure_iterable_not_str,
98
98
  expanding_window,
99
99
  filter_include_and_exclude,
100
+ group_consecutive_integers,
100
101
  groupby_lists,
101
102
  hashable_to_iterable,
102
103
  is_iterable,
@@ -118,6 +119,7 @@ from utilities.iterables import (
118
119
  sum_mappings,
119
120
  take,
120
121
  transpose,
122
+ ungroup_consecutive_integers,
121
123
  unique_everseen,
122
124
  )
123
125
  from utilities.sentinel import Sentinel, sentinel
@@ -890,6 +892,18 @@ class TestFilterIncludeAndExclude:
890
892
  assert result == expected
891
893
 
892
894
 
895
+ class TestGroupAndUngroupConsecutiveIntegers:
896
+ @given(xs=lists(integers(), unique=True).map(sorted))
897
+ def test_main(self, *, xs: list[int]) -> None:
898
+ result = list(ungroup_consecutive_integers(group_consecutive_integers(xs)))
899
+ assert result == xs
900
+
901
+ def test_example(self) -> None:
902
+ result = list(group_consecutive_integers([1, 2, 3, 6, 7, 10, 11, 12]))
903
+ expected = [(1, 3), (6, 7), (10, 12)]
904
+ assert result == expected
905
+
906
+
893
907
  class TestGroupbyLists:
894
908
  iterable: ClassVar[str] = "AAAABBBCCDAABB"
895
909
 
@@ -1044,7 +1058,7 @@ class TestOne:
1044
1058
 
1045
1059
  @given(args=sampled_from([([],), ([], []), ([], [], [])]))
1046
1060
  def test_error_empty(self, *, args: tuple[Iterable[Any], ...]) -> None:
1047
- with raises(OneEmptyError, match=r"Iterable\(s\) must not be empty"):
1061
+ with raises(OneEmptyError, match=r"Iterable\(s\) .* must not be empty"):
1048
1062
  _ = one(*args)
1049
1063
 
1050
1064
  @given(iterable=sets(integers(), min_size=2))
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime as dt
4
+ from typing import cast
5
+
6
+ from lightweight_charts import Chart
7
+ from polars import DataFrame, Date, Float64, Int64, col
8
+ from pytest import fixture, raises
9
+
10
+ from utilities.lightweight_charts import (
11
+ _SetDataFrameEmptyError,
12
+ _SetDataFrameNonUniqueError,
13
+ set_dataframe,
14
+ )
15
+
16
+
17
+ @fixture
18
+ def df() -> DataFrame:
19
+ data = [
20
+ (dt.date(2000, 1, 1), 5824.0, 5824.75, 5823.75, 5824.25, 124),
21
+ (dt.date(2000, 1, 2), 5821.0, 5821.5, 5820.75, 5820.75, 146),
22
+ (dt.date(2000, 1, 3), 5820.0, 5821.0, 5819.75, 5820.5, 128),
23
+ (dt.date(2000, 1, 4), 5822.5, 5822.5, 5822.25, 5822.25, 78),
24
+ (dt.date(2000, 1, 5), 5822.5, 5822.5, 5821.5, 5821.75, 73),
25
+ (dt.date(2000, 1, 6), 5817.0, 5817.0, 5816.0, 5816.5, 301),
26
+ (dt.date(2000, 1, 7), 5817.75, 5818.75, 5817.5, 5818.75, 150),
27
+ (dt.date(2000, 1, 8), 5821.0, 5821.25, 5821.0, 5821.25, 75),
28
+ (dt.date(2000, 1, 9), 5818.0, 5819.0, 5818.0, 5818.75, 69),
29
+ (dt.date(2000, 1, 10), 5818.75, 5819.25, 5818.5, 5819.0, 67),
30
+ ]
31
+ return DataFrame(
32
+ data=data,
33
+ schema={
34
+ "date": Date,
35
+ "open": Float64,
36
+ "high": Float64,
37
+ "low": Float64,
38
+ "close": Float64,
39
+ "volume": Int64,
40
+ },
41
+ orient="row",
42
+ )
43
+
44
+
45
+ class TestSetDataFrame:
46
+ def test_main(self, *, df: DataFrame) -> None:
47
+ chart = Chart()
48
+ set_dataframe(df, chart)
49
+
50
+ def test_error_empty(self, *, df: DataFrame) -> None:
51
+ df = df.drop("date")
52
+ with raises(
53
+ _SetDataFrameEmptyError,
54
+ match="At least 1 column must be of date/datetime type; got 0",
55
+ ):
56
+ set_dataframe(df, cast("Chart", None))
57
+
58
+ def test_error_non_unique(self, *, df: DataFrame) -> None:
59
+ df = df.with_columns(col("date").alias("date2"))
60
+ with raises(
61
+ _SetDataFrameNonUniqueError,
62
+ match=r"Schema\(.*\) must contain exactly 1 date/datetime column; got 'date', 'date2' and perhaps more",
63
+ ):
64
+ set_dataframe(df, cast("Chart", None))
@@ -755,7 +755,7 @@ class TestDataClassToDataFrame:
755
755
 
756
756
  with raises(
757
757
  _DataClassToDataFrameNonUniqueError,
758
- match="Iterable .* must contain exactly one class; got .*, .* and perhaps more",
758
+ match="Iterable .* must contain exactly 1 class; got .*, .* and perhaps more",
759
759
  ):
760
760
  _ = dataclass_to_dataframe([Example1(), Example2()])
761
761
 
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.109.12"
3
+ __version__ = "0.109.14"
@@ -22,7 +22,6 @@ from altair import (
22
22
  vconcat,
23
23
  )
24
24
  from altair.utils.schemapi import Undefined
25
- from polars import Date, Datetime
26
25
 
27
26
  from utilities.functions import ensure_bytes, ensure_number
28
27
  from utilities.iterables import always_iterable
@@ -66,7 +65,7 @@ def plot_dataframes(
66
65
  ) -> VConcatChart:
67
66
  """Plot a DataFrame as a set of time series, with a multi-line tooltip."""
68
67
  import polars as pl
69
- from polars import int_range
68
+ from polars import Date, Datetime, int_range
70
69
 
71
70
  from utilities.polars import replace_time_zone
72
71
 
@@ -19,7 +19,7 @@ from enum import Enum
19
19
  from functools import cmp_to_key, partial, reduce
20
20
  from itertools import accumulate, chain, groupby, islice, pairwise, product
21
21
  from math import isnan
22
- from operator import add, or_
22
+ from operator import add, itemgetter, or_
23
23
  from typing import (
24
24
  TYPE_CHECKING,
25
25
  Any,
@@ -861,6 +861,24 @@ def filter_include_and_exclude(
861
861
  ##
862
862
 
863
863
 
864
+ def group_consecutive_integers(iterable: Iterable[int], /) -> Iterable[tuple[int, int]]:
865
+ """Group consecutive integers."""
866
+ integers = sorted(iterable)
867
+ for _, group in groupby(enumerate(integers), key=lambda x: x[1] - x[0]):
868
+ as_list = list(map(itemgetter(1), group))
869
+ yield as_list[0], as_list[-1]
870
+
871
+
872
+ def ungroup_consecutive_integers(
873
+ iterable: Iterable[tuple[int, int]], /
874
+ ) -> Iterable[int]:
875
+ """Ungroup consecutive integers."""
876
+ return chain.from_iterable(range(start, end + 1) for start, end in iterable)
877
+
878
+
879
+ ##
880
+
881
+
864
882
  @overload
865
883
  def groupby_lists(
866
884
  iterable: Iterable[_T], /, *, key: None = None
@@ -991,7 +1009,7 @@ def one(*iterables: Iterable[_T]) -> _T:
991
1009
  try:
992
1010
  first = next(it)
993
1011
  except StopIteration:
994
- raise OneEmptyError from None
1012
+ raise OneEmptyError(iterables=iterables) from None
995
1013
  try:
996
1014
  second = next(it)
997
1015
  except StopIteration:
@@ -1000,19 +1018,19 @@ def one(*iterables: Iterable[_T]) -> _T:
1000
1018
 
1001
1019
 
1002
1020
  @dataclass(kw_only=True, slots=True)
1003
- class OneError(Exception): ...
1021
+ class OneError(Exception, Generic[_T]):
1022
+ iterables: tuple[Iterable[_T], ...]
1004
1023
 
1005
1024
 
1006
1025
  @dataclass(kw_only=True, slots=True)
1007
- class OneEmptyError(OneError):
1026
+ class OneEmptyError(OneError[_T]):
1008
1027
  @override
1009
1028
  def __str__(self) -> str:
1010
- return "Iterable(s) must not be empty"
1029
+ return f"Iterable(s) {get_repr(self.iterables)} must not be empty"
1011
1030
 
1012
1031
 
1013
1032
  @dataclass(kw_only=True, slots=True)
1014
1033
  class OneNonUniqueError(OneError, Generic[_T]):
1015
- iterables: tuple[Iterable[_T], ...]
1016
1034
  first: _T
1017
1035
  second: _T
1018
1036
 
@@ -1504,6 +1522,7 @@ __all__ = [
1504
1522
  "ensure_iterable_not_str",
1505
1523
  "expanding_window",
1506
1524
  "filter_include_and_exclude",
1525
+ "group_consecutive_integers",
1507
1526
  "groupby_lists",
1508
1527
  "hashable_to_iterable",
1509
1528
  "is_iterable",
@@ -1525,5 +1544,6 @@ __all__ = [
1525
1544
  "sum_mappings",
1526
1545
  "take",
1527
1546
  "transpose",
1547
+ "ungroup_consecutive_integers",
1528
1548
  "unique_everseen",
1529
1549
  ]
@@ -0,0 +1,96 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import asynccontextmanager
4
+ from dataclasses import dataclass
5
+ from typing import TYPE_CHECKING, override
6
+
7
+ from utilities.iterables import OneEmptyError, OneNonUniqueError, one
8
+ from utilities.reprlib import get_repr
9
+
10
+ if TYPE_CHECKING:
11
+ from collections.abc import AsyncIterator
12
+
13
+ from lightweight_charts import AbstractChart, Chart
14
+ from lightweight_charts.abstract import SeriesCommon
15
+ from polars import DataFrame
16
+ from polars._typing import SchemaDict
17
+
18
+ from utilities.types import PathLike
19
+
20
+
21
+ ##
22
+
23
+
24
+ def save_chart(chart: Chart, path: PathLike, /, *, overwrite: bool = False) -> None:
25
+ """Atomically save a chart to disk."""
26
+ from utilities.atomicwrites import writer # pragma: no cover
27
+
28
+ chart.show(block=False) # pragma: no cover
29
+ with ( # pragma: no cover
30
+ writer(path, overwrite=overwrite) as temp,
31
+ temp.open(mode="wb") as fh,
32
+ ):
33
+ _ = fh.write(chart.screenshot())
34
+ chart.exit() # pragma: no cover
35
+
36
+
37
+ ##
38
+
39
+
40
+ def set_dataframe(df: DataFrame, obj: AbstractChart | SeriesCommon, /) -> None:
41
+ """Set a `polars` DataFrame onto a Chart."""
42
+ from polars import Date, Datetime, col # pragma: no cover
43
+
44
+ try:
45
+ name = one(k for k, v in df.schema.items() if isinstance(v, Date | Datetime))
46
+ except OneEmptyError:
47
+ raise _SetDataFrameEmptyError(schema=df.schema) from None
48
+ except OneNonUniqueError as error:
49
+ raise _SetDataFrameNonUniqueError(
50
+ schema=df.schema, first=error.first, second=error.second
51
+ ) from None
52
+ return obj.set(
53
+ df.select(
54
+ col(name).alias("date").dt.strftime("iso"),
55
+ *[c for c in df.columns if c != name],
56
+ ).to_pandas()
57
+ )
58
+
59
+
60
+ @dataclass(kw_only=True, slots=True)
61
+ class SetDataFrameError(Exception):
62
+ schema: SchemaDict
63
+
64
+
65
+ @dataclass(kw_only=True, slots=True)
66
+ class _SetDataFrameEmptyError(SetDataFrameError):
67
+ @override
68
+ def __str__(self) -> str:
69
+ return "At least 1 column must be of date/datetime type; got 0"
70
+
71
+
72
+ @dataclass(kw_only=True, slots=True)
73
+ class _SetDataFrameNonUniqueError(SetDataFrameError):
74
+ first: str
75
+ second: str
76
+
77
+ @override
78
+ def __str__(self) -> str:
79
+ return f"{get_repr(self.schema)} must contain exactly 1 date/datetime column; got {self.first!r}, {self.second!r} and perhaps more"
80
+
81
+
82
+ ##
83
+
84
+
85
+ @asynccontextmanager
86
+ async def yield_chart(chart: Chart, /) -> AsyncIterator[None]:
87
+ """Yield a chart for visualization in a notebook."""
88
+ try: # pragma: no cover
89
+ yield await chart.show_async()
90
+ except BaseException: # pragma: no cover # noqa: BLE001, S110
91
+ pass
92
+ finally: # pragma: no cover
93
+ chart.exit()
94
+
95
+
96
+ __all__ = ["save_chart", "set_dataframe", "yield_chart"]
@@ -714,7 +714,7 @@ class _DataClassToDataFrameNonUniqueError(DataClassToDataFrameError):
714
714
 
715
715
  @override
716
716
  def __str__(self) -> str:
717
- return f"Iterable {get_repr(self.objs)} must contain exactly one class; got {self.first}, {self.second} and perhaps more"
717
+ return f"Iterable {get_repr(self.objs)} must contain exactly 1 class; got {self.first}, {self.second} and perhaps more"
718
718
 
719
719
 
720
720
  ##