dycw-utilities 0.113.4__tar.gz → 0.114.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 (228) hide show
  1. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/PKG-INFO +1 -1
  2. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/pyproject.toml +2 -2
  3. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_asyncio.py +104 -39
  4. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/__init__.py +1 -1
  5. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/asyncio.py +96 -29
  6. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/slack_sdk.py +1 -1
  7. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/sqlalchemy.py +1 -1
  8. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/.gitignore +0 -0
  9. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/LICENSE +0 -0
  10. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/README.md +0 -0
  11. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/__init__.py +0 -0
  12. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/conftest.py +0 -0
  13. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/__init__.py +0 -0
  14. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_missing/__init__.py +0 -0
  15. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_missing/module.py +0 -0
  16. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/__init__.py +0 -0
  17. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/outer_1.py +0 -0
  18. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/outer_2.py +0 -0
  19. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  20. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  21. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  22. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  23. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_without/__init__.py +0 -0
  24. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_without/module_1.py +0 -0
  25. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/package_without/module_2.py +0 -0
  26. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/standalone.py +0 -0
  27. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/modules/with_imports.py +0 -0
  28. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  29. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  30. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  31. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  32. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  33. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  34. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  35. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  36. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/__init__.py +0 -0
  37. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/test_async_service/__init__.py +0 -0
  38. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/test_async_service/__main__.py +0 -0
  39. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/test_async_service/run.sh +0 -0
  40. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
  41. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
  42. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/scripts/test_queue_processor/run.sh +0 -0
  43. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_altair.py +0 -0
  44. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_astor.py +0 -0
  45. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_atomicwrites.py +0 -0
  46. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_atools.py +0 -0
  47. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_cachetools.py +0 -0
  48. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_click.py +0 -0
  49. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_concurrent.py +0 -0
  50. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_contextlib.py +0 -0
  51. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_contextvars.py +0 -0
  52. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_cryptography.py +0 -0
  53. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_cvxpy.py +0 -0
  54. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_dataclasses.py +0 -0
  55. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_datetime.py +0 -0
  56. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_enum.py +0 -0
  57. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_errors.py +0 -0
  58. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_eventkit.py +0 -0
  59. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_fastapi.py +0 -0
  60. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_fpdf2.py +0 -0
  61. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_functions.py +0 -0
  62. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_functools.py +0 -0
  63. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_getpass.py +0 -0
  64. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_git.py +0 -0
  65. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_hashlib.py +0 -0
  66. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_http.py +0 -0
  67. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_hypothesis.py +0 -0
  68. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_ipython.py +0 -0
  69. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_iterables.py +0 -0
  70. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_jupyter.py +0 -0
  71. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_lightweight_charts.py +0 -0
  72. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_logging.py +0 -0
  73. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_loguru.py +0 -0
  74. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_luigi.py +0 -0
  75. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_math.py +0 -0
  76. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_memory_profiler.py +0 -0
  77. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_modules.py +0 -0
  78. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_more_itertools.py +0 -0
  79. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_numpy.py +0 -0
  80. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_operator.py +0 -0
  81. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_optuna.py +0 -0
  82. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_orjson.py +0 -0
  83. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_os.py +0 -0
  84. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_parse.py +0 -0
  85. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pathlib.py +0 -0
  86. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_period.py +0 -0
  87. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pickle.py +0 -0
  88. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_platform.py +0 -0
  89. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_polars.py +0 -0
  90. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_polars_ols.py +0 -0
  91. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pqdm.py +0 -0
  92. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pydantic.py +0 -0
  93. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pyinstrument.py +0 -0
  94. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pyrsistent.py +0 -0
  95. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pytest.py +0 -0
  96. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_pytest_regressions.py +0 -0
  97. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_python_dotenv.py +0 -0
  98. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_random.py +0 -0
  99. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_re.py +0 -0
  100. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_redis.py +0 -0
  101. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_reprlib.py +0 -0
  102. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_rich.py +0 -0
  103. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_scipy.py +0 -0
  104. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_sentinel.py +0 -0
  105. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_shelve.py +0 -0
  106. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_slack_sdk.py +0 -0
  107. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_socket.py +0 -0
  108. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_sqlalchemy.py +0 -0
  109. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_sqlalchemy_polars.py +0 -0
  110. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_statsmodel.py +0 -0
  111. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_streamlit.py +0 -0
  112. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_sys.py +0 -0
  113. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_tempfile.py +0 -0
  114. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_tenacity.py +0 -0
  115. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_text.py +0 -0
  116. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_threading.py +0 -0
  117. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_timer.py +0 -0
  118. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback.py +0 -0
  119. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/__init__.py +0 -0
  120. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/chain.py +0 -0
  121. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  122. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  123. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  124. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/many.py +0 -0
  125. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/one.py +0 -0
  126. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/recursive.py +0 -0
  127. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  128. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  129. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/two.py +0 -0
  130. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_traceback_funcs/untraced.py +0 -0
  131. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_types.py +0 -0
  132. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_typing.py +0 -0
  133. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_typing_funcs/__init__.py +0 -0
  134. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_typing_funcs/no_future.py +0 -0
  135. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_typing_funcs/with_future.py +0 -0
  136. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_tzdata.py +0 -0
  137. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_tzlocal.py +0 -0
  138. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_uuid.py +0 -0
  139. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_version.py +0 -0
  140. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_warnings.py +0 -0
  141. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_whenever.py +0 -0
  142. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_zipfile.py +0 -0
  143. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/tests/test_zoneinfo.py +0 -0
  144. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/altair.py +0 -0
  145. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/astor.py +0 -0
  146. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/atomicwrites.py +0 -0
  147. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/atools.py +0 -0
  148. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/cachetools.py +0 -0
  149. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/click.py +0 -0
  150. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/concurrent.py +0 -0
  151. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/contextlib.py +0 -0
  152. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/contextvars.py +0 -0
  153. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/cryptography.py +0 -0
  154. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/cvxpy.py +0 -0
  155. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/dataclasses.py +0 -0
  156. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/datetime.py +0 -0
  157. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/enum.py +0 -0
  158. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/errors.py +0 -0
  159. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/eventkit.py +0 -0
  160. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/fastapi.py +0 -0
  161. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/fpdf2.py +0 -0
  162. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/functions.py +0 -0
  163. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/functools.py +0 -0
  164. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/getpass.py +0 -0
  165. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/git.py +0 -0
  166. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/hashlib.py +0 -0
  167. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/http.py +0 -0
  168. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/hypothesis.py +0 -0
  169. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/ipython.py +0 -0
  170. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/iterables.py +0 -0
  171. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/jupyter.py +0 -0
  172. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/lightweight_charts.py +0 -0
  173. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/logging.py +0 -0
  174. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/loguru.py +0 -0
  175. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/luigi.py +0 -0
  176. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/math.py +0 -0
  177. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/memory_profiler.py +0 -0
  178. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/modules.py +0 -0
  179. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/more_itertools.py +0 -0
  180. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/numpy.py +0 -0
  181. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/operator.py +0 -0
  182. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/optuna.py +0 -0
  183. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/orjson.py +0 -0
  184. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/os.py +0 -0
  185. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/parse.py +0 -0
  186. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pathlib.py +0 -0
  187. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/period.py +0 -0
  188. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pickle.py +0 -0
  189. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/platform.py +0 -0
  190. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/polars.py +0 -0
  191. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/polars_ols.py +0 -0
  192. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pqdm.py +0 -0
  193. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/py.typed +0 -0
  194. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pydantic.py +0 -0
  195. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pyinstrument.py +0 -0
  196. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pyrsistent.py +0 -0
  197. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pytest.py +0 -0
  198. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/pytest_regressions.py +0 -0
  199. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/python_dotenv.py +0 -0
  200. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/random.py +0 -0
  201. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/re.py +0 -0
  202. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/redis.py +0 -0
  203. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/reprlib.py +0 -0
  204. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/rich.py +0 -0
  205. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/scipy.py +0 -0
  206. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/sentinel.py +0 -0
  207. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/shelve.py +0 -0
  208. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/socket.py +0 -0
  209. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/sqlalchemy_polars.py +0 -0
  210. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/statsmodels.py +0 -0
  211. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/streamlit.py +0 -0
  212. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/sys.py +0 -0
  213. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/tempfile.py +0 -0
  214. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/tenacity.py +0 -0
  215. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/text.py +0 -0
  216. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/threading.py +0 -0
  217. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/timer.py +0 -0
  218. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/traceback.py +0 -0
  219. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/types.py +0 -0
  220. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/typing.py +0 -0
  221. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/tzdata.py +0 -0
  222. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/tzlocal.py +0 -0
  223. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/uuid.py +0 -0
  224. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/version.py +0 -0
  225. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/warnings.py +0 -0
  226. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/whenever.py +0 -0
  227. {dycw_utilities-0.113.4 → dycw_utilities-0.114.0}/src/utilities/zipfile.py +0 -0
  228. {dycw_utilities-0.113.4 → dycw_utilities-0.114.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.113.4
3
+ Version: 0.114.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -92,7 +92,7 @@ dependencies = [
92
92
  name = "dycw-utilities"
93
93
  readme = "README.md"
94
94
  requires-python = ">= 3.12"
95
- version = "0.113.4"
95
+ version = "0.114.0"
96
96
 
97
97
  [project.optional-dependencies]
98
98
  test = [
@@ -334,7 +334,7 @@ zzz-test-zoneinfo = [
334
334
  # bump-my-version
335
335
  [tool.bumpversion]
336
336
  allow_dirty = true
337
- current_version = "0.113.4"
337
+ current_version = "0.114.0"
338
338
 
339
339
  [[tool.bumpversion.files]]
340
340
  filename = "src/utilities/__init__.py"
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from asyncio import (
4
4
  CancelledError,
5
5
  Event,
6
- Lock,
7
6
  PriorityQueue,
8
7
  Queue,
9
8
  TaskGroup,
@@ -22,7 +21,6 @@ from hypothesis.strategies import (
22
21
  DataObject,
23
22
  data,
24
23
  integers,
25
- just,
26
24
  lists,
27
25
  none,
28
26
  permutations,
@@ -35,12 +33,15 @@ from utilities.asyncio import (
35
33
  AsyncService,
36
34
  EnhancedTaskGroup,
37
35
  ExceptionProcessor,
36
+ InfiniteLooper,
38
37
  QueueProcessor,
39
38
  UniquePriorityQueue,
40
39
  UniqueQueue,
41
40
  get_event,
42
41
  get_items,
43
42
  get_items_nowait,
43
+ put_items,
44
+ put_items_nowait,
44
45
  sleep_dur,
45
46
  stream_command,
46
47
  timeout_dur,
@@ -54,7 +55,9 @@ from utilities.sentinel import Sentinel, sentinel
54
55
  from utilities.timer import Timer
55
56
 
56
57
  if TYPE_CHECKING:
57
- from utilities.types import Duration, MaybeCallableEvent
58
+ from collections.abc import Mapping
59
+
60
+ from utilities.types import Duration, MaybeCallableEvent, MaybeType
58
61
 
59
62
 
60
63
  class TestAsyncLoopingService:
@@ -332,41 +335,110 @@ class TestGetEvent:
332
335
  assert get_event(event=lambda: event) is event
333
336
 
334
337
 
335
- class TestGetItems:
336
- @given(
337
- xs=lists(integers(), min_size=1),
338
- max_size=integers(1, 10) | none(),
339
- lock=just(Lock()) | none(),
340
- )
341
- async def test_put_then_get(
342
- self, *, xs: list[int], max_size: int | None, lock: Lock | None
343
- ) -> None:
338
+ class TestInfiniteLooper:
339
+ @given(n=integers(10, 11))
340
+ async def test_main(self, *, n: int) -> None:
341
+ class CustomTrueError(BaseException): ...
342
+
343
+ class CustomFalseError(BaseException): ...
344
+
345
+ @dataclass(kw_only=True)
346
+ class Example(InfiniteLooper[bool]):
347
+ counter: int = field(init=False, repr=False)
348
+
349
+ @override
350
+ async def initialize(self) -> None:
351
+ self.counter = 0
352
+
353
+ @override
354
+ async def core(self) -> None:
355
+ self.counter += 1
356
+ if self.counter >= n:
357
+ self.events[n % 2 == 0].set()
358
+
359
+ @property
360
+ @override
361
+ def events_and_exceptions(self) -> Mapping[bool, MaybeType[BaseException]]:
362
+ return {True: CustomTrueError, False: CustomFalseError}
363
+
364
+ looper = Example(sleep_core=0.1)
365
+ match n % 2 == 0:
366
+ case True:
367
+ with raises(CustomTrueError):
368
+ _ = await looper()
369
+ case False:
370
+ with raises(CustomFalseError):
371
+ _ = await looper()
372
+
373
+ async def test_error_upon_initialize(self) -> None:
374
+ class CustomError(Exception): ...
375
+
376
+ @dataclass(kw_only=True)
377
+ class Example(InfiniteLooper[None]):
378
+ counter: int = field(init=False, repr=False)
379
+
380
+ @override
381
+ async def initialize(self) -> None:
382
+ raise CustomError
383
+
384
+ @override
385
+ async def core(self) -> None:
386
+ raise NotImplementedError
387
+
388
+ @property
389
+ @override
390
+ def events_and_exceptions(self) -> Mapping[None, MaybeType[BaseException]]:
391
+ return {None: CustomError}
392
+
393
+ with raises(TimeoutError):
394
+ async with timeout_dur(duration=0.5):
395
+ _ = await Example(sleep_core=0.1)()
396
+
397
+ async def test_error_upon_core(self) -> None:
398
+ class CustomError(Exception): ...
399
+
400
+ @dataclass(kw_only=True)
401
+ class Example(InfiniteLooper[None]):
402
+ counter: int = field(init=False, repr=False)
403
+
404
+ @override
405
+ async def initialize(self) -> None: ...
406
+
407
+ @override
408
+ async def core(self) -> None:
409
+ raise CustomError
410
+
411
+ @property
412
+ @override
413
+ def events_and_exceptions(self) -> Mapping[None, MaybeType[BaseException]]:
414
+ return {None: CustomError}
415
+
416
+ with raises(TimeoutError):
417
+ async with timeout_dur(duration=0.5):
418
+ _ = await Example(sleep_core=0.1)()
419
+
420
+
421
+ class TestPutAndGetItems:
422
+ @given(xs=lists(integers(), min_size=1), max_size=integers(1, 10) | none())
423
+ async def test_put_then_get(self, *, xs: list[int], max_size: int | None) -> None:
344
424
  queue: Queue[int] = Queue()
345
- for x in xs:
346
- await queue.put(x)
347
- result = await get_items(queue, max_size=max_size, lock=lock)
425
+ await put_items(xs, queue)
426
+ result = await get_items(queue, max_size=max_size)
348
427
  if max_size is None:
349
428
  assert result == xs
350
429
  else:
351
430
  assert result == xs[:max_size]
352
431
 
353
- @given(
354
- xs=lists(integers(), min_size=1),
355
- max_size=integers(1, 10) | none(),
356
- lock=just(Lock()) | none(),
357
- )
358
- async def test_get_then_put(
359
- self, *, xs: list[int], max_size: int | None, lock: Lock | None
360
- ) -> None:
432
+ @given(xs=lists(integers(), min_size=1), max_size=integers(1, 10) | none())
433
+ async def test_get_then_put(self, *, xs: list[int], max_size: int | None) -> None:
361
434
  queue: Queue[int] = Queue()
362
435
 
363
436
  async def put() -> None:
364
437
  await sleep(0.01)
365
- for x in xs:
366
- await queue.put(x)
438
+ await put_items(xs, queue)
367
439
 
368
440
  async with TaskGroup() as tg:
369
- task = tg.create_task(get_items(queue, max_size=max_size, lock=lock))
441
+ task = tg.create_task(get_items(queue, max_size=max_size))
370
442
  _ = tg.create_task(put())
371
443
  result = task.result()
372
444
  if max_size is None:
@@ -382,19 +454,12 @@ class TestGetItems:
382
454
  _ = tg.create_task(sleep(0.02))
383
455
 
384
456
 
385
- class TestGetItemsNoWait:
386
- @given(
387
- xs=lists(integers(), min_size=1),
388
- max_size=integers(1, 10) | none(),
389
- lock=just(Lock()) | none(),
390
- )
391
- async def test_main(
392
- self, *, xs: list[int], max_size: int | None, lock: Lock | None
393
- ) -> None:
457
+ class TestPutAndGetItemsNoWait:
458
+ @given(xs=lists(integers(), min_size=1), max_size=integers(1, 10) | none())
459
+ def test_main(self, *, xs: list[int], max_size: int | None) -> None:
394
460
  queue: Queue[int] = Queue()
395
- for x in xs:
396
- await queue.put(x)
397
- result = await get_items_nowait(queue, max_size=max_size, lock=lock)
461
+ put_items_nowait(xs, queue)
462
+ result = get_items_nowait(queue, max_size=max_size)
398
463
  if max_size is None:
399
464
  assert result == xs
400
465
  else:
@@ -524,7 +589,7 @@ class TestQueueProcessor:
524
589
 
525
590
  @override
526
591
  async def _process_item(self, _: int, /) -> None:
527
- items = await self._get_items_nowait()
592
+ items = self._get_items_nowait()
528
593
  self.output.add(len(items))
529
594
 
530
595
  processor = Example()
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.113.4"
3
+ __version__ = "0.114.0"
@@ -4,7 +4,6 @@ from abc import ABC, abstractmethod
4
4
  from asyncio import (
5
5
  CancelledError,
6
6
  Event,
7
- Lock,
8
7
  PriorityQueue,
9
8
  Queue,
10
9
  QueueEmpty,
@@ -17,7 +16,7 @@ from asyncio import (
17
16
  sleep,
18
17
  timeout,
19
18
  )
20
- from collections.abc import Callable
19
+ from collections.abc import Callable, Iterable, Mapping
21
20
  from contextlib import (
22
21
  AsyncExitStack,
23
22
  _AsyncGeneratorContextManager,
@@ -39,11 +38,17 @@ from typing import (
39
38
  override,
40
39
  )
41
40
 
42
- from utilities.datetime import MILLISECOND, datetime_duration_to_float
41
+ from utilities.datetime import MILLISECOND, MINUTE, SECOND, datetime_duration_to_float
43
42
  from utilities.errors import ImpossibleCaseError
44
43
  from utilities.functions import ensure_int, ensure_not_none
45
44
  from utilities.sentinel import Sentinel, sentinel
46
- from utilities.types import MaybeCallableEvent, THashable, TSupportsRichComparison
45
+ from utilities.types import (
46
+ Coroutine1,
47
+ MaybeCallableEvent,
48
+ MaybeType,
49
+ THashable,
50
+ TSupportsRichComparison,
51
+ )
47
52
 
48
53
  if TYPE_CHECKING:
49
54
  from asyncio import _CoroutineLike
@@ -234,7 +239,6 @@ class QueueProcessor(AsyncService, Generic[_T]):
234
239
  sleep: Duration = MILLISECOND
235
240
  _await_upon_aenter: bool = field(default=False, init=False, repr=False)
236
241
  _queue: Queue[_T] = field(init=False, repr=False)
237
- _lock: Lock = field(default_factory=Lock, init=False, repr=False)
238
242
 
239
243
  def __post_init__(self) -> None:
240
244
  self._queue = self.queue_type(
@@ -259,9 +263,9 @@ class QueueProcessor(AsyncService, Generic[_T]):
259
263
  await self._run()
260
264
  await sleep_dur(duration=self.sleep)
261
265
 
262
- async def _get_items_nowait(self, *, max_size: int | None = None) -> Sequence[_T]:
266
+ def _get_items_nowait(self, *, max_size: int | None = None) -> Sequence[_T]:
263
267
  """Get items from the queue; no waiting."""
264
- return await get_items_nowait(self._queue, max_size=max_size, lock=self._lock)
268
+ return get_items_nowait(self._queue, max_size=max_size)
265
269
 
266
270
  @abstractmethod
267
271
  async def _process_item(self, item: _T, /) -> None:
@@ -276,7 +280,7 @@ class QueueProcessor(AsyncService, Generic[_T]):
276
280
  async def _run(self) -> None:
277
281
  """Run the processer."""
278
282
  try:
279
- (item,) = await self._get_items_nowait(max_size=1)
283
+ (item,) = self._get_items_nowait(max_size=1)
280
284
  except ValueError:
281
285
  raise QueueEmpty from None
282
286
  try:
@@ -320,6 +324,70 @@ class ExceptionProcessor(QueueProcessor[Exception | type[Exception]]):
320
324
  ##
321
325
 
322
326
 
327
+ @dataclass(kw_only=True)
328
+ class InfiniteLooper(ABC, Generic[THashable]):
329
+ """An infinite loop which can throw exceptions by setting events."""
330
+
331
+ events: Mapping[THashable, Event] = field(
332
+ default_factory=dict, init=False, repr=False
333
+ )
334
+ sleep_core: Duration = SECOND
335
+ sleep_restart: Duration = MINUTE
336
+
337
+ def __post_init__(self) -> None:
338
+ self._reset_events()
339
+
340
+ async def __call__(self) -> Coroutine1[None]:
341
+ while True:
342
+ try:
343
+ self._reset_events()
344
+ try:
345
+ await self.initialize()
346
+ except Exception as error: # noqa: BLE001
347
+ self.error_upon_initialize(error)
348
+ await sleep_dur(duration=self.sleep_restart)
349
+ else:
350
+ while True:
351
+ try:
352
+ event = next(
353
+ key
354
+ for (key, value) in self.events.items()
355
+ if value.is_set()
356
+ )
357
+ except StopIteration:
358
+ await self.core()
359
+ await sleep_dur(duration=self.sleep_core)
360
+ else:
361
+ raise self.events_and_exceptions[event]
362
+ except Exception as error: # noqa: BLE001
363
+ self.error_upon_core(error)
364
+ await sleep_dur(duration=self.sleep_restart)
365
+
366
+ @property
367
+ @abstractmethod
368
+ def events_and_exceptions(self) -> Mapping[THashable, MaybeType[BaseException]]:
369
+ """A mapping of events to exceptions."""
370
+
371
+ async def initialize(self) -> None:
372
+ """Initialize the loop."""
373
+
374
+ async def core(self) -> None:
375
+ """Run the core."""
376
+
377
+ def error_upon_initialize(self, error: Exception, /) -> None:
378
+ _ = error
379
+
380
+ def error_upon_core(self, error: Exception, /) -> None:
381
+ _ = error
382
+
383
+ def _reset_events(self) -> None:
384
+ """Reset the events."""
385
+ self.events = {event: Event() for event in self.events_and_exceptions}
386
+
387
+
388
+ ##
389
+
390
+
323
391
  class UniquePriorityQueue(PriorityQueue[tuple[TSupportsRichComparison, THashable]]):
324
392
  """Priority queue with unique tasks."""
325
393
 
@@ -395,9 +463,7 @@ def get_event(
395
463
  ##
396
464
 
397
465
 
398
- async def get_items(
399
- queue: Queue[_T], /, *, max_size: int | None = None, lock: Lock | None = None
400
- ) -> list[_T]:
466
+ async def get_items(queue: Queue[_T], /, *, max_size: int | None = None) -> list[_T]:
401
467
  """Get items from a queue; if empty then wait."""
402
468
  try:
403
469
  items = [await queue.get()]
@@ -406,28 +472,12 @@ async def get_items(
406
472
  return []
407
473
  raise
408
474
  max_size_use = None if max_size is None else (max_size - 1)
409
- if lock is None:
410
- items.extend(await get_items_nowait(queue, max_size=max_size_use))
411
- else:
412
- async with lock:
413
- items.extend(await get_items_nowait(queue, max_size=max_size_use))
475
+ items.extend(get_items_nowait(queue, max_size=max_size_use))
414
476
  return items
415
477
 
416
478
 
417
- async def get_items_nowait(
418
- queue: Queue[_T], /, *, max_size: int | None = None, lock: Lock | None = None
419
- ) -> list[_T]:
479
+ def get_items_nowait(queue: Queue[_T], /, *, max_size: int | None = None) -> list[_T]:
420
480
  """Get items from a queue; no waiting."""
421
- if lock is None:
422
- return _get_items_nowait_core(queue, max_size=max_size)
423
- async with lock:
424
- return _get_items_nowait_core(queue, max_size=max_size)
425
-
426
-
427
- def _get_items_nowait_core(
428
- queue: Queue[_T], /, *, max_size: int | None = None
429
- ) -> list[_T]:
430
- """Get all the items from a queue; no waiting."""
431
481
  items: list[_T] = []
432
482
  if max_size is None:
433
483
  while True:
@@ -447,6 +497,21 @@ def _get_items_nowait_core(
447
497
  ##
448
498
 
449
499
 
500
+ async def put_items(items: Iterable[_T], queue: Queue[_T], /) -> None:
501
+ """Put items into a queue; if full then wait."""
502
+ for item in items:
503
+ await queue.put(item)
504
+
505
+
506
+ def put_items_nowait(items: Iterable[_T], queue: Queue[_T], /) -> None:
507
+ """Put items into a queue; no waiting."""
508
+ for item in items:
509
+ queue.put_nowait(item)
510
+
511
+
512
+ ##
513
+
514
+
450
515
  async def sleep_dur(*, duration: Duration | None = None) -> None:
451
516
  """Sleep which accepts durations."""
452
517
  if duration is None:
@@ -532,6 +597,8 @@ __all__ = [
532
597
  "get_event",
533
598
  "get_items",
534
599
  "get_items_nowait",
600
+ "put_items",
601
+ "put_items_nowait",
535
602
  "sleep_dur",
536
603
  "stream_command",
537
604
  "timeout_dur",
@@ -78,7 +78,7 @@ class SlackHandler(Handler, QueueProcessor[str]):
78
78
  @override
79
79
  async def _process_item(self, item: str, /) -> None:
80
80
  """Process the first item."""
81
- items = list(chain([item], await self._get_items_nowait()))
81
+ items = list(chain([item], self._get_items_nowait()))
82
82
  text = "\n".join(items)
83
83
  try:
84
84
  async with timeout_dur(duration=self.timeout):
@@ -627,7 +627,7 @@ class Upserter(QueueProcessor[_InsertItem]):
627
627
  @override
628
628
  async def _process_item(self, item: _InsertItem, /) -> None:
629
629
  """Process the first item."""
630
- items = list(chain([item], await self._get_items_nowait()))
630
+ items = list(chain([item], self._get_items_nowait()))
631
631
  await self._pre_upsert(items)
632
632
  await upsert_items(
633
633
  self.engine,