dycw-utilities 0.131.4__tar.gz → 0.131.6__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 (220) hide show
  1. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/PKG-INFO +1 -1
  2. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/pyproject.toml +2 -2
  3. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_hypothesis.py +11 -4
  4. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_operator.py +9 -9
  5. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_parse.py +4 -3
  6. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_whenever2.py +73 -1
  7. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/__init__.py +1 -1
  8. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/hypothesis.py +24 -3
  9. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/whenever2.py +96 -4
  10. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/.gitignore +0 -0
  11. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/LICENSE +0 -0
  12. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/README.md +0 -0
  13. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/__init__.py +0 -0
  14. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/conftest.py +0 -0
  15. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/__init__.py +0 -0
  16. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_missing/__init__.py +0 -0
  17. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_missing/module.py +0 -0
  18. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/__init__.py +0 -0
  19. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/outer_1.py +0 -0
  20. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/outer_2.py +0 -0
  21. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  22. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  23. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  24. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  25. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_without/__init__.py +0 -0
  26. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_without/module_1.py +0 -0
  27. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/package_without/module_2.py +0 -0
  28. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/standalone.py +0 -0
  29. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/modules/with_imports.py +0 -0
  30. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  31. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  32. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  33. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  34. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  35. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  36. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  37. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  38. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_aiolimiter.py +0 -0
  39. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_altair.py +0 -0
  40. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_asyncio.py +0 -0
  41. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_asyncio_classes/__init__.py +0 -0
  42. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_asyncio_classes/loopers.py +0 -0
  43. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_asyncio_classes/redis.py +0 -0
  44. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_atomicwrites.py +0 -0
  45. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_atools.py +0 -0
  46. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_cachetools.py +0 -0
  47. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_click.py +0 -0
  48. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_concurrent.py +0 -0
  49. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_contextlib.py +0 -0
  50. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_contextvars.py +0 -0
  51. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_cryptography.py +0 -0
  52. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_cvxpy.py +0 -0
  53. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_dataclasses.py +0 -0
  54. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_datetime.py +0 -0
  55. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_enum.py +0 -0
  56. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_errors.py +0 -0
  57. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_eventkit.py +0 -0
  58. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_fastapi.py +0 -0
  59. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_fpdf2.py +0 -0
  60. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_functions.py +0 -0
  61. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_functools.py +0 -0
  62. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_getpass.py +0 -0
  63. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_git.py +0 -0
  64. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_hashlib.py +0 -0
  65. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_http.py +0 -0
  66. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_importlib.py +0 -0
  67. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_inflect.py +0 -0
  68. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_ipython.py +0 -0
  69. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_iterables.py +0 -0
  70. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_jupyter.py +0 -0
  71. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_libcst.py +0 -0
  72. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_lightweight_charts.py +0 -0
  73. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_logging.py +0 -0
  74. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_luigi.py +0 -0
  75. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_math.py +0 -0
  76. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_memory_profiler.py +0 -0
  77. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_modules.py +0 -0
  78. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_more_itertools.py +0 -0
  79. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_numpy.py +0 -0
  80. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_optuna.py +0 -0
  81. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_orjson.py +0 -0
  82. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_os.py +0 -0
  83. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pathlib.py +0 -0
  84. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_period.py +0 -0
  85. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pickle.py +0 -0
  86. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_platform.py +0 -0
  87. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_polars.py +0 -0
  88. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_polars_ols.py +0 -0
  89. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pottery.py +0 -0
  90. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pqdm.py +0 -0
  91. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_psutil.py +0 -0
  92. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pydantic.py +0 -0
  93. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pyinstrument.py +0 -0
  94. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pyrsistent.py +0 -0
  95. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pytest.py +0 -0
  96. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_pytest_regressions.py +0 -0
  97. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_python_dotenv.py +0 -0
  98. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_random.py +0 -0
  99. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_re.py +0 -0
  100. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_redis.py +0 -0
  101. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_reprlib.py +0 -0
  102. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_scipy.py +0 -0
  103. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_sentinel.py +0 -0
  104. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_shelve.py +0 -0
  105. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_slack_sdk.py +0 -0
  106. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_socket.py +0 -0
  107. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_sqlalchemy.py +0 -0
  108. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_sqlalchemy_polars.py +0 -0
  109. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_statsmodel.py +0 -0
  110. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_streamlit.py +0 -0
  111. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_string.py +0 -0
  112. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_tempfile.py +0 -0
  113. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_tenacity.py +0 -0
  114. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_text.py +0 -0
  115. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_threading.py +0 -0
  116. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_timer.py +0 -0
  117. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_traceback.py +0 -0
  118. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_types.py +0 -0
  119. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_typing.py +0 -0
  120. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_typing_funcs/__init__.py +0 -0
  121. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_typing_funcs/no_future.py +0 -0
  122. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_typing_funcs/with_future.py +0 -0
  123. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_tzdata.py +0 -0
  124. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_tzlocal.py +0 -0
  125. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_uuid.py +0 -0
  126. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_version.py +0 -0
  127. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_warnings.py +0 -0
  128. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_whenever.py +0 -0
  129. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_zipfile.py +0 -0
  130. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/tests/test_zoneinfo.py +0 -0
  131. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/aiolimiter.py +0 -0
  132. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/altair.py +0 -0
  133. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/asyncio.py +0 -0
  134. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/atomicwrites.py +0 -0
  135. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/atools.py +0 -0
  136. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/cachetools.py +0 -0
  137. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/click.py +0 -0
  138. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/concurrent.py +0 -0
  139. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/contextlib.py +0 -0
  140. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/contextvars.py +0 -0
  141. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/cryptography.py +0 -0
  142. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/cvxpy.py +0 -0
  143. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/dataclasses.py +0 -0
  144. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/datetime.py +0 -0
  145. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/enum.py +0 -0
  146. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/errors.py +0 -0
  147. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/eventkit.py +0 -0
  148. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/fastapi.py +0 -0
  149. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/fpdf2.py +0 -0
  150. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/functions.py +0 -0
  151. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/functools.py +0 -0
  152. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/getpass.py +0 -0
  153. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/git.py +0 -0
  154. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/hashlib.py +0 -0
  155. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/http.py +0 -0
  156. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/importlib.py +0 -0
  157. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/inflect.py +0 -0
  158. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/ipython.py +0 -0
  159. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/iterables.py +0 -0
  160. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/jupyter.py +0 -0
  161. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/libcst.py +0 -0
  162. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/lightweight_charts.py +0 -0
  163. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/logging.py +0 -0
  164. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/luigi.py +0 -0
  165. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/math.py +0 -0
  166. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/memory_profiler.py +0 -0
  167. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/modules.py +0 -0
  168. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/more_itertools.py +0 -0
  169. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/numpy.py +0 -0
  170. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/operator.py +0 -0
  171. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/optuna.py +0 -0
  172. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/orjson.py +0 -0
  173. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/os.py +0 -0
  174. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/parse.py +0 -0
  175. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pathlib.py +0 -0
  176. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/period.py +0 -0
  177. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pickle.py +0 -0
  178. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/platform.py +0 -0
  179. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/polars.py +0 -0
  180. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/polars_ols.py +0 -0
  181. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pottery.py +0 -0
  182. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pqdm.py +0 -0
  183. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/psutil.py +0 -0
  184. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/py.typed +0 -0
  185. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pydantic.py +0 -0
  186. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pyinstrument.py +0 -0
  187. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pyrsistent.py +0 -0
  188. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pytest.py +0 -0
  189. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/pytest_regressions.py +0 -0
  190. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/python_dotenv.py +0 -0
  191. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/random.py +0 -0
  192. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/re.py +0 -0
  193. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/redis.py +0 -0
  194. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/reprlib.py +0 -0
  195. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/scipy.py +0 -0
  196. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/sentinel.py +0 -0
  197. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/shelve.py +0 -0
  198. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/slack_sdk.py +0 -0
  199. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/socket.py +0 -0
  200. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/sqlalchemy.py +0 -0
  201. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/sqlalchemy_polars.py +0 -0
  202. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/statsmodels.py +0 -0
  203. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/streamlit.py +0 -0
  204. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/string.py +0 -0
  205. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/tempfile.py +0 -0
  206. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/tenacity.py +0 -0
  207. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/text.py +0 -0
  208. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/threading.py +0 -0
  209. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/timer.py +0 -0
  210. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/traceback.py +0 -0
  211. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/types.py +0 -0
  212. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/typing.py +0 -0
  213. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/tzdata.py +0 -0
  214. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/tzlocal.py +0 -0
  215. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/uuid.py +0 -0
  216. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/version.py +0 -0
  217. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/warnings.py +0 -0
  218. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/whenever.py +0 -0
  219. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/zipfile.py +0 -0
  220. {dycw_utilities-0.131.4 → dycw_utilities-0.131.6}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.131.4
3
+ Version: 0.131.6
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.4"
97
+ version = "0.131.6"
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.4"
124
+ current_version = "0.131.6"
125
125
 
126
126
  [[tool.bumpversion.files]]
127
127
  filename = "src/utilities/__init__.py"
@@ -183,14 +183,16 @@ class TestBoolArrays:
183
183
  assert array.shape == shape
184
184
 
185
185
 
186
- class TestDateDeltas:
187
- @given(data=data())
188
- def test_main(self, *, data: DataObject) -> None:
186
+ class TestDateDeltasWhenever:
187
+ @given(data=data(), parsable=booleans())
188
+ def test_main(self, *, data: DataObject, parsable: bool) -> None:
189
189
  min_value = data.draw(date_deltas_whenever() | none())
190
190
  max_value = data.draw(date_deltas_whenever() | none())
191
191
  with assume_does_not_raise(InvalidArgument):
192
192
  delta = data.draw(
193
- date_deltas_whenever(min_value=min_value, max_value=max_value)
193
+ date_deltas_whenever(
194
+ min_value=min_value, max_value=max_value, parsable=parsable
195
+ )
194
196
  )
195
197
  assert isinstance(delta, DateDelta)
196
198
  years, months, days = delta.in_years_months_days()
@@ -206,6 +208,8 @@ class TestDateDeltas:
206
208
  assert max_years == 0
207
209
  assert max_months == 0
208
210
  assert days <= max_days
211
+ if parsable:
212
+ assert DateDelta.parse_common_iso(delta.format_common_iso()) == delta
209
213
 
210
214
 
211
215
  class TestDateDurations:
@@ -295,6 +299,7 @@ class TestDatesWhenever:
295
299
  with assume_does_not_raise(InvalidArgument):
296
300
  date = data.draw(dates_whenever(min_value=min_value, max_value=max_value))
297
301
  assert isinstance(date, Date)
302
+ assert Date.parse_common_iso(date.format_common_iso()) == date
298
303
  if min_value is not None:
299
304
  assert date >= min_value
300
305
  if max_value is not None:
@@ -894,6 +899,7 @@ class TestPlainDateTimesWhenever:
894
899
  plain_datetimes_whenever(min_value=min_value, max_value=max_value)
895
900
  )
896
901
  assert isinstance(datetime, PlainDateTime)
902
+ assert PlainDateTime.parse_common_iso(datetime.format_common_iso()) == datetime
897
903
  if min_value is not None:
898
904
  assert datetime >= min_value
899
905
  if max_value is not None:
@@ -1273,6 +1279,7 @@ class TestZonedDateTimesWhenever:
1273
1279
  )
1274
1280
  )
1275
1281
  assert isinstance(datetime, ZonedDateTime)
1282
+ assert ZonedDateTime.parse_common_iso(datetime.format_common_iso()) == datetime
1276
1283
  assert datetime.tz == time_zone.key
1277
1284
  if min_value is not None:
1278
1285
  assert datetime >= min_value
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime as dt
4
3
  from dataclasses import dataclass
5
4
  from enum import Enum, auto
6
5
  from functools import partial
@@ -23,16 +22,15 @@ from hypothesis.strategies import (
23
22
  recursive,
24
23
  sampled_from,
25
24
  times,
26
- timezones,
27
25
  tuples,
28
26
  uuids,
29
27
  )
30
28
  from polars import DataFrame, Int64
31
29
  from pytest import raises
30
+ from whenever import DateTimeDelta
32
31
 
33
32
  import utilities.math
34
33
  import utilities.operator
35
- from tests.conftest import IS_CI_AND_WINDOWS
36
34
  from tests.test_typing_funcs.with_future import (
37
35
  DataClassFutureCustomEquality,
38
36
  DataClassFutureDefaultInInitChild,
@@ -60,6 +58,7 @@ from utilities.hypothesis import (
60
58
  from utilities.math import MAX_INT64, MIN_INT64
61
59
  from utilities.operator import IsEqualError
62
60
  from utilities.polars import are_frames_equal
61
+ from utilities.whenever2 import get_now
63
62
 
64
63
  if TYPE_CHECKING:
65
64
  from collections.abc import Sequence
@@ -106,11 +105,12 @@ def base_objects(
106
105
  | timedeltas_2w()
107
106
  | uuids()
108
107
  | versions()
108
+ | zoned_datetimes(
109
+ min_value=get_now().py_datetime(),
110
+ max_value=(get_now() + DateTimeDelta(years=1)).py_datetime(),
111
+ valid=True,
112
+ )
109
113
  )
110
- if IS_CI_AND_WINDOWS:
111
- base |= zoned_datetimes()
112
- else:
113
- base |= zoned_datetimes(time_zone=timezones() | just(dt.UTC), valid=True)
114
114
  if dataclass_custom_equality:
115
115
  base |= builds(DataClassFutureCustomEquality)
116
116
  if dataclass_default_in_init_child:
@@ -348,8 +348,8 @@ class TestIsEqual:
348
348
  assert utilities.operator.is_equal(first, second, abs_tol=1e-8)
349
349
 
350
350
  @given(
351
- x=dates() | datetimes() | zoned_datetimes(time_zone=timezones()),
352
- y=dates() | datetimes() | zoned_datetimes(time_zone=timezones()),
351
+ x=dates() | datetimes() | zoned_datetimes(),
352
+ y=dates() | datetimes() | zoned_datetimes(),
353
353
  )
354
354
  def test_dates_or_datetimes(self, *, x: DateOrDateTime, y: DateOrDateTime) -> None:
355
355
  result = utilities.operator.is_equal(x, y)
@@ -36,6 +36,7 @@ from utilities.errors import ImpossibleCaseError
36
36
  from utilities.functions import ensure_path
37
37
  from utilities.hypothesis import (
38
38
  datetime_durations,
39
+ int64s,
39
40
  numbers,
40
41
  paths,
41
42
  plain_datetimes,
@@ -78,10 +79,10 @@ class TestSerializeAndParseObject:
78
79
  result = parse_object(dt.datetime, serialized)
79
80
  assert result == datetime
80
81
 
81
- @given(mapping=dictionaries(dates(), zoned_datetimes()))
82
- def test_dict(self, *, mapping: dict[dt.date, dt.datetime]) -> None:
82
+ @given(mapping=dictionaries(dates(), int64s()))
83
+ def test_dict(self, *, mapping: dict[dt.date, int]) -> None:
83
84
  serialized = serialize_object(mapping)
84
- result = parse_object(dict[dt.date, dt.datetime], serialized)
85
+ result = parse_object(dict[dt.date, int], serialized)
85
86
  assert result == mapping
86
87
 
87
88
  @given(duration=datetime_durations(two_way=True))
@@ -6,23 +6,31 @@ from zoneinfo import ZoneInfo
6
6
  from hypothesis import given
7
7
  from hypothesis.strategies import just, timezones
8
8
  from pytest import mark, param, raises
9
- from whenever import DateDelta, DateTimeDelta, TimeDelta, ZonedDateTime
9
+ from whenever import Date, DateDelta, DateTimeDelta, TimeDelta, ZonedDateTime
10
10
 
11
11
  from tests.conftest import IS_CI
12
12
  from utilities.hypothesis import zoned_datetimes_whenever
13
13
  from utilities.tzdata import HongKong, Tokyo
14
+ from utilities.tzlocal import LOCAL_TIME_ZONE
14
15
  from utilities.whenever2 import (
15
16
  DATE_DELTA_MAX,
16
17
  DATE_DELTA_MIN,
18
+ DATE_DELTA_PARSABLE_MAX,
19
+ DATE_DELTA_PARSABLE_MIN,
17
20
  DATE_MAX,
18
21
  DATE_MIN,
19
22
  DATE_TIME_DELTA_MAX,
20
23
  DATE_TIME_DELTA_MIN,
24
+ DATE_TIME_DELTA_PARSABLE_MAX,
25
+ DATE_TIME_DELTA_PARSABLE_MIN,
26
+ NOW_LOCAL,
21
27
  NOW_UTC,
22
28
  PLAIN_DATE_TIME_MAX,
23
29
  PLAIN_DATE_TIME_MIN,
24
30
  TIME_DELTA_MAX,
25
31
  TIME_DELTA_MIN,
32
+ TODAY_LOCAL,
33
+ TODAY_UTC,
26
34
  ZONED_DATE_TIME_MAX,
27
35
  ZONED_DATE_TIME_MIN,
28
36
  WheneverLogRecord,
@@ -31,6 +39,8 @@ from utilities.whenever2 import (
31
39
  from_timestamp_nanos,
32
40
  get_now,
33
41
  get_now_local,
42
+ get_today,
43
+ get_today_local,
34
44
  )
35
45
  from utilities.zoneinfo import UTC
36
46
 
@@ -77,6 +87,28 @@ class TestGetNowLocal:
77
87
  time_zones = {ETC, HongKong, Tokyo, UTC}
78
88
  assert any(now.tz == time_zone.key for time_zone in time_zones)
79
89
 
90
+ def test_constant(self) -> None:
91
+ assert isinstance(NOW_LOCAL, ZonedDateTime)
92
+ assert NOW_LOCAL.tz == LOCAL_TIME_ZONE.key
93
+
94
+
95
+ class TestGetToday:
96
+ def test_function(self) -> None:
97
+ today = get_today()
98
+ assert isinstance(today, Date)
99
+
100
+ def test_constant(self) -> None:
101
+ assert isinstance(TODAY_UTC, Date)
102
+
103
+
104
+ class TestGetTodayLocal:
105
+ def test_function(self) -> None:
106
+ today = get_today_local()
107
+ assert isinstance(today, Date)
108
+
109
+ def test_constant(self) -> None:
110
+ assert isinstance(TODAY_LOCAL, Date)
111
+
80
112
 
81
113
  class TestMinMax:
82
114
  def test_date_min(self) -> None:
@@ -95,6 +127,22 @@ class TestMinMax:
95
127
  with raises(ValueError, match="Addition result out of bounds"):
96
128
  _ = DATE_DELTA_MAX + DateDelta(days=1)
97
129
 
130
+ def test_date_delta_parsable_min(self) -> None:
131
+ def func(delta: DateDelta, /) -> None:
132
+ _ = DateDelta.parse_common_iso(delta.format_common_iso())
133
+
134
+ _ = func(DATE_DELTA_PARSABLE_MIN)
135
+ with raises(ValueError, match="Invalid format: '.*'"):
136
+ _ = func(DATE_DELTA_PARSABLE_MIN - DateDelta(days=1))
137
+
138
+ def test_date_delta_parsable_max(self) -> None:
139
+ def func(delta: DateDelta, /) -> None:
140
+ _ = DateDelta.parse_common_iso(delta.format_common_iso())
141
+
142
+ _ = func(DATE_DELTA_PARSABLE_MAX)
143
+ with raises(ValueError, match="Invalid format: '.*'"):
144
+ _ = func(DATE_DELTA_PARSABLE_MAX + DateDelta(days=1))
145
+
98
146
  @mark.parametrize(
99
147
  "delta",
100
148
  [
@@ -129,6 +177,22 @@ class TestMinMax:
129
177
  with raises(ValueError, match="Addition result out of bounds"):
130
178
  _ = DATE_TIME_DELTA_MAX + delta
131
179
 
180
+ def test_date_time_delta_parsable_min(self) -> None:
181
+ def func(delta: DateTimeDelta, /) -> None:
182
+ _ = DateTimeDelta.parse_common_iso(delta.format_common_iso())
183
+
184
+ _ = func(DATE_TIME_DELTA_PARSABLE_MIN)
185
+ with raises(ValueError, match="Addition result out of bounds"):
186
+ _ = func(DATE_TIME_DELTA_PARSABLE_MIN - DateTimeDelta(nanoseconds=1))
187
+
188
+ def test_date_time_delta_parsable_max(self) -> None:
189
+ def func(delta: DateTimeDelta, /) -> None:
190
+ _ = DateTimeDelta.parse_common_iso(delta.format_common_iso())
191
+
192
+ _ = func(DATE_TIME_DELTA_PARSABLE_MAX)
193
+ with raises(ValueError, match="Invalid format or out of range: '.*'"):
194
+ _ = func(DATE_TIME_DELTA_PARSABLE_MAX + TimeDelta(nanoseconds=1))
195
+
132
196
  def test_plain_date_time_min(self) -> None:
133
197
  with raises(ValueError, match=r"Result of subtract\(\) out of range"):
134
198
  _ = PLAIN_DATE_TIME_MIN.subtract(nanoseconds=1, ignore_dst=True)
@@ -148,6 +212,7 @@ class TestMinMax:
148
212
  ],
149
213
  )
150
214
  def test_time_delta_min(self, *, delta: TimeDelta) -> None:
215
+ _ = TimeDelta.parse_common_iso(TIME_DELTA_MIN.format_common_iso())
151
216
  with raises(ValueError, match="Addition result out of range"):
152
217
  _ = TIME_DELTA_MIN - delta
153
218
 
@@ -166,6 +231,7 @@ class TestMinMax:
166
231
  def test_time_delta_max(self, *, delta: TimeDelta, is_ok: bool) -> None:
167
232
  if is_ok:
168
233
  _ = TIME_DELTA_MAX + delta
234
+ _ = TimeDelta.parse_common_iso(delta.format_common_iso())
169
235
  else:
170
236
  with raises(ValueError, match="Addition result out of range"):
171
237
  _ = TIME_DELTA_MAX + delta
@@ -186,3 +252,9 @@ class TestWheneverLogRecord:
186
252
 
187
253
  def test_get_length(self) -> None:
188
254
  assert isinstance(WheneverLogRecord._get_length(), int)
255
+
256
+ def test_get_time_zone(self) -> None:
257
+ assert isinstance(WheneverLogRecord._get_time_zone(), ZoneInfo)
258
+
259
+ def test_get_time_zone_key(self) -> None:
260
+ assert isinstance(WheneverLogRecord._get_time_zone_key(), str)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.131.4"
3
+ __version__ = "0.131.6"
@@ -47,7 +47,7 @@ from hypothesis.strategies import (
47
47
  uuids,
48
48
  )
49
49
  from hypothesis.utils.conventions import not_set
50
- from whenever import Date, DateDelta, PlainDateTime
50
+ from whenever import Date, DateDelta
51
51
 
52
52
  from utilities.datetime import (
53
53
  DATETIME_MAX_NAIVE,
@@ -97,7 +97,7 @@ if TYPE_CHECKING:
97
97
 
98
98
  from hypothesis.database import ExampleDatabase
99
99
  from numpy.random import RandomState
100
- from whenever import ZonedDateTime
100
+ from whenever import PlainDateTime, ZonedDateTime
101
101
 
102
102
  from utilities.numpy import NDArrayB, NDArrayF, NDArrayI, NDArrayO
103
103
  from utilities.types import Duration, Number, RoundMode, TimeZoneLike
@@ -167,9 +167,15 @@ def date_deltas_whenever(
167
167
  *,
168
168
  min_value: MaybeSearchStrategy[DateDelta | None] = None,
169
169
  max_value: MaybeSearchStrategy[DateDelta | None] = None,
170
+ parsable: MaybeSearchStrategy[bool] = False,
170
171
  ) -> DateDelta:
171
172
  """Strategy for generating date deltas."""
172
- from utilities.whenever2 import DATE_DELTA_MAX, DATE_DELTA_MIN
173
+ from utilities.whenever2 import (
174
+ DATE_DELTA_MAX,
175
+ DATE_DELTA_MIN,
176
+ DATE_DELTA_PARSABLE_MAX,
177
+ DATE_DELTA_PARSABLE_MIN,
178
+ )
173
179
 
174
180
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
175
181
  match min_value_:
@@ -192,6 +198,19 @@ def date_deltas_whenever(
192
198
  max_years, max_months, max_days = max_value_.in_years_months_days()
193
199
  assert max_years == 0
194
200
  assert max_months == 0
201
+ if draw2(draw, parsable):
202
+ parsable_min_years, parsable_min_months, parsable_min_days = (
203
+ DATE_DELTA_PARSABLE_MIN.in_years_months_days()
204
+ )
205
+ assert parsable_min_years == 0
206
+ assert parsable_min_months == 0
207
+ min_days = max(min_days, parsable_min_days)
208
+ parsable_max_years, parsable_max_months, parsable_max_days = (
209
+ DATE_DELTA_PARSABLE_MAX.in_years_months_days()
210
+ )
211
+ assert parsable_max_years == 0
212
+ assert parsable_max_months == 0
213
+ max_days = min(max_days, parsable_max_days)
195
214
  days = draw(integers(min_value=min_days, max_value=max_days))
196
215
  return DateDelta(days=days)
197
216
 
@@ -1050,6 +1069,8 @@ def plain_datetimes_whenever(
1050
1069
  max_value: MaybeSearchStrategy[PlainDateTime | None] = None,
1051
1070
  ) -> PlainDateTime:
1052
1071
  """Strategy for generating plain datetimes."""
1072
+ from whenever import PlainDateTime
1073
+
1053
1074
  from utilities.whenever2 import PLAIN_DATE_TIME_MAX, PLAIN_DATE_TIME_MIN
1054
1075
 
1055
1076
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
@@ -5,17 +5,33 @@ from functools import cache
5
5
  from logging import LogRecord
6
6
  from typing import TYPE_CHECKING, Any, override
7
7
 
8
- from whenever import Date, DateTimeDelta, PlainDateTime, ZonedDateTime
8
+ from whenever import (
9
+ Date,
10
+ DateDelta,
11
+ DateTimeDelta,
12
+ PlainDateTime,
13
+ Time,
14
+ TimeDelta,
15
+ ZonedDateTime,
16
+ )
9
17
 
10
- from utilities.tzlocal import LOCAL_TIME_ZONE
11
18
  from utilities.zoneinfo import UTC, get_time_zone_name
12
19
 
13
20
  if TYPE_CHECKING:
21
+ from zoneinfo import ZoneInfo
22
+
14
23
  from utilities.types import TimeZoneLike
15
24
 
16
25
 
26
+ ## bounds
27
+
28
+
17
29
  DATE_MIN = Date.from_py_date(dt.date.min)
18
30
  DATE_MAX = Date.from_py_date(dt.date.max)
31
+ TIME_MIN = Time.from_py_time(dt.time.min)
32
+ TIME_MAX = Time.from_py_time(dt.time.max)
33
+
34
+
19
35
  PLAIN_DATE_TIME_MIN = PlainDateTime.from_py_datetime(dt.datetime.min) # noqa: DTZ901
20
36
  PLAIN_DATE_TIME_MAX = PlainDateTime.from_py_datetime(dt.datetime.max) # noqa: DTZ901
21
37
  ZONED_DATE_TIME_MIN = PLAIN_DATE_TIME_MIN.assume_tz(UTC.key)
@@ -28,6 +44,25 @@ TIME_DELTA_MIN = DATE_TIME_DELTA_MIN.time_part()
28
44
  TIME_DELTA_MAX = DATE_TIME_DELTA_MAX.time_part()
29
45
 
30
46
 
47
+ DATE_TIME_DELTA_PARSABLE_MIN = DateTimeDelta(days=-999999, seconds=-316192377600)
48
+ DATE_TIME_DELTA_PARSABLE_MAX = DateTimeDelta(days=999999, seconds=316192377600)
49
+ DATE_DELTA_PARSABLE_MIN = DateDelta(days=-999999)
50
+ DATE_DELTA_PARSABLE_MAX = DateDelta(days=999999)
51
+
52
+
53
+ ## common constants
54
+
55
+
56
+ ZERO_TIME = Time()
57
+ MICROSECOND = TimeDelta(microseconds=1)
58
+ MILLISECOND = TimeDelta(milliseconds=1)
59
+ SECOND = TimeDelta(seconds=1)
60
+ MINUTE = TimeDelta(minutes=1)
61
+ HOUR = TimeDelta(hours=1)
62
+ DAY = DateDelta(days=1)
63
+ WEEK = DateDelta(weeks=1)
64
+
65
+
31
66
  ##
32
67
 
33
68
 
@@ -62,6 +97,28 @@ def get_now_local() -> ZonedDateTime:
62
97
  return get_now(time_zone="local")
63
98
 
64
99
 
100
+ NOW_LOCAL = get_now_local()
101
+
102
+
103
+ ##
104
+
105
+
106
+ def get_today(*, time_zone: TimeZoneLike = UTC) -> Date:
107
+ """Get the current, timezone-aware local date."""
108
+ return get_now(time_zone=time_zone).date()
109
+
110
+
111
+ TODAY_UTC = get_today(time_zone=UTC)
112
+
113
+
114
+ def get_today_local() -> Date:
115
+ """Get the current, timezone-aware local date."""
116
+ return get_today(time_zone="local")
117
+
118
+
119
+ TODAY_LOCAL = get_today_local()
120
+
121
+
65
122
  ##
66
123
 
67
124
 
@@ -88,7 +145,24 @@ class WheneverLogRecord(LogRecord):
88
145
  )
89
146
  length = self._get_length()
90
147
  plain = format(get_now_local().to_plain().format_common_iso(), f"{length}s")
91
- self.zoned_datetime = f"{plain}[{LOCAL_TIME_ZONE.key}]"
148
+ time_zone = self._get_time_zone_key()
149
+ self.zoned_datetime = f"{plain}[{time_zone}]"
150
+
151
+ @classmethod
152
+ @cache
153
+ def _get_time_zone(cls) -> ZoneInfo:
154
+ """Get the local timezone."""
155
+ try:
156
+ from utilities.tzlocal import get_local_time_zone
157
+ except ModuleNotFoundError: # pragma: no cover
158
+ return UTC
159
+ return get_local_time_zone()
160
+
161
+ @classmethod
162
+ @cache
163
+ def _get_time_zone_key(cls) -> str:
164
+ """Get the local timezone as a string."""
165
+ return cls._get_time_zone().key
92
166
 
93
167
  @classmethod
94
168
  @cache
@@ -101,14 +175,31 @@ class WheneverLogRecord(LogRecord):
101
175
  __all__ = [
102
176
  "DATE_DELTA_MAX",
103
177
  "DATE_DELTA_MIN",
178
+ "DATE_DELTA_PARSABLE_MAX",
179
+ "DATE_DELTA_PARSABLE_MIN",
104
180
  "DATE_MAX",
105
181
  "DATE_MIN",
106
182
  "DATE_TIME_DELTA_MAX",
107
183
  "DATE_TIME_DELTA_MIN",
184
+ "DATE_TIME_DELTA_PARSABLE_MAX",
185
+ "DATE_TIME_DELTA_PARSABLE_MIN",
186
+ "DAY",
187
+ "HOUR",
188
+ "MICROSECOND",
189
+ "MILLISECOND",
190
+ "MINUTE",
191
+ "NOW_LOCAL",
108
192
  "PLAIN_DATE_TIME_MAX",
109
193
  "PLAIN_DATE_TIME_MIN",
194
+ "SECOND",
110
195
  "TIME_DELTA_MAX",
111
196
  "TIME_DELTA_MIN",
197
+ "TIME_MAX",
198
+ "TIME_MIN",
199
+ "TODAY_LOCAL",
200
+ "TODAY_UTC",
201
+ "WEEK",
202
+ "ZERO_TIME",
112
203
  "ZONED_DATE_TIME_MAX",
113
204
  "ZONED_DATE_TIME_MIN",
114
205
  "WheneverLogRecord",
@@ -116,6 +207,7 @@ __all__ = [
116
207
  "from_timestamp_millis",
117
208
  "from_timestamp_nanos",
118
209
  "get_now",
119
- "get_now",
120
210
  "get_now_local",
211
+ "get_today",
212
+ "get_today_local",
121
213
  ]