dycw-utilities 0.132.3__tar.gz → 0.133.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 (218) hide show
  1. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/PKG-INFO +1 -1
  2. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/pyproject.toml +5 -3
  3. dycw_utilities-0.133.0/src/tests/test_arq.py +47 -0
  4. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_click.py +5 -0
  5. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_parse.py +14 -0
  6. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/__init__.py +1 -1
  7. dycw_utilities-0.133.0/src/utilities/arq.py +161 -0
  8. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/click.py +58 -0
  9. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/parse.py +13 -8
  10. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/types.py +14 -0
  11. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/.gitignore +0 -0
  12. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/LICENSE +0 -0
  13. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/README.md +0 -0
  14. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/__init__.py +0 -0
  15. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/conftest.py +0 -0
  16. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/__init__.py +0 -0
  17. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_missing/__init__.py +0 -0
  18. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_missing/module.py +0 -0
  19. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/__init__.py +0 -0
  20. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/outer_1.py +0 -0
  21. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/outer_2.py +0 -0
  22. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  23. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  24. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  25. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  26. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_without/__init__.py +0 -0
  27. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_without/module_1.py +0 -0
  28. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/package_without/module_2.py +0 -0
  29. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/standalone.py +0 -0
  30. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/modules/with_imports.py +0 -0
  31. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  32. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  33. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  34. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  35. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  36. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  37. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  38. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  39. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_aiolimiter.py +0 -0
  40. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_altair.py +0 -0
  41. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_asyncio.py +0 -0
  42. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_asyncio_classes/__init__.py +0 -0
  43. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_asyncio_classes/loopers.py +0 -0
  44. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_asyncio_classes/redis.py +0 -0
  45. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_atomicwrites.py +0 -0
  46. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_atools.py +0 -0
  47. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_cachetools.py +0 -0
  48. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_concurrent.py +0 -0
  49. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_contextlib.py +0 -0
  50. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_contextvars.py +0 -0
  51. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_cryptography.py +0 -0
  52. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_cvxpy.py +0 -0
  53. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_dataclasses.py +0 -0
  54. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_enum.py +0 -0
  55. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_errors.py +0 -0
  56. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_eventkit.py +0 -0
  57. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_fastapi.py +0 -0
  58. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_fpdf2.py +0 -0
  59. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_functions.py +0 -0
  60. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_functools.py +0 -0
  61. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_getpass.py +0 -0
  62. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_git.py +0 -0
  63. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_hashlib.py +0 -0
  64. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_http.py +0 -0
  65. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_hypothesis.py +0 -0
  66. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_importlib.py +0 -0
  67. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_inflect.py +0 -0
  68. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_ipython.py +0 -0
  69. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_iterables.py +0 -0
  70. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_jupyter.py +0 -0
  71. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_libcst.py +0 -0
  72. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_lightweight_charts.py +0 -0
  73. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_logging.py +0 -0
  74. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_luigi.py +0 -0
  75. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_math.py +0 -0
  76. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_memory_profiler.py +0 -0
  77. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_modules.py +0 -0
  78. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_more_itertools.py +0 -0
  79. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_numpy.py +0 -0
  80. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_objects/__init__.py +0 -0
  81. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_objects/objects.py +0 -0
  82. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_operator.py +0 -0
  83. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_optuna.py +0 -0
  84. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_orjson.py +0 -0
  85. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_os.py +0 -0
  86. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pathlib.py +0 -0
  87. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_period.py +0 -0
  88. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pickle.py +0 -0
  89. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_platform.py +0 -0
  90. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_polars.py +0 -0
  91. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_polars_ols.py +0 -0
  92. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pottery.py +0 -0
  93. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pqdm.py +0 -0
  94. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_psutil.py +0 -0
  95. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pydantic.py +0 -0
  96. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pyinstrument.py +0 -0
  97. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pytest.py +0 -0
  98. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_pytest_regressions.py +0 -0
  99. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_python_dotenv.py +0 -0
  100. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_random.py +0 -0
  101. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_re.py +0 -0
  102. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_redis.py +0 -0
  103. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_reprlib.py +0 -0
  104. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_scipy.py +0 -0
  105. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_sentinel.py +0 -0
  106. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_shelve.py +0 -0
  107. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_slack_sdk.py +0 -0
  108. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_socket.py +0 -0
  109. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_sqlalchemy.py +0 -0
  110. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_sqlalchemy_polars.py +0 -0
  111. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_statsmodels.py +0 -0
  112. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_streamlit.py +0 -0
  113. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_string.py +0 -0
  114. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_tempfile.py +0 -0
  115. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_text.py +0 -0
  116. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_threading.py +0 -0
  117. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_timer.py +0 -0
  118. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_traceback.py +0 -0
  119. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_typed_settings.py +0 -0
  120. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_types.py +0 -0
  121. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_typing.py +0 -0
  122. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_typing_funcs/__init__.py +0 -0
  123. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_typing_funcs/no_future.py +0 -0
  124. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_typing_funcs/with_future.py +0 -0
  125. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_tzdata.py +0 -0
  126. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_tzlocal.py +0 -0
  127. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_uuid.py +0 -0
  128. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_version.py +0 -0
  129. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_warnings.py +0 -0
  130. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_whenever.py +0 -0
  131. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_zipfile.py +0 -0
  132. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/tests/test_zoneinfo.py +0 -0
  133. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/aiolimiter.py +0 -0
  134. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/altair.py +0 -0
  135. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/asyncio.py +0 -0
  136. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/atomicwrites.py +0 -0
  137. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/atools.py +0 -0
  138. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/cachetools.py +0 -0
  139. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/concurrent.py +0 -0
  140. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/contextlib.py +0 -0
  141. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/contextvars.py +0 -0
  142. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/cryptography.py +0 -0
  143. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/cvxpy.py +0 -0
  144. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/dataclasses.py +0 -0
  145. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/enum.py +0 -0
  146. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/errors.py +0 -0
  147. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/eventkit.py +0 -0
  148. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/fastapi.py +0 -0
  149. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/fpdf2.py +0 -0
  150. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/functions.py +0 -0
  151. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/functools.py +0 -0
  152. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/getpass.py +0 -0
  153. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/git.py +0 -0
  154. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/hashlib.py +0 -0
  155. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/http.py +0 -0
  156. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/hypothesis.py +0 -0
  157. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/importlib.py +0 -0
  158. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/inflect.py +0 -0
  159. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/ipython.py +0 -0
  160. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/iterables.py +0 -0
  161. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/jupyter.py +0 -0
  162. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/libcst.py +0 -0
  163. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/lightweight_charts.py +0 -0
  164. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/logging.py +0 -0
  165. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/luigi.py +0 -0
  166. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/math.py +0 -0
  167. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/memory_profiler.py +0 -0
  168. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/modules.py +0 -0
  169. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/more_itertools.py +0 -0
  170. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/numpy.py +0 -0
  171. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/operator.py +0 -0
  172. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/optuna.py +0 -0
  173. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/orjson.py +0 -0
  174. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/os.py +0 -0
  175. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pathlib.py +0 -0
  176. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/period.py +0 -0
  177. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pickle.py +0 -0
  178. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/platform.py +0 -0
  179. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/polars.py +0 -0
  180. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/polars_ols.py +0 -0
  181. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pottery.py +0 -0
  182. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pqdm.py +0 -0
  183. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/psutil.py +0 -0
  184. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/py.typed +0 -0
  185. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pydantic.py +0 -0
  186. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pyinstrument.py +0 -0
  187. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pytest.py +0 -0
  188. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/pytest_regressions.py +0 -0
  189. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/python_dotenv.py +0 -0
  190. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/random.py +0 -0
  191. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/re.py +0 -0
  192. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/redis.py +0 -0
  193. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/reprlib.py +0 -0
  194. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/scipy.py +0 -0
  195. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/sentinel.py +0 -0
  196. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/shelve.py +0 -0
  197. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/slack_sdk.py +0 -0
  198. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/socket.py +0 -0
  199. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/sqlalchemy.py +0 -0
  200. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/sqlalchemy_polars.py +0 -0
  201. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/statsmodels.py +0 -0
  202. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/streamlit.py +0 -0
  203. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/string.py +0 -0
  204. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/tempfile.py +0 -0
  205. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/text.py +0 -0
  206. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/threading.py +0 -0
  207. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/timer.py +0 -0
  208. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/traceback.py +0 -0
  209. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/typed_settings.py +0 -0
  210. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/typing.py +0 -0
  211. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/tzdata.py +0 -0
  212. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/tzlocal.py +0 -0
  213. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/uuid.py +0 -0
  214. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/version.py +0 -0
  215. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/warnings.py +0 -0
  216. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/whenever.py +0 -0
  217. {dycw_utilities-0.132.3 → dycw_utilities-0.133.0}/src/utilities/zipfile.py +0 -0
  218. {dycw_utilities-0.132.3 → dycw_utilities-0.133.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.132.3
3
+ Version: 0.133.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -14,6 +14,7 @@ altair-test = [
14
14
  "img2pdf",
15
15
  "vl-convert-python",
16
16
  ]
17
+ arq = ["arq >= 0.26.3, < 0.27"]
17
18
  atools = ["atools >= 0.14.2, < 0.15"]
18
19
  cachetools = ["cachetools >= 5.5.2, < 5.6"]
19
20
  click = ["click >= 8.2.1, < 8.3"]
@@ -74,7 +75,7 @@ pytest-regressions = ["pytest-regressions >= 2.8.0, < 2.9"]
74
75
  pytest-regressions-test = ["orjson", "polars-lts-cpu"]
75
76
  pytest-test = ["orjson", "pytest-rng", "pytest-rerunfailures"]
76
77
  python-dotenv = ["python-dotenv >= 1.1.0, < 1.2"]
77
- redis = ["redis >= 6.2.0, < 6.3", "orjson"]
78
+ redis = ["redis >= 5.3.0, < 6.0", "orjson"]
78
79
  redis-test = ["pytest-rerunfailures"]
79
80
  reprlib-test = ["rich"]
80
81
  scipy = ["scipy >= 1.15.3, < 1.16"]
@@ -102,7 +103,7 @@ dependencies = [
102
103
  name = "dycw-utilities"
103
104
  readme = "README.md"
104
105
  requires-python = ">= 3.12"
105
- version = "0.132.3"
106
+ version = "0.133.0"
106
107
 
107
108
  [project.optional-dependencies]
108
109
  logging = [
@@ -128,7 +129,7 @@ test = [
128
129
  # bump-my-version
129
130
  [tool.bumpversion]
130
131
  allow_dirty = true
131
- current_version = "0.132.3"
132
+ current_version = "0.133.0"
132
133
 
133
134
  [[tool.bumpversion.files]]
134
135
  filename = "src/utilities/__init__.py"
@@ -236,6 +237,7 @@ asyncio_mode = "auto"
236
237
  filterwarnings = [
237
238
  "error",
238
239
  "ignore:.*utcfromtimestamp.* is deprecated and scheduled for removal in a future version:DeprecationWarning", # luigi
240
+ "ignore:Exception ignored in.* <coroutine object .* at .*>:pytest.PytestUnraisableExceptionWarning",
239
241
  "ignore:Implicitly cleaning up <TemporaryDirectory '.*'>:ResourceWarning",
240
242
  "ignore:ResourceTracker called reentrantly for resource cleanup, which is unsupported:UserWarning",
241
243
  "ignore:Task .* without outputs has no custom complete.* method:UserWarning", # luigi
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from asyncio import sleep
4
+ from typing import TYPE_CHECKING, Any, cast
5
+
6
+ from hypothesis import given
7
+ from hypothesis.strategies import integers
8
+
9
+ from utilities.arq import Worker, cron_raw
10
+ from utilities.iterables import one
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Sequence
14
+
15
+ from arq.cron import CronJob
16
+ from arq.typing import WorkerCoroutine
17
+
18
+ from utilities.types import CallableCoroutine1
19
+
20
+
21
+ class TestWorker:
22
+ @given(x=integers(), y=integers())
23
+ async def test_main(self, *, x: int, y: int) -> None:
24
+ async def func(x: int, y: int, /) -> int:
25
+ await sleep(0.01)
26
+ return x + y
27
+
28
+ class Example(Worker):
29
+ functions_raw: Sequence[CallableCoroutine1[Any]] = [func]
30
+
31
+ func_use = cast("WorkerCoroutine", one(Example.functions))
32
+ result = await func_use({}, x, y)
33
+ assert result == (x + y)
34
+
35
+ @given(x=integers(), y=integers())
36
+ async def test_cron(self, *, x: int, y: int) -> None:
37
+ async def func(x: int, y: int, /) -> int:
38
+ await sleep(0.01)
39
+ return x + y
40
+
41
+ class Example(Worker):
42
+ cron_jobs: Sequence[CronJob] | None = [cron_raw(func, args=(x, y))]
43
+
44
+ assert Example.cron_jobs is not None
45
+ cron_job = one(Example.cron_jobs)
46
+ result = await cron_job.coroutine({})
47
+ assert result == (x + y)
@@ -16,6 +16,7 @@ from hypothesis.strategies import (
16
16
  booleans,
17
17
  data,
18
18
  frozensets,
19
+ ip_addresses,
19
20
  lists,
20
21
  sampled_from,
21
22
  )
@@ -36,6 +37,8 @@ from utilities.click import (
36
37
  FrozenSetChoices,
37
38
  FrozenSetEnums,
38
39
  FrozenSetStrs,
40
+ IPv4Address,
41
+ IPv6Address,
39
42
  ListEnums,
40
43
  ListStrs,
41
44
  Month,
@@ -227,6 +230,8 @@ class TestParameters:
227
230
  _lift_serializer(str, sort=True),
228
231
  False,
229
232
  ),
233
+ param(IPv4Address(), "IPV4 ADDRESS", ip_addresses(v=4), str, True),
234
+ param(IPv6Address(), "IPV6 ADDRESS", ip_addresses(v=6), str, True),
230
235
  param(
231
236
  ListEnums(_ExampleEnum),
232
237
  "LIST[ENUM[_ExampleEnum]]",
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import Iterable
4
+ from ipaddress import IPv4Address, IPv6Address
4
5
  from pathlib import Path
5
6
  from types import NoneType
6
7
  from typing import Final, Literal
@@ -12,6 +13,7 @@ from hypothesis.strategies import (
12
13
  floats,
13
14
  frozensets,
14
15
  integers,
16
+ ip_addresses,
15
17
  lists,
16
18
  none,
17
19
  sampled_from,
@@ -110,6 +112,18 @@ class TestSerializeAndParseObject:
110
112
  result = parse_object(int, serialized)
111
113
  assert result == int_
112
114
 
115
+ @given(address=ip_addresses(v=4))
116
+ def test_ipv4_address(self, *, address: IPv4Address) -> None:
117
+ serialized = serialize_object(address)
118
+ result = parse_object(IPv4Address, serialized)
119
+ assert result == address
120
+
121
+ @given(address=ip_addresses(v=6))
122
+ def test_ipv6_address(self, *, address: IPv6Address) -> None:
123
+ serialized = serialize_object(address)
124
+ result = parse_object(IPv6Address, serialized)
125
+ assert result == address
126
+
113
127
  @given(ints=lists(int64s()))
114
128
  def test_list(self, *, ints: list[int]) -> None:
115
129
  serialized = serialize_object(ints)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.132.3"
3
+ __version__ = "0.133.0"
@@ -0,0 +1,161 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from functools import wraps
5
+ from itertools import chain
6
+ from typing import TYPE_CHECKING, Any, ParamSpec, TypeVar, cast, override
7
+
8
+ from arq.constants import default_queue_name, expires_extra_ms
9
+ from arq.cron import cron
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Callable, Iterable, Sequence
13
+ from datetime import timezone
14
+
15
+ from arq.connections import ArqRedis, RedisSettings
16
+ from arq.cron import CronJob
17
+ from arq.jobs import Deserializer, Serializer
18
+ from arq.typing import (
19
+ OptionType,
20
+ SecondsTimedelta,
21
+ StartupShutdown,
22
+ WeekdayOptionType,
23
+ WorkerCoroutine,
24
+ )
25
+ from arq.worker import Function
26
+
27
+ from utilities.types import CallableCoroutine1, Coroutine1, StrMapping
28
+
29
+ _P = ParamSpec("_P")
30
+ _T = TypeVar("_T")
31
+
32
+
33
+ ##
34
+
35
+
36
+ def cron_raw(
37
+ coroutine: CallableCoroutine1[Any],
38
+ /,
39
+ *,
40
+ name: str | None = None,
41
+ month: OptionType = None,
42
+ day: OptionType = None,
43
+ weekday: WeekdayOptionType = None,
44
+ hour: OptionType = None,
45
+ minute: OptionType = None,
46
+ second: OptionType = 0,
47
+ microsecond: int = 123_456,
48
+ run_at_startup: bool = False,
49
+ unique: bool = True,
50
+ job_id: str | None = None,
51
+ timeout: SecondsTimedelta | None = None,
52
+ keep_result: float | None = 0,
53
+ keep_result_forever: bool | None = False,
54
+ max_tries: int | None = 1,
55
+ args: Iterable[Any] | None = None,
56
+ kwargs: StrMapping | None = None,
57
+ ) -> CronJob:
58
+ """Create a cron job with a raw coroutine function."""
59
+ lifted = _lift_cron(
60
+ coroutine, *(() if args is None else args), **({} if kwargs is None else kwargs)
61
+ )
62
+ return cron(
63
+ lifted,
64
+ name=name,
65
+ month=month,
66
+ day=day,
67
+ weekday=weekday,
68
+ hour=hour,
69
+ minute=minute,
70
+ second=second,
71
+ microsecond=microsecond,
72
+ run_at_startup=run_at_startup,
73
+ unique=unique,
74
+ job_id=job_id,
75
+ timeout=timeout,
76
+ keep_result=keep_result,
77
+ keep_result_forever=keep_result_forever,
78
+ max_tries=max_tries,
79
+ )
80
+
81
+
82
+ def _lift_cron(
83
+ func: Callable[_P, Coroutine1[_T]], *args: _P.args, **kwargs: _P.kwargs
84
+ ) -> WorkerCoroutine:
85
+ """Lift a coroutine function & call arg/kwargs for `cron`."""
86
+
87
+ @wraps(func)
88
+ async def wrapped(ctx: StrMapping, /) -> _T:
89
+ _ = ctx
90
+ return await func(*args, **kwargs)
91
+
92
+ return cast("Any", wrapped)
93
+
94
+
95
+ ##
96
+
97
+
98
+ class _WorkerMeta(type):
99
+ @override
100
+ def __new__(
101
+ mcs: type[_WorkerMeta],
102
+ name: str,
103
+ bases: tuple[type, ...],
104
+ namespace: dict[str, Any],
105
+ /,
106
+ ) -> type[Worker]:
107
+ cls = cast("type[Worker]", super().__new__(mcs, name, bases, namespace))
108
+ cls.functions = tuple(chain(cls.functions, map(cls._lift, cls.functions_raw)))
109
+ return cls
110
+
111
+ @classmethod
112
+ def _lift(cls, func: Callable[_P, Coroutine1[_T]]) -> WorkerCoroutine:
113
+ """Lift a coroutine function to accept the required `ctx` argument."""
114
+
115
+ @wraps(func)
116
+ async def wrapped(ctx: StrMapping, *args: _P.args, **kwargs: _P.kwargs) -> _T:
117
+ _ = ctx
118
+ return await func(*args, **kwargs)
119
+
120
+ return cast("Any", wrapped)
121
+
122
+
123
+ @dataclass(kw_only=True)
124
+ class Worker(metaclass=_WorkerMeta):
125
+ """Base class for all workers."""
126
+
127
+ functions: Sequence[Function | WorkerCoroutine] = ()
128
+ functions_raw: Sequence[CallableCoroutine1[Any]] = ()
129
+ queue_name: str | None = default_queue_name
130
+ cron_jobs: Sequence[CronJob] | None = None
131
+ redis_settings: RedisSettings | None = None
132
+ redis_pool: ArqRedis | None = None
133
+ burst: bool = False
134
+ on_startup: StartupShutdown | None = None
135
+ on_shutdown: StartupShutdown | None = None
136
+ on_job_start: StartupShutdown | None = None
137
+ on_job_end: StartupShutdown | None = None
138
+ after_job_end: StartupShutdown | None = None
139
+ handle_signals: bool = True
140
+ job_completion_wait: int = 0
141
+ max_jobs: int = 10
142
+ job_timeout: SecondsTimedelta = 300
143
+ keep_result: SecondsTimedelta = 3600
144
+ keep_result_forever: bool = False
145
+ poll_delay: SecondsTimedelta = 0.5
146
+ queue_read_limit: int | None = None
147
+ max_tries: int = 5
148
+ health_check_interval: SecondsTimedelta = 3600
149
+ health_check_key: str | None = None
150
+ ctx: dict[Any, Any] | None = None
151
+ retry_jobs: bool = True
152
+ allow_abort_jobs: bool = False
153
+ max_burst_jobs: int = -1
154
+ job_serializer: Serializer | None = None
155
+ job_deserializer: Deserializer | None = None
156
+ expires_extra_ms: int = expires_extra_ms
157
+ timezone: timezone | None = None
158
+ log_results: bool = True
159
+
160
+
161
+ __all__ = ["Worker", "cron"]
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import ipaddress
3
4
  import pathlib
4
5
  from typing import TYPE_CHECKING, Generic, TypedDict, TypeVar, assert_never, override
5
6
 
@@ -12,12 +13,15 @@ import utilities.whenever
12
13
  from utilities.enum import EnsureEnumError, ensure_enum
13
14
  from utilities.functions import EnsureStrError, ensure_str, get_class_name
14
15
  from utilities.iterables import is_iterable_not_str
16
+ from utilities.parse import ParseObjectError, parse_object
15
17
  from utilities.text import split_str
16
18
  from utilities.types import (
17
19
  DateDeltaLike,
18
20
  DateLike,
19
21
  DateTimeDeltaLike,
20
22
  EnumLike,
23
+ IPv4AddressLike,
24
+ IPv6AddressLike,
21
25
  MaybeStr,
22
26
  PlainDateTimeLike,
23
27
  TEnum,
@@ -173,6 +177,58 @@ class Enum(ParamType, Generic[TEnum]):
173
177
  return _make_metavar(param, desc)
174
178
 
175
179
 
180
+ class IPv4Address(ParamType):
181
+ """An IPv4 address-valued parameter."""
182
+
183
+ name = "ipv4 address"
184
+
185
+ @override
186
+ def __repr__(self) -> str:
187
+ return self.name.upper()
188
+
189
+ @override
190
+ def convert(
191
+ self, value: IPv4AddressLike, param: Parameter | None, ctx: Context | None
192
+ ) -> ipaddress.IPv4Address:
193
+ """Convert a value into the `IPv4Address` type."""
194
+ match value:
195
+ case ipaddress.IPv4Address():
196
+ return value
197
+ case str():
198
+ try:
199
+ return parse_object(ipaddress.IPv4Address, value)
200
+ except ParseObjectError as error:
201
+ self.fail(str(error), param, ctx)
202
+ case _ as never:
203
+ assert_never(never)
204
+
205
+
206
+ class IPv6Address(ParamType):
207
+ """An IPv6 address-valued parameter."""
208
+
209
+ name = "ipv6 address"
210
+
211
+ @override
212
+ def __repr__(self) -> str:
213
+ return self.name.upper()
214
+
215
+ @override
216
+ def convert(
217
+ self, value: IPv6AddressLike, param: Parameter | None, ctx: Context | None
218
+ ) -> ipaddress.IPv6Address:
219
+ """Convert a value into the `IPv6Address` type."""
220
+ match value:
221
+ case ipaddress.IPv6Address():
222
+ return value
223
+ case str():
224
+ try:
225
+ return parse_object(ipaddress.IPv6Address, value)
226
+ except ParseObjectError as error:
227
+ self.fail(str(error), param, ctx)
228
+ case _ as never:
229
+ assert_never(never)
230
+
231
+
176
232
  class Month(ParamType):
177
233
  """A month-valued parameter."""
178
234
 
@@ -467,6 +523,8 @@ __all__ = [
467
523
  "FrozenSetEnums",
468
524
  "FrozenSetParameter",
469
525
  "FrozenSetStrs",
526
+ "IPv4Address",
527
+ "IPv6Address",
470
528
  "ListEnums",
471
529
  "ListParameter",
472
530
  "ListStrs",
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from contextlib import suppress
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
+ from ipaddress import IPv4Address, IPv6Address
6
7
  from pathlib import Path
7
8
  from re import DOTALL
8
9
  from types import NoneType
@@ -176,14 +177,9 @@ def _parse_object_type(
176
177
  return parse_bool(text)
177
178
  except ParseBoolError:
178
179
  raise _ParseObjectParseError(type_=cls, text=text) from None
179
- if is_subclass_gen(cls, int):
180
+ if is_subclass_gen(cls, int | float | IPv4Address | IPv6Address):
180
181
  try:
181
- return int(text)
182
- except ValueError:
183
- raise _ParseObjectParseError(type_=cls, text=text) from None
184
- if issubclass(cls, float):
185
- try:
186
- return float(text)
182
+ return cls(text)
187
183
  except ValueError:
188
184
  raise _ParseObjectParseError(type_=cls, text=text) from None
189
185
  if issubclass(cls, Enum):
@@ -443,7 +439,16 @@ def serialize_object(
443
439
  with suppress(_SerializeObjectSerializeError):
444
440
  return _serialize_object_extra(obj, extra)
445
441
  if (obj is None) or isinstance(
446
- obj, bool | int | float | str | Path | Sentinel | Version
442
+ obj,
443
+ bool
444
+ | int
445
+ | float
446
+ | str
447
+ | IPv4Address
448
+ | IPv6Address
449
+ | Path
450
+ | Sentinel
451
+ | Version,
447
452
  ):
448
453
  return str(obj)
449
454
  if isinstance(
@@ -4,6 +4,7 @@ import datetime as dt
4
4
  from asyncio import Event
5
5
  from collections.abc import Awaitable, Callable, Coroutine, Hashable, Iterable, Mapping
6
6
  from enum import Enum
7
+ from ipaddress import IPv4Address, IPv6Address
7
8
  from logging import Logger
8
9
  from pathlib import Path
9
10
  from random import Random
@@ -71,12 +72,16 @@ type Coroutine1[_T] = Coroutine[Any, Any, _T]
71
72
  type MaybeAwaitable[_T] = _T | Awaitable[_T]
72
73
  type MaybeCallableEvent = MaybeCallable[Event]
73
74
  type MaybeCoroutine1[_T] = _T | Coroutine1[_T]
75
+ type CallableCoroutine1[_T] = Callable[..., Coroutine1[_T]]
74
76
 
75
77
 
76
78
  # callable
77
79
  TCallable = TypeVar("TCallable", bound=Callable[..., Any])
78
80
  TCallable1 = TypeVar("TCallable1", bound=Callable[..., Any])
79
81
  TCallable2 = TypeVar("TCallable2", bound=Callable[..., Any])
82
+ TCallableCoroutine1 = TypeVar(
83
+ "TCallableCoroutine1", bound=Callable[..., Coroutine1[Any]]
84
+ )
80
85
  TCallableMaybeCoroutine1None = TypeVar(
81
86
  "TCallableMaybeCoroutine1None", bound=Callable[..., MaybeCoroutine1[None]]
82
87
  )
@@ -112,6 +117,11 @@ THashable1 = TypeVar("THashable1", bound=Hashable)
112
117
  THashable2 = TypeVar("THashable2", bound=Hashable)
113
118
 
114
119
 
120
+ # ipaddress
121
+ IPv4AddressLike = MaybeStr[IPv4Address]
122
+ IPv6AddressLike = MaybeStr[IPv6Address]
123
+
124
+
115
125
  # iterables
116
126
  type MaybeIterable[_T] = _T | Iterable[_T]
117
127
  type IterableHashable[_THashable: Hashable] = (
@@ -286,6 +296,7 @@ type TimeZoneLike = (
286
296
 
287
297
 
288
298
  __all__ = [
299
+ "CallableCoroutine1",
289
300
  "Coroutine1",
290
301
  "Dataclass",
291
302
  "DateDeltaLike",
@@ -295,6 +306,8 @@ __all__ = [
295
306
  "DateTimeRoundUnit",
296
307
  "EnumLike",
297
308
  "ExcInfo",
309
+ "IPv4AddressLike",
310
+ "IPv6AddressLike",
298
311
  "IterableHashable",
299
312
  "LogLevel",
300
313
  "LoggerOrName",
@@ -338,6 +351,7 @@ __all__ = [
338
351
  "TCallable",
339
352
  "TCallable1",
340
353
  "TCallable2",
354
+ "TCallableCoroutine1",
341
355
  "TCallableMaybeCoroutine1None",
342
356
  "TDataclass",
343
357
  "TEnum",