dycw-utilities 0.131.12__tar.gz → 0.131.13__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 (224) hide show
  1. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/PKG-INFO +1 -1
  2. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/pyproject.toml +2 -2
  3. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_atools.py +6 -5
  4. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_cachetools.py +22 -9
  5. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_hypothesis.py +0 -55
  6. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_orjson.py +2 -1
  7. dycw_utilities-0.131.13/src/tests/test_period.py +259 -0
  8. dycw_utilities-0.131.13/src/tests/test_tzdata.py +14 -0
  9. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_zoneinfo.py +3 -5
  10. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/__init__.py +1 -1
  11. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/atools.py +7 -9
  12. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/cachetools.py +8 -10
  13. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/hypothesis.py +0 -136
  14. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/orjson.py +1 -1
  15. dycw_utilities-0.131.13/src/utilities/period.py +154 -0
  16. dycw_utilities-0.131.13/src/utilities/tzdata.py +11 -0
  17. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/whenever2.py +4 -3
  18. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/zoneinfo.py +2 -2
  19. dycw_utilities-0.131.12/src/tests/test_period.py +0 -387
  20. dycw_utilities-0.131.12/src/tests/test_tzdata.py +0 -60
  21. dycw_utilities-0.131.12/src/utilities/period.py +0 -324
  22. dycw_utilities-0.131.12/src/utilities/tzdata.py +0 -63
  23. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/.gitignore +0 -0
  24. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/LICENSE +0 -0
  25. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/README.md +0 -0
  26. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/__init__.py +0 -0
  27. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/conftest.py +0 -0
  28. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/__init__.py +0 -0
  29. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_missing/__init__.py +0 -0
  30. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_missing/module.py +0 -0
  31. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/__init__.py +0 -0
  32. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/outer_1.py +0 -0
  33. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/outer_2.py +0 -0
  34. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  35. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  36. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  37. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  38. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_without/__init__.py +0 -0
  39. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_without/module_1.py +0 -0
  40. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/package_without/module_2.py +0 -0
  41. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/standalone.py +0 -0
  42. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/modules/with_imports.py +0 -0
  43. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  44. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  45. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  46. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  47. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  48. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  49. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  50. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  51. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_aiolimiter.py +0 -0
  52. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_altair.py +0 -0
  53. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_asyncio.py +0 -0
  54. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_asyncio_classes/__init__.py +0 -0
  55. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_asyncio_classes/loopers.py +0 -0
  56. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_asyncio_classes/redis.py +0 -0
  57. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_atomicwrites.py +0 -0
  58. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_click.py +0 -0
  59. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_concurrent.py +0 -0
  60. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_contextlib.py +0 -0
  61. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_contextvars.py +0 -0
  62. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_cryptography.py +0 -0
  63. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_cvxpy.py +0 -0
  64. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_dataclasses.py +0 -0
  65. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_datetime.py +0 -0
  66. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_enum.py +0 -0
  67. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_errors.py +0 -0
  68. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_eventkit.py +0 -0
  69. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_fastapi.py +0 -0
  70. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_fpdf2.py +0 -0
  71. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_functions.py +0 -0
  72. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_functools.py +0 -0
  73. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_getpass.py +0 -0
  74. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_git.py +0 -0
  75. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_hashlib.py +0 -0
  76. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_http.py +0 -0
  77. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_importlib.py +0 -0
  78. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_inflect.py +0 -0
  79. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_ipython.py +0 -0
  80. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_iterables.py +0 -0
  81. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_jupyter.py +0 -0
  82. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_libcst.py +0 -0
  83. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_lightweight_charts.py +0 -0
  84. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_logging.py +0 -0
  85. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_luigi.py +0 -0
  86. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_math.py +0 -0
  87. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_memory_profiler.py +0 -0
  88. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_modules.py +0 -0
  89. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_more_itertools.py +0 -0
  90. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_numpy.py +0 -0
  91. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_operator.py +0 -0
  92. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_optuna.py +0 -0
  93. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_os.py +0 -0
  94. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_parse.py +0 -0
  95. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pathlib.py +0 -0
  96. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pickle.py +0 -0
  97. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_platform.py +0 -0
  98. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_polars.py +0 -0
  99. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_polars_ols.py +0 -0
  100. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pottery.py +0 -0
  101. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pqdm.py +0 -0
  102. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_psutil.py +0 -0
  103. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pydantic.py +0 -0
  104. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pyinstrument.py +0 -0
  105. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pyrsistent.py +0 -0
  106. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pytest.py +0 -0
  107. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_pytest_regressions.py +0 -0
  108. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_python_dotenv.py +0 -0
  109. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_random.py +0 -0
  110. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_re.py +0 -0
  111. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_redis.py +0 -0
  112. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_reprlib.py +0 -0
  113. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_scipy.py +0 -0
  114. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_sentinel.py +0 -0
  115. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_shelve.py +0 -0
  116. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_slack_sdk.py +0 -0
  117. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_socket.py +0 -0
  118. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_sqlalchemy.py +0 -0
  119. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_sqlalchemy_polars.py +0 -0
  120. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_statsmodel.py +0 -0
  121. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_streamlit.py +0 -0
  122. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_string.py +0 -0
  123. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_tempfile.py +0 -0
  124. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_tenacity.py +0 -0
  125. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_text.py +0 -0
  126. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_threading.py +0 -0
  127. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_timer.py +0 -0
  128. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_traceback.py +0 -0
  129. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_types.py +0 -0
  130. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_typing.py +0 -0
  131. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_typing_funcs/__init__.py +0 -0
  132. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_typing_funcs/no_future.py +0 -0
  133. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_typing_funcs/with_future.py +0 -0
  134. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_tzlocal.py +0 -0
  135. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_uuid.py +0 -0
  136. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_version.py +0 -0
  137. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_warnings.py +0 -0
  138. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_whenever.py +0 -0
  139. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_whenever2.py +0 -0
  140. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/tests/test_zipfile.py +0 -0
  141. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/aiolimiter.py +0 -0
  142. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/altair.py +0 -0
  143. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/asyncio.py +0 -0
  144. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/atomicwrites.py +0 -0
  145. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/click.py +0 -0
  146. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/concurrent.py +0 -0
  147. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/contextlib.py +0 -0
  148. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/contextvars.py +0 -0
  149. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/cryptography.py +0 -0
  150. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/cvxpy.py +0 -0
  151. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/dataclasses.py +0 -0
  152. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/datetime.py +0 -0
  153. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/enum.py +0 -0
  154. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/errors.py +0 -0
  155. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/eventkit.py +0 -0
  156. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/fastapi.py +0 -0
  157. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/fpdf2.py +0 -0
  158. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/functions.py +0 -0
  159. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/functools.py +0 -0
  160. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/getpass.py +0 -0
  161. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/git.py +0 -0
  162. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/hashlib.py +0 -0
  163. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/http.py +0 -0
  164. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/importlib.py +0 -0
  165. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/inflect.py +0 -0
  166. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/ipython.py +0 -0
  167. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/iterables.py +0 -0
  168. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/jupyter.py +0 -0
  169. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/libcst.py +0 -0
  170. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/lightweight_charts.py +0 -0
  171. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/logging.py +0 -0
  172. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/luigi.py +0 -0
  173. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/math.py +0 -0
  174. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/memory_profiler.py +0 -0
  175. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/modules.py +0 -0
  176. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/more_itertools.py +0 -0
  177. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/numpy.py +0 -0
  178. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/operator.py +0 -0
  179. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/optuna.py +0 -0
  180. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/os.py +0 -0
  181. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/parse.py +0 -0
  182. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pathlib.py +0 -0
  183. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pickle.py +0 -0
  184. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/platform.py +0 -0
  185. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/polars.py +0 -0
  186. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/polars_ols.py +0 -0
  187. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pottery.py +0 -0
  188. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pqdm.py +0 -0
  189. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/psutil.py +0 -0
  190. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/py.typed +0 -0
  191. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pydantic.py +0 -0
  192. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pyinstrument.py +0 -0
  193. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pyrsistent.py +0 -0
  194. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pytest.py +0 -0
  195. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/pytest_regressions.py +0 -0
  196. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/python_dotenv.py +0 -0
  197. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/random.py +0 -0
  198. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/re.py +0 -0
  199. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/redis.py +0 -0
  200. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/reprlib.py +0 -0
  201. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/scipy.py +0 -0
  202. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/sentinel.py +0 -0
  203. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/shelve.py +0 -0
  204. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/slack_sdk.py +0 -0
  205. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/socket.py +0 -0
  206. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/sqlalchemy.py +0 -0
  207. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/sqlalchemy_polars.py +0 -0
  208. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/statsmodels.py +0 -0
  209. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/streamlit.py +0 -0
  210. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/string.py +0 -0
  211. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/tempfile.py +0 -0
  212. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/tenacity.py +0 -0
  213. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/text.py +0 -0
  214. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/threading.py +0 -0
  215. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/timer.py +0 -0
  216. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/traceback.py +0 -0
  217. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/types.py +0 -0
  218. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/typing.py +0 -0
  219. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/tzlocal.py +0 -0
  220. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/uuid.py +0 -0
  221. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/version.py +0 -0
  222. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/warnings.py +0 -0
  223. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/whenever.py +0 -0
  224. {dycw_utilities-0.131.12 → dycw_utilities-0.131.13}/src/utilities/zipfile.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.131.12
3
+ Version: 0.131.13
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -94,7 +94,7 @@ dependencies = [
94
94
  name = "dycw-utilities"
95
95
  readme = "README.md"
96
96
  requires-python = ">= 3.12"
97
- version = "0.131.12"
97
+ version = "0.131.13"
98
98
 
99
99
  [project.optional-dependencies]
100
100
  logging = [
@@ -121,7 +121,7 @@ test = [
121
121
  # bump-my-version
122
122
  [tool.bumpversion]
123
123
  allow_dirty = true
124
- current_version = "0.131.12"
124
+ current_version = "0.131.13"
125
125
 
126
126
  [[tool.bumpversion.files]]
127
127
  filename = "src/utilities/__init__.py"
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from asyncio import sleep
4
-
3
+ from utilities.asyncio import sleep_dur
5
4
  from utilities.atools import call_memoized
5
+ from utilities.whenever2 import SECOND
6
6
 
7
7
 
8
8
  class TestCallMemoized:
@@ -20,6 +20,7 @@ class TestCallMemoized:
20
20
 
21
21
  async def test_refresh(self) -> None:
22
22
  counter = 0
23
+ delta = 0.05 * SECOND
23
24
 
24
25
  async def increment() -> int:
25
26
  nonlocal counter
@@ -27,9 +28,9 @@ class TestCallMemoized:
27
28
  return counter
28
29
 
29
30
  for _ in range(2):
30
- assert (await call_memoized(increment, 0.05)) == 1
31
+ assert (await call_memoized(increment, delta)) == 1
31
32
  assert counter == 1
32
- await sleep(0.1)
33
+ await sleep_dur(duration=2 * delta)
33
34
  for _ in range(2):
34
- assert (await call_memoized(increment, 0.05)) == 2
35
+ assert (await call_memoized(increment, delta)) == 2
35
36
  assert counter == 2
@@ -1,20 +1,32 @@
1
1
  from __future__ import annotations
2
2
 
3
- from time import sleep
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from hypothesis import example, given
6
- from hypothesis.strategies import floats, integers, none
6
+ from hypothesis.strategies import integers, none
7
7
 
8
+ from utilities.asyncio import sleep_dur
8
9
  from utilities.cachetools import TTLSet, cache
10
+ from utilities.hypothesis import time_deltas_whenever
11
+ from utilities.whenever2 import SECOND
12
+
13
+ if TYPE_CHECKING:
14
+ from whenever import TimeDelta
9
15
 
10
16
 
11
17
  class TestCache:
12
18
  @example(max_size=None, max_duration=None)
13
- @example(max_size=None, max_duration=1.0)
19
+ @example(max_size=None, max_duration=SECOND)
14
20
  @example(max_size=1, max_duration=None)
15
- @example(max_size=1, max_duration=1.0)
16
- @given(max_size=integers(1, 10) | none(), max_duration=floats(0.1, 10.0) | none())
17
- def test_main(self, *, max_size: int, max_duration: float) -> None:
21
+ @example(max_size=1, max_duration=SECOND)
22
+ @given(
23
+ max_size=integers(1, 10) | none(),
24
+ max_duration=time_deltas_whenever(
25
+ min_value=0.1 * SECOND, max_value=10.0 * SECOND
26
+ )
27
+ | none(),
28
+ )
29
+ def test_main(self, *, max_size: int, max_duration: TimeDelta) -> None:
18
30
  counter = 0
19
31
 
20
32
  @cache(max_size=max_size, max_duration=max_duration)
@@ -48,10 +60,11 @@ class TestTTLSet:
48
60
  set_ = TTLSet(range(3))
49
61
  assert len(set_) == 3
50
62
 
51
- def test_max_duration(self) -> None:
52
- set_ = TTLSet(range(3), max_duration=0.1)
63
+ async def test_max_duration(self) -> None:
64
+ delta = 0.1 * SECOND
65
+ set_ = TTLSet(range(3), max_duration=delta)
53
66
  assert set_ == {0, 1, 2}
54
- sleep(0.2)
67
+ await sleep_dur(duration=2 * delta)
55
68
  assert set_ == set()
56
69
 
57
70
  def test_max_size(self) -> None:
@@ -68,8 +68,6 @@ from utilities.hypothesis import (
68
68
  int_arrays,
69
69
  lists_fixed_length,
70
70
  min_and_max_datetimes,
71
- min_and_maybe_max_datetimes,
72
- min_and_maybe_max_sizes,
73
71
  months,
74
72
  namespace_mixins,
75
73
  numbers,
@@ -729,59 +727,6 @@ class TestMinAndMaxDateTimes:
729
727
  assert max_datetime == max_value
730
728
 
731
729
 
732
- class TestMinAndMaybeMaxDateTimes:
733
- @given(
734
- data=data(),
735
- min_value=zoned_datetimes() | none() | just(zoned_datetimes() | none()),
736
- max_value=zoned_datetimes()
737
- | none()
738
- | sentinels()
739
- | just(zoned_datetimes() | none() | sentinels()),
740
- )
741
- def test_main(
742
- self,
743
- *,
744
- data: DataObject,
745
- min_value: MaybeSearchStrategy[dt.datetime | None],
746
- max_value: MaybeSearchStrategy[dt.datetime | None | Sentinel],
747
- ) -> None:
748
- min_datetime, max_datetime = data.draw(
749
- min_and_maybe_max_datetimes(min_value=min_value, max_value=max_value)
750
- )
751
- assert (max_datetime is None) or (min_datetime <= max_datetime)
752
- if isinstance(min_value, dt.datetime):
753
- assert min_datetime == min_value
754
- if isinstance(max_value, dt.datetime) or (max_value is None):
755
- assert max_datetime == max_value
756
-
757
-
758
- class TestMinAndMaybeMaxSizes:
759
- @given(
760
- data=data(),
761
- min_value=integers(min_value=0) | none() | just(integers(min_value=0) | none()),
762
- max_value=integers(min_value=0)
763
- | none()
764
- | sentinels()
765
- | just(integers(min_value=0) | none() | sentinels()),
766
- )
767
- def test_main(
768
- self,
769
- *,
770
- data: DataObject,
771
- min_value: MaybeSearchStrategy[int | None],
772
- max_value: MaybeSearchStrategy[int | None | Sentinel],
773
- ) -> None:
774
- min_size, max_size = data.draw(
775
- min_and_maybe_max_sizes(min_value=min_value, max_value=max_value)
776
- )
777
- assert min_size >= 0
778
- assert (max_size is None) or (min_size <= max_size)
779
- if isinstance(min_value, int):
780
- assert min_size == min_value
781
- if isinstance(max_value, int) or (max_value is None):
782
- assert max_size == max_value
783
-
784
-
785
730
  class TestMonths:
786
731
  @given(data=data())
787
732
  def test_main(self, *, data: DataObject) -> None:
@@ -81,6 +81,7 @@ from utilities.polars import check_polars_dataframe, zoned_datetime
81
81
  from utilities.sentinel import Sentinel, sentinel
82
82
  from utilities.types import LogLevel, MaybeIterable, PathLike
83
83
  from utilities.typing import get_args
84
+ from utilities.tzlocal import LOCAL_TIME_ZONE
84
85
  from utilities.whenever2 import MINUTE, SECOND, get_now
85
86
 
86
87
  if TYPE_CHECKING:
@@ -169,7 +170,7 @@ class TestGetLogRecords:
169
170
  "level": UInt64,
170
171
  "path_name": String,
171
172
  "line_num": UInt64,
172
- "datetime": zoned_datetime(time_zone="local"),
173
+ "datetime": zoned_datetime(time_zone=LOCAL_TIME_ZONE),
173
174
  "func_name": String,
174
175
  "stack_info": String,
175
176
  "extra": Object,
@@ -0,0 +1,259 @@
1
+ from __future__ import annotations
2
+
3
+ from re import search
4
+ from typing import TYPE_CHECKING
5
+
6
+ from hypothesis import HealthCheck, given, settings
7
+ from hypothesis.strategies import DataObject, data, sampled_from
8
+ from pytest import raises
9
+
10
+ from utilities.hypothesis import (
11
+ assume_does_not_raise,
12
+ date_deltas_whenever,
13
+ dates_whenever,
14
+ pairs,
15
+ plain_datetimes_whenever,
16
+ time_deltas_whenever,
17
+ zoned_datetimes_whenever,
18
+ )
19
+ from utilities.period import (
20
+ DatePeriod,
21
+ ZonedDateTimePeriod,
22
+ _PeriodAsDict,
23
+ _PeriodInvalidError,
24
+ _PeriodTimeZoneError,
25
+ )
26
+ from utilities.tzdata import USCentral, USEastern
27
+ from utilities.whenever2 import DAY
28
+ from utilities.zoneinfo import UTC, get_time_zone_name
29
+
30
+ if TYPE_CHECKING:
31
+ from collections.abc import Callable
32
+
33
+ from whenever import Date, DateDelta, PlainDateTime, TimeDelta, ZonedDateTime
34
+
35
+
36
+ class TestDatePeriod:
37
+ @given(dates=pairs(dates_whenever(), sorted=True), delta=date_deltas_whenever())
38
+ @settings(suppress_health_check={HealthCheck.filter_too_much})
39
+ def test_add(self, *, dates: tuple[Date, Date], delta: DateDelta) -> None:
40
+ start, end = dates
41
+ period = DatePeriod(start, end)
42
+ with assume_does_not_raise(ValueError, match="Resulting date out of range"):
43
+ result = period + delta
44
+ expected = DatePeriod(start + delta, end + delta)
45
+ assert result == expected
46
+
47
+ @given(date=dates_whenever(), dates=pairs(dates_whenever(), sorted=True))
48
+ def test_contains(self, *, date: Date, dates: tuple[Date, Date]) -> None:
49
+ start, end = dates
50
+ period = DatePeriod(start, end)
51
+ result = date in period
52
+ expected = start <= date <= end
53
+ assert result is expected
54
+
55
+ @given(dates=pairs(dates_whenever(), sorted=True))
56
+ def test_delta(self, *, dates: tuple[Date, Date]) -> None:
57
+ start, end = dates
58
+ period = DatePeriod(start, end)
59
+ assert period.delta == (end - start)
60
+
61
+ @given(dates=pairs(dates_whenever(), sorted=True))
62
+ def test_hashable(self, *, dates: tuple[Date, Date]) -> None:
63
+ start, end = dates
64
+ period = DatePeriod(start, end)
65
+ _ = hash(period)
66
+
67
+ @given(dates=pairs(dates_whenever(), sorted=True), func=sampled_from([repr, str]))
68
+ def test_repr(self, *, dates: tuple[Date, Date], func: Callable[..., str]) -> None:
69
+ start, end = dates
70
+ period = DatePeriod(start, end)
71
+ result = func(period)
72
+ assert search(r"^DatePeriod\(\d{4}-\d{2}-\d{2}, \d{4}-\d{2}-\d{2}\)$", result)
73
+
74
+ @given(
75
+ dates1=pairs(dates_whenever(), sorted=True),
76
+ dates2=pairs(dates_whenever(), sorted=True),
77
+ )
78
+ def test_sortable(
79
+ self, *, dates1: tuple[Date, Date], dates2: tuple[Date, Date]
80
+ ) -> None:
81
+ start1, end1 = dates1
82
+ start2, end2 = dates2
83
+ period1 = DatePeriod(start1, end1)
84
+ period2 = DatePeriod(start2, end2)
85
+ _ = sorted([period1, period2])
86
+
87
+ @given(dates=pairs(dates_whenever(), sorted=True), delta=date_deltas_whenever())
88
+ @settings(suppress_health_check={HealthCheck.filter_too_much})
89
+ def test_sub(self, *, dates: tuple[Date, Date], delta: DateDelta) -> None:
90
+ start, end = dates
91
+ period = DatePeriod(start, end)
92
+ with assume_does_not_raise(ValueError, match="Resulting date out of range"):
93
+ result = period - delta
94
+ expected = DatePeriod(start - delta, end - delta)
95
+ assert result == expected
96
+
97
+ @given(dates=pairs(dates_whenever(), sorted=True))
98
+ def test_to_dict(self, *, dates: tuple[Date, Date]) -> None:
99
+ start, end = dates
100
+ period = DatePeriod(start, end)
101
+ result = period.to_dict()
102
+ expected = _PeriodAsDict(start=start, end=end)
103
+ assert result == expected
104
+
105
+ @given(dates=pairs(dates_whenever(), unique=True, sorted=True))
106
+ def test_error_period_invalid(self, *, dates: tuple[Date, Date]) -> None:
107
+ start, end = dates
108
+ with raises(_PeriodInvalidError, match="Invalid period; got .* > .*"):
109
+ _ = DatePeriod(end, start)
110
+
111
+
112
+ class TestZonedDateTimePeriod:
113
+ @given(
114
+ datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
115
+ delta=time_deltas_whenever(),
116
+ )
117
+ @settings(suppress_health_check={HealthCheck.filter_too_much})
118
+ def test_add(
119
+ self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime], delta: TimeDelta
120
+ ) -> None:
121
+ start, end = datetimes
122
+ period = ZonedDateTimePeriod(start, end)
123
+ with assume_does_not_raise(ValueError, match="Instant is out of range"):
124
+ result = period + delta
125
+ expected = ZonedDateTimePeriod(start + delta, end + delta)
126
+ assert result == expected
127
+
128
+ @given(
129
+ datetime=zoned_datetimes_whenever(),
130
+ datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
131
+ )
132
+ def test_contains(
133
+ self, *, datetime: ZonedDateTime, datetimes: tuple[ZonedDateTime, ZonedDateTime]
134
+ ) -> None:
135
+ start, end = datetimes
136
+ period = ZonedDateTimePeriod(start, end)
137
+ result = datetime in period
138
+ expected = start <= datetime <= end
139
+ assert result is expected
140
+
141
+ @given(
142
+ datetime=zoned_datetimes_whenever(),
143
+ datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
144
+ )
145
+ def test_contain_datetime(
146
+ self, *, datetime: ZonedDateTime, datetimes: tuple[ZonedDateTime, ZonedDateTime]
147
+ ) -> None:
148
+ start, end = datetimes
149
+ period = ZonedDateTimePeriod(start, end)
150
+ result = datetime in period
151
+ expected = start <= datetime <= end
152
+ assert result is expected
153
+
154
+ @given(datetimes=pairs(zoned_datetimes_whenever(), sorted=True))
155
+ def test_delta(self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime]) -> None:
156
+ start, end = datetimes
157
+ period = ZonedDateTimePeriod(start, end)
158
+ assert period.delta == (end - start)
159
+
160
+ @given(datetimes=pairs(zoned_datetimes_whenever(), sorted=True))
161
+ def test_hashable(self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime]) -> None:
162
+ start, end = datetimes
163
+ period = ZonedDateTimePeriod(start, end)
164
+ _ = hash(period)
165
+
166
+ @given(
167
+ data=data(),
168
+ datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
169
+ func=sampled_from([repr, str]),
170
+ )
171
+ def test_repr(
172
+ self,
173
+ *,
174
+ data: DataObject,
175
+ datetimes: tuple[ZonedDateTime, ZonedDateTime],
176
+ func: Callable[..., str],
177
+ ) -> None:
178
+ start, end = datetimes
179
+ datetimes = data.draw(pairs(zoned_datetimes_whenever(), sorted=True))
180
+ start, end = datetimes
181
+ period = ZonedDateTimePeriod(start, end)
182
+ result = func(period)
183
+ assert search(
184
+ r"^ZonedDateTimePeriod\(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?, \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?\[.+\]\)$",
185
+ result,
186
+ )
187
+
188
+ @given(
189
+ dates1=pairs(zoned_datetimes_whenever(), sorted=True),
190
+ dates2=pairs(zoned_datetimes_whenever(), sorted=True),
191
+ )
192
+ def test_sortable(
193
+ self,
194
+ *,
195
+ dates1: tuple[ZonedDateTime, ZonedDateTime],
196
+ dates2: tuple[ZonedDateTime, ZonedDateTime],
197
+ ) -> None:
198
+ start1, end1 = dates1
199
+ start2, end2 = dates2
200
+ period1 = ZonedDateTimePeriod(start1, end1)
201
+ period2 = ZonedDateTimePeriod(start2, end2)
202
+ _ = sorted([period1, period2])
203
+
204
+ @given(
205
+ datetimes=pairs(zoned_datetimes_whenever(), sorted=True),
206
+ delta=time_deltas_whenever(),
207
+ )
208
+ @settings(suppress_health_check={HealthCheck.filter_too_much})
209
+ def test_sub(
210
+ self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime], delta: TimeDelta
211
+ ) -> None:
212
+ start, end = datetimes
213
+ period = ZonedDateTimePeriod(start, end)
214
+ with assume_does_not_raise(ValueError, match="Instant is out of range"):
215
+ result = period - delta
216
+ expected = ZonedDateTimePeriod(start - delta, end - delta)
217
+ assert result == expected
218
+
219
+ @given(datetimes=pairs(zoned_datetimes_whenever(), sorted=True))
220
+ def test_to_dict(self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime]) -> None:
221
+ start, end = datetimes
222
+ period = ZonedDateTimePeriod(start, end)
223
+ result = period.to_dict()
224
+ expected = _PeriodAsDict(start=start, end=end)
225
+ assert result == expected
226
+
227
+ @given(datetimes=pairs(zoned_datetimes_whenever(), sorted=True))
228
+ def test_to_tz(self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime]) -> None:
229
+ start, end = datetimes
230
+ period = ZonedDateTimePeriod(start, end)
231
+ with assume_does_not_raise(OverflowError, match="date value out of range"):
232
+ result = period.to_tz(UTC)
233
+ assert result.time_zone == UTC
234
+ name = get_time_zone_name(UTC)
235
+ expected = ZonedDateTimePeriod(start.to_tz(name), end.to_tz(name))
236
+ assert result == expected
237
+
238
+ @given(datetimes=pairs(zoned_datetimes_whenever(), unique=True, sorted=True))
239
+ @settings(suppress_health_check={HealthCheck.filter_too_much})
240
+ def test_error_period_invalid(
241
+ self, *, datetimes: tuple[ZonedDateTime, ZonedDateTime]
242
+ ) -> None:
243
+ start, end = datetimes
244
+ with raises(_PeriodInvalidError, match="Invalid period; got .* > .*"):
245
+ _ = ZonedDateTimePeriod(end, start)
246
+
247
+ @given(datetimes=pairs(plain_datetimes_whenever(), sorted=True))
248
+ def test_error_period_time_zone(
249
+ self, *, datetimes: tuple[PlainDateTime, PlainDateTime]
250
+ ) -> None:
251
+ plain_start, plain_end = datetimes
252
+ with assume_does_not_raise(OverflowError, match="date value out of range"):
253
+ start = (plain_start - DAY).assume_tz(USCentral.key)
254
+ end = (plain_end + DAY).assume_tz(USEastern.key)
255
+ with raises(
256
+ _PeriodTimeZoneError,
257
+ match="Period must contain exactly one time zone; got .* and .*",
258
+ ):
259
+ _ = ZonedDateTimePeriod(start, end)
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from zoneinfo import ZoneInfo
4
+
5
+ from hypothesis import given
6
+ from hypothesis.strategies import sampled_from
7
+
8
+ from utilities.tzdata import HongKong, Tokyo, USCentral, USEastern
9
+
10
+
11
+ class TestTimeZones:
12
+ @given(time_zone=sampled_from([HongKong, Tokyo, USCentral, USEastern]))
13
+ def test_main(self, *, time_zone: ZoneInfo) -> None:
14
+ assert isinstance(time_zone, ZoneInfo)
@@ -10,7 +10,7 @@ from pytest import raises
10
10
 
11
11
  from utilities.hypothesis import zoned_datetimes
12
12
  from utilities.tzdata import HongKong, Tokyo
13
- from utilities.tzlocal import get_local_time_zone
13
+ from utilities.tzlocal import LOCAL_TIME_ZONE, LOCAL_TIME_ZONE_NAME
14
14
  from utilities.zoneinfo import (
15
15
  UTC,
16
16
  _EnsureTimeZoneInvalidTZInfoError,
@@ -45,8 +45,7 @@ class TestEnsureTimeZone:
45
45
 
46
46
  def test_local(self) -> None:
47
47
  result = ensure_time_zone("local")
48
- expected = get_local_time_zone()
49
- assert result is expected
48
+ assert result is LOCAL_TIME_ZONE
50
49
 
51
50
  @given(data=data(), time_zone=timezones())
52
51
  def test_zoned_datetime(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
@@ -78,8 +77,7 @@ class TestGetTimeZoneName:
78
77
 
79
78
  def test_local(self) -> None:
80
79
  result = get_time_zone_name("local")
81
- expected = get_local_time_zone().key
82
- assert result is expected
80
+ assert result == LOCAL_TIME_ZONE_NAME
83
81
 
84
82
 
85
83
  class TestTimeZones:
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.131.12"
3
+ __version__ = "0.131.13"
@@ -5,25 +5,22 @@ from typing import TYPE_CHECKING, ParamSpec, TypeVar
5
5
 
6
6
  from atools import memoize
7
7
 
8
- from utilities.datetime import datetime_duration_to_timedelta
9
8
  from utilities.types import Coroutine1
10
9
 
11
10
  if TYPE_CHECKING:
12
- import datetime as dt
13
-
14
- from utilities.types import Duration
11
+ from whenever import TimeDelta
15
12
 
16
13
 
17
14
  _P = ParamSpec("_P")
18
15
  _R = TypeVar("_R")
19
16
  _AsyncFunc = Callable[_P, Coroutine1[_R]]
20
- type _Key = tuple[_AsyncFunc, dt.timedelta]
17
+ type _Key = tuple[_AsyncFunc, TimeDelta]
21
18
  _MEMOIZED_FUNCS: dict[_Key, _AsyncFunc] = {}
22
19
 
23
20
 
24
21
  async def call_memoized(
25
22
  func: _AsyncFunc[_P, _R],
26
- refresh: Duration | None = None,
23
+ refresh: TimeDelta | None = None,
27
24
  /,
28
25
  *args: _P.args,
29
26
  **kwargs: _P.kwargs,
@@ -31,13 +28,14 @@ async def call_memoized(
31
28
  """Call an asynchronous function, with possible memoization."""
32
29
  if refresh is None:
33
30
  return await func(*args, **kwargs)
34
- timedelta = datetime_duration_to_timedelta(refresh)
35
- key: _Key = (func, timedelta)
31
+ key: _Key = (func, refresh)
36
32
  memoized_func: _AsyncFunc[_P, _R]
37
33
  try:
38
34
  memoized_func = _MEMOIZED_FUNCS[key]
39
35
  except KeyError:
40
- memoized_func = _MEMOIZED_FUNCS[(key)] = memoize(duration=refresh)(func)
36
+ memoized_func = _MEMOIZED_FUNCS[(key)] = memoize(duration=refresh.in_seconds())(
37
+ func
38
+ )
41
39
  return await memoized_func(*args, **kwargs)
42
40
 
43
41
 
@@ -8,10 +8,10 @@ from typing import TYPE_CHECKING, Any, TypeVar, override
8
8
  import cachetools
9
9
  from cachetools.func import ttl_cache
10
10
 
11
- from utilities.datetime import datetime_duration_to_float
12
-
13
11
  if TYPE_CHECKING:
14
- from utilities.types import Duration, TCallable
12
+ from whenever import TimeDelta
13
+
14
+ from utilities.types import TCallable
15
15
 
16
16
  _K = TypeVar("_K")
17
17
  _T = TypeVar("_T")
@@ -25,15 +25,13 @@ class TTLCache(cachetools.TTLCache[_K, _V]):
25
25
  self,
26
26
  *,
27
27
  max_size: int | None = None,
28
- max_duration: Duration | None = None,
28
+ max_duration: TimeDelta | None = None,
29
29
  timer: Callable[[], float] = monotonic,
30
30
  get_size_of: Callable[[Any], int] | None = None,
31
31
  ) -> None:
32
32
  super().__init__(
33
33
  maxsize=inf if max_size is None else max_size,
34
- ttl=inf
35
- if max_duration is None
36
- else datetime_duration_to_float(max_duration),
34
+ ttl=inf if max_duration is None else max_duration.in_seconds(),
37
35
  timer=timer,
38
36
  getsizeof=get_size_of,
39
37
  )
@@ -54,7 +52,7 @@ class TTLSet(MutableSet[_T]):
54
52
  /,
55
53
  *,
56
54
  max_size: int | None = None,
57
- max_duration: Duration | None = None,
55
+ max_duration: TimeDelta | None = None,
58
56
  timer: Callable[[], float] = monotonic,
59
57
  get_size_of: Callable[[Any], int] | None = None,
60
58
  ) -> None:
@@ -103,14 +101,14 @@ class TTLSet(MutableSet[_T]):
103
101
  def cache(
104
102
  *,
105
103
  max_size: int | None = None,
106
- max_duration: Duration | None = None,
104
+ max_duration: TimeDelta | None = None,
107
105
  timer: Callable[[], float] = monotonic,
108
106
  typed_: bool = False,
109
107
  ) -> Callable[[TCallable], TCallable]:
110
108
  """Decorate a function with `max_size` and/or `ttl` settings."""
111
109
  return ttl_cache(
112
110
  maxsize=inf if max_size is None else max_size,
113
- ttl=inf if max_duration is None else datetime_duration_to_float(max_duration),
111
+ ttl=inf if max_duration is None else max_duration.in_seconds(),
114
112
  timer=timer,
115
113
  typed=typed_,
116
114
  )