dycw-utilities 0.160.2__tar.gz → 0.161.1__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 (211) hide show
  1. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/PKG-INFO +1 -1
  2. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/pyproject.toml +2 -2
  3. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/conftest.py +3 -1
  4. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_hypothesis.py +22 -11
  5. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_polars.py +12 -12
  6. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_types.py +2 -3
  7. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_whenever.py +51 -47
  8. dycw_utilities-0.161.1/src/tests/test_zoneinfo.py +131 -0
  9. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/__init__.py +1 -1
  10. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/hypothesis.py +20 -4
  11. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/polars.py +6 -6
  12. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/types.py +11 -1
  13. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/whenever.py +21 -33
  14. dycw_utilities-0.161.1/src/utilities/zoneinfo.py +133 -0
  15. dycw_utilities-0.160.2/src/tests/test_zoneinfo.py +0 -103
  16. dycw_utilities-0.160.2/src/utilities/zoneinfo.py +0 -75
  17. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/.gitignore +0 -0
  18. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/LICENSE +0 -0
  19. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/README.md +0 -0
  20. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/__init__.py +0 -0
  21. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/__init__.py +0 -0
  22. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_missing/__init__.py +0 -0
  23. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_missing/module.py +0 -0
  24. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/__init__.py +0 -0
  25. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/outer_1.py +0 -0
  26. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/outer_2.py +0 -0
  27. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  28. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  29. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  30. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  31. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_without/__init__.py +0 -0
  32. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_without/module_1.py +0 -0
  33. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/package_without/module_2.py +0 -0
  34. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/standalone.py +0 -0
  35. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/modules/with_imports.py +0 -0
  36. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  37. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  38. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  39. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  40. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  41. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  42. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  43. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  44. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_altair.py +0 -0
  45. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_asyncio.py +0 -0
  46. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_atomicwrites.py +0 -0
  47. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_atools.py +0 -0
  48. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_cachetools.py +0 -0
  49. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_click.py +0 -0
  50. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_concurrent.py +0 -0
  51. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_contextlib.py +0 -0
  52. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_contextvars.py +0 -0
  53. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_cryptography.py +0 -0
  54. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_cvxpy.py +0 -0
  55. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_dataclasses.py +0 -0
  56. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_enum.py +0 -0
  57. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_errors.py +0 -0
  58. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_eventkit.py +0 -0
  59. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_fastapi.py +0 -0
  60. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_fpdf2.py +0 -0
  61. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_functions.py +0 -0
  62. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_functools.py +0 -0
  63. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_getpass.py +0 -0
  64. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_gzip.py +0 -0
  65. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_hashlib.py +0 -0
  66. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_http.py +0 -0
  67. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_importlib.py +0 -0
  68. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_inflect.py +0 -0
  69. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_ipython.py +0 -0
  70. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_iterables.py +0 -0
  71. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_json.py +0 -0
  72. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_jupyter.py +0 -0
  73. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_libcst.py +0 -0
  74. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_lightweight_charts.py +0 -0
  75. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_logging.py +0 -0
  76. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_math.py +0 -0
  77. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_memory_profiler.py +0 -0
  78. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_modules.py +0 -0
  79. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_more_itertools.py +0 -0
  80. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_numpy.py +0 -0
  81. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_objects/__init__.py +0 -0
  82. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_objects/objects.py +0 -0
  83. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_operator.py +0 -0
  84. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_optuna.py +0 -0
  85. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_orjson.py +0 -0
  86. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_os.py +0 -0
  87. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_parse.py +0 -0
  88. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pathlib.py +0 -0
  89. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pickle.py +0 -0
  90. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_platform.py +0 -0
  91. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_polars_ols.py +0 -0
  92. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_postgres.py +0 -0
  93. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pottery.py +0 -0
  94. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pqdm.py +0 -0
  95. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_psutil.py +0 -0
  96. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pyinstrument.py +0 -0
  97. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pytest.py +0 -0
  98. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pytest_randomly.py +0 -0
  99. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_pytest_regressions.py +0 -0
  100. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_random.py +0 -0
  101. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_re.py +0 -0
  102. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_redis.py +0 -0
  103. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_reprlib.py +0 -0
  104. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_scipy.py +0 -0
  105. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_sentinel.py +0 -0
  106. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_shelve.py +0 -0
  107. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_slack_sdk.py +0 -0
  108. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_socket.py +0 -0
  109. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_sqlalchemy.py +0 -0
  110. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_sqlalchemy_polars.py +0 -0
  111. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_statsmodels.py +0 -0
  112. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_string.py +0 -0
  113. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_tempfile.py +0 -0
  114. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_text.py +0 -0
  115. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_threading.py +0 -0
  116. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_timer.py +0 -0
  117. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_traceback.py +0 -0
  118. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_typed_settings.py +0 -0
  119. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_typing.py +0 -0
  120. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_typing_funcs/__init__.py +0 -0
  121. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_typing_funcs/no_future.py +0 -0
  122. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_typing_funcs/with_future.py +0 -0
  123. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_tzdata.py +0 -0
  124. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_tzlocal.py +0 -0
  125. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_uuid.py +0 -0
  126. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_version.py +0 -0
  127. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_warnings.py +0 -0
  128. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/tests/test_zipfile.py +0 -0
  129. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/altair.py +0 -0
  130. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/asyncio.py +0 -0
  131. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/atomicwrites.py +0 -0
  132. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/atools.py +0 -0
  133. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/cachetools.py +0 -0
  134. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/click.py +0 -0
  135. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/concurrent.py +0 -0
  136. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/contextlib.py +0 -0
  137. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/contextvars.py +0 -0
  138. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/cryptography.py +0 -0
  139. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/cvxpy.py +0 -0
  140. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/dataclasses.py +0 -0
  141. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/enum.py +0 -0
  142. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/errors.py +0 -0
  143. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/eventkit.py +0 -0
  144. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/fastapi.py +0 -0
  145. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/fpdf2.py +0 -0
  146. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/functions.py +0 -0
  147. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/functools.py +0 -0
  148. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/getpass.py +0 -0
  149. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/gzip.py +0 -0
  150. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/hashlib.py +0 -0
  151. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/http.py +0 -0
  152. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/importlib.py +0 -0
  153. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/inflect.py +0 -0
  154. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/ipython.py +0 -0
  155. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/iterables.py +0 -0
  156. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/json.py +0 -0
  157. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/jupyter.py +0 -0
  158. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/libcst.py +0 -0
  159. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/lightweight_charts.py +0 -0
  160. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/logging.py +0 -0
  161. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/math.py +0 -0
  162. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/memory_profiler.py +0 -0
  163. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/modules.py +0 -0
  164. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/more_itertools.py +0 -0
  165. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/numpy.py +0 -0
  166. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/operator.py +0 -0
  167. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/optuna.py +0 -0
  168. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/orjson.py +0 -0
  169. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/os.py +0 -0
  170. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/parse.py +0 -0
  171. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pathlib.py +0 -0
  172. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pickle.py +0 -0
  173. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/platform.py +0 -0
  174. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/polars_ols.py +0 -0
  175. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/postgres.py +0 -0
  176. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pottery.py +0 -0
  177. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pqdm.py +0 -0
  178. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/psutil.py +0 -0
  179. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/py.typed +0 -0
  180. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pyinstrument.py +0 -0
  181. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pytest.py +0 -0
  182. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pytest_plugins/__init__.py +0 -0
  183. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pytest_plugins/pytest_randomly.py +0 -0
  184. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pytest_plugins/pytest_regressions.py +0 -0
  185. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/pytest_regressions.py +0 -0
  186. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/random.py +0 -0
  187. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/re.py +0 -0
  188. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/redis.py +0 -0
  189. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/reprlib.py +0 -0
  190. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/scipy.py +0 -0
  191. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/sentinel.py +0 -0
  192. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/shelve.py +0 -0
  193. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/slack_sdk.py +0 -0
  194. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/socket.py +0 -0
  195. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/sqlalchemy.py +0 -0
  196. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/sqlalchemy_polars.py +0 -0
  197. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/statsmodels.py +0 -0
  198. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/string.py +0 -0
  199. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/tempfile.py +0 -0
  200. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/text.py +0 -0
  201. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/threading.py +0 -0
  202. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/timer.py +0 -0
  203. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/traceback.py +0 -0
  204. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/typed_settings.py +0 -0
  205. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/typing.py +0 -0
  206. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/tzdata.py +0 -0
  207. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/tzlocal.py +0 -0
  208. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/uuid.py +0 -0
  209. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/version.py +0 -0
  210. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/warnings.py +0 -0
  211. {dycw_utilities-0.160.2 → dycw_utilities-0.161.1}/src/utilities/zipfile.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.160.2
3
+ Version: 0.161.1
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -227,7 +227,7 @@ dependencies = [
227
227
  name = "dycw-utilities"
228
228
  readme = "README.md"
229
229
  requires-python = ">= 3.12"
230
- version = "0.160.2"
230
+ version = "0.161.1"
231
231
 
232
232
  [project.entry-points.pytest11]
233
233
  pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
@@ -259,7 +259,7 @@ test = [
259
259
  # bump-my-version
260
260
  [tool.bumpversion]
261
261
  allow_dirty = true
262
- current_version = "0.160.2"
262
+ current_version = "0.161.1"
263
263
 
264
264
  [[tool.bumpversion.files]]
265
265
  filename = "src/utilities/__init__.py"
@@ -9,7 +9,7 @@ from hypothesis import HealthCheck
9
9
  from pytest import fixture, mark, param, skip
10
10
 
11
11
  from utilities.contextlib import enhanced_context_manager
12
- from utilities.platform import IS_MAC, IS_NOT_LINUX, IS_WINDOWS
12
+ from utilities.platform import IS_LINUX, IS_MAC, IS_NOT_LINUX, IS_WINDOWS
13
13
  from utilities.re import ExtractGroupError, extract_group
14
14
  from utilities.whenever import MINUTE, get_now, parse_plain_local
15
15
 
@@ -29,11 +29,13 @@ SKIPIF_CI = mark.skipif(IS_CI, reason="Skipped for CI")
29
29
  IS_CI_AND_NOT_LINUX = IS_CI and IS_NOT_LINUX
30
30
  IS_CI_AND_WINDOWS = IS_CI and IS_WINDOWS
31
31
  IS_CI_AND_MAC = IS_CI and IS_MAC
32
+ IS_CI_AND_LINUX = IS_CI and IS_LINUX
32
33
  SKIPIF_CI_AND_NOT_LINUX = mark.skipif(
33
34
  IS_CI_AND_NOT_LINUX, reason="Skipped for CI/non-Linux"
34
35
  )
35
36
  SKIPIF_CI_AND_WINDOWS = mark.skipif(IS_CI_AND_WINDOWS, reason="Skipped for CI/Windows")
36
37
  SKIPIF_CI_AND_MAC = mark.skipif(IS_CI_AND_MAC, reason="Skipped for CI/Mac")
38
+ SKIPIF_CI_AND_LINUX = mark.skipif(IS_CI_AND_LINUX, reason="Skipped for CI/Linux")
37
39
 
38
40
 
39
41
  # hypothesis
@@ -5,6 +5,7 @@ from itertools import pairwise
5
5
  from pathlib import Path
6
6
  from re import search
7
7
  from typing import TYPE_CHECKING, Any, cast
8
+ from zoneinfo import ZoneInfo
8
9
 
9
10
  from hypothesis import assume, given, settings
10
11
  from hypothesis.errors import InvalidArgument
@@ -20,7 +21,6 @@ from hypothesis.strategies import (
20
21
  just,
21
22
  none,
22
23
  sets,
23
- timezones,
24
24
  )
25
25
  from libcst import Import, ImportFrom
26
26
  from numpy import inf, int64, isfinite, isinf, isnan, ravel, rint
@@ -34,7 +34,6 @@ from whenever import (
34
34
  PlainDateTime,
35
35
  Time,
36
36
  TimeDelta,
37
- TimeZoneNotFoundError,
38
37
  YearMonth,
39
38
  ZonedDateTime,
40
39
  )
@@ -97,6 +96,7 @@ from utilities.hypothesis import (
97
96
  urls,
98
97
  versions,
99
98
  year_months,
99
+ zone_infos,
100
100
  zoned_date_time_periods,
101
101
  zoned_date_times,
102
102
  )
@@ -134,6 +134,7 @@ from utilities.whenever import (
134
134
  DatePeriod,
135
135
  TimePeriod,
136
136
  ZonedDateTimePeriod,
137
+ get_now,
137
138
  to_days,
138
139
  to_nanoseconds,
139
140
  to_py_time_delta,
@@ -141,7 +142,6 @@ from utilities.whenever import (
141
142
 
142
143
  if TYPE_CHECKING:
143
144
  from collections.abc import Set as AbstractSet
144
- from zoneinfo import ZoneInfo
145
145
 
146
146
  from utilities.sentinel import Sentinel
147
147
  from utilities.tempfile import TemporaryDirectory
@@ -1186,11 +1186,21 @@ class TestYearMonths:
1186
1186
  assert year_month.on_day(28) <= DATE_TWO_DIGIT_YEAR_MAX
1187
1187
 
1188
1188
 
1189
+ class TestZoneInfos:
1190
+ @given(data=data())
1191
+ def test_main(self, *, data: DataObject) -> None:
1192
+ time_zone = data.draw(zone_infos())
1193
+ assert isinstance(time_zone, ZoneInfo)
1194
+ assert time_zone.key not in {"Etc/UTC", "localtime"}
1195
+ _ = get_now(time_zone)
1196
+
1197
+
1189
1198
  class TestZonedDateTimePeriods:
1190
- @given(data=data(), time_zone=timezones())
1191
- def test_main(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
1199
+ @given(data=data())
1200
+ def test_main(self, *, data: DataObject) -> None:
1192
1201
  min_value = data.draw(zoned_date_times() | none())
1193
1202
  max_value = data.draw(zoned_date_times() | none())
1203
+ time_zone = data.draw(zone_infos())
1194
1204
  with assume_does_not_raise(InvalidArgument):
1195
1205
  period = data.draw(
1196
1206
  zoned_date_time_periods(
@@ -1206,10 +1216,11 @@ class TestZonedDateTimePeriods:
1206
1216
 
1207
1217
 
1208
1218
  class TestZonedDateTimes:
1209
- @given(data=data(), time_zone=timezones())
1210
- def test_main(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
1219
+ @given(data=data())
1220
+ def test_main(self, *, data: DataObject) -> None:
1211
1221
  min_value = data.draw(zoned_date_times() | none())
1212
1222
  max_value = data.draw(zoned_date_times() | none())
1223
+ time_zone = data.draw(zone_infos())
1213
1224
  with assume_does_not_raise(InvalidArgument):
1214
1225
  datetime = data.draw(
1215
1226
  zoned_date_times(
@@ -1225,9 +1236,9 @@ class TestZonedDateTimes:
1225
1236
  if max_value is not None:
1226
1237
  assert datetime <= max_value
1227
1238
 
1228
- @given(data=data(), time_zone=timezones())
1229
- def test_examples(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
1230
- with assume_does_not_raise(TimeZoneNotFoundError):
1231
- max_value = ZonedDateTime(1, 1, 2, tz=time_zone.key)
1239
+ @given(data=data())
1240
+ def test_examples(self, *, data: DataObject) -> None:
1241
+ time_zone = data.draw(zone_infos())
1242
+ max_value = ZonedDateTime(1, 1, 2, tz=time_zone.key)
1232
1243
  datetime = data.draw(zoned_date_times(max_value=max_value, time_zone=time_zone))
1233
1244
  _ = datetime.py_datetime()
@@ -222,7 +222,7 @@ from utilities.whenever import (
222
222
  get_now_plain,
223
223
  get_today,
224
224
  )
225
- from utilities.zoneinfo import UTC, get_time_zone_name
225
+ from utilities.zoneinfo import UTC, to_time_zone_name
226
226
 
227
227
  if TYPE_CHECKING:
228
228
  from collections.abc import Callable, Iterable, Mapping, Sequence
@@ -1426,18 +1426,18 @@ class TestDataClassToSchema:
1426
1426
 
1427
1427
 
1428
1428
  class TestDatetimeDTypes:
1429
- @given(
1430
- case=sampled_from([
1431
- (HongKong, DatetimeHongKong),
1432
- (Tokyo, DatetimeTokyo),
1433
- (USCentral, DatetimeUSCentral),
1434
- (USEastern, DatetimeUSEastern),
1435
- (UTC, DatetimeUTC),
1436
- ])
1429
+ @mark.parametrize(
1430
+ ("time_zone", "dtype"),
1431
+ [
1432
+ param(HongKong, DatetimeHongKong),
1433
+ param(Tokyo, DatetimeTokyo),
1434
+ param(USCentral, DatetimeUSCentral),
1435
+ param(USEastern, DatetimeUSEastern),
1436
+ param(UTC, DatetimeUTC),
1437
+ ],
1437
1438
  )
1438
- def test_main(self, *, case: tuple[ZoneInfo, Datetime]) -> None:
1439
- time_zone, dtype = case
1440
- name = get_time_zone_name(time_zone)
1439
+ def test_main(self, *, time_zone: ZoneInfo, dtype: Datetime) -> None:
1440
+ name = to_time_zone_name(time_zone)
1441
1441
  expected = dtype.time_zone
1442
1442
  assert name == expected
1443
1443
 
@@ -9,8 +9,7 @@ from hypothesis.strategies import sampled_from
9
9
  from pytest import mark, param
10
10
 
11
11
  from utilities.platform import SYSTEM
12
- from utilities.types import Dataclass, Number, PathLike, TimeZone
13
- from utilities.typing import get_literal_elements
12
+ from utilities.types import TIME_ZONES, Dataclass, Number, PathLike
14
13
 
15
14
 
16
15
  class TestDataClassProtocol:
@@ -45,7 +44,7 @@ class TestPathLike:
45
44
 
46
45
  class TestTimeZone:
47
46
  def test_main(self) -> None:
48
- result = set(get_literal_elements(TimeZone))
47
+ result = set(TIME_ZONES)
49
48
  expected = available_timezones()
50
49
  match SYSTEM:
51
50
  case "windows" | "mac":
@@ -8,14 +8,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Self, cast
8
8
  from zoneinfo import ZoneInfo
9
9
 
10
10
  from hypothesis import HealthCheck, given, settings
11
- from hypothesis.strategies import (
12
- DataObject,
13
- data,
14
- integers,
15
- none,
16
- sampled_from,
17
- timezones,
18
- )
11
+ from hypothesis.strategies import DataObject, data, integers, none, sampled_from
19
12
  from pytest import mark, param, raises
20
13
  from whenever import (
21
14
  Date,
@@ -24,7 +17,6 @@ from whenever import (
24
17
  PlainDateTime,
25
18
  Time,
26
19
  TimeDelta,
27
- TimeZoneNotFoundError,
28
20
  Weekday,
29
21
  YearMonth,
30
22
  ZonedDateTime,
@@ -41,6 +33,7 @@ from utilities.hypothesis import (
41
33
  time_deltas,
42
34
  time_periods,
43
35
  times,
36
+ zone_infos,
44
37
  zoned_date_time_periods,
45
38
  zoned_date_times,
46
39
  zoned_date_times_2000,
@@ -150,7 +143,7 @@ from utilities.whenever import (
150
143
  to_zoned_date_time,
151
144
  two_digit_year_month,
152
145
  )
153
- from utilities.zoneinfo import UTC, get_time_zone_name
146
+ from utilities.zoneinfo import UTC
154
147
 
155
148
  if TYPE_CHECKING:
156
149
  from collections.abc import Callable
@@ -382,7 +375,7 @@ class TestFormatCompact:
382
375
 
383
376
  class TestFromTimeStamp:
384
377
  @given(
385
- datetime=zoned_date_times(time_zone=timezones()).map(
378
+ datetime=zoned_date_times(time_zone=zone_infos()).map(
386
379
  lambda d: d.round("second")
387
380
  )
388
381
  )
@@ -392,7 +385,7 @@ class TestFromTimeStamp:
392
385
  assert result == datetime
393
386
 
394
387
  @given(
395
- datetime=zoned_date_times(time_zone=timezones()).map(
388
+ datetime=zoned_date_times(time_zone=zone_infos()).map(
396
389
  lambda d: d.round("millisecond")
397
390
  )
398
391
  )
@@ -401,7 +394,7 @@ class TestFromTimeStamp:
401
394
  result = from_timestamp_millis(timestamp, time_zone=ZoneInfo(datetime.tz))
402
395
  assert result == datetime
403
396
 
404
- @given(datetime=zoned_date_times(time_zone=timezones()))
397
+ @given(datetime=zoned_date_times(time_zone=zone_infos()))
405
398
  def test_nanos(self, *, datetime: ZonedDateTime) -> None:
406
399
  timestamp = datetime.timestamp_nanos()
407
400
  result = from_timestamp_nanos(timestamp, time_zone=ZoneInfo(datetime.tz))
@@ -409,16 +402,16 @@ class TestFromTimeStamp:
409
402
 
410
403
 
411
404
  class TestGetNow:
412
- @given(time_zone=timezones())
405
+ @given(time_zone=zone_infos())
413
406
  def test_function(self, *, time_zone: ZoneInfo) -> None:
414
- with assume_does_not_raise(TimeZoneNotFoundError):
415
- now = get_now(time_zone)
407
+ now = get_now(time_zone)
416
408
  assert isinstance(now, ZonedDateTime)
417
409
  assert now.tz == time_zone.key
418
410
 
419
411
  def test_constant(self) -> None:
420
412
  assert isinstance(NOW_UTC, ZonedDateTime)
421
- assert NOW_UTC.tz == "UTC"
413
+ expected = UTC.key
414
+ assert NOW_UTC.tz == expected
422
415
 
423
416
 
424
417
  class TestGetNowLocal:
@@ -435,10 +428,9 @@ class TestGetNowLocal:
435
428
 
436
429
 
437
430
  class TestGetNowPlain:
438
- @given(time_zone=timezones())
431
+ @given(time_zone=zone_infos())
439
432
  def test_function(self, *, time_zone: ZoneInfo) -> None:
440
- with assume_does_not_raise(TimeZoneNotFoundError):
441
- now = get_now_plain(time_zone)
433
+ now = get_now_plain(time_zone)
442
434
  assert isinstance(now, PlainDateTime)
443
435
 
444
436
  def test_constant(self) -> None:
@@ -1394,32 +1386,50 @@ class TestToZonedDateTime:
1394
1386
  def test_default(self) -> None:
1395
1387
  assert abs(to_zoned_date_time() - get_now()) <= SECOND
1396
1388
 
1397
- @given(date_time=zoned_date_times())
1398
- def test_date_time(self, *, date_time: ZonedDateTime) -> None:
1399
- assert to_zoned_date_time(date_time) == date_time
1389
+ @given(date_time=zoned_date_times(), time_zone=zone_infos())
1390
+ def test_date_time(self, *, date_time: ZonedDateTime, time_zone: ZoneInfo) -> None:
1391
+ result = to_zoned_date_time(date_time, time_zone=time_zone)
1392
+ expected = date_time.to_tz(time_zone.key)
1393
+ assert result.exact_eq(expected)
1400
1394
 
1401
- @given(date_time=zoned_date_times())
1402
- def test_str(self, *, date_time: ZonedDateTime) -> None:
1403
- assert to_zoned_date_time(date_time.format_common_iso()) == date_time
1395
+ @given(date_time=zoned_date_times(), time_zone=zone_infos())
1396
+ def test_str(self, *, date_time: ZonedDateTime, time_zone: ZoneInfo) -> None:
1397
+ result = to_zoned_date_time(date_time.format_common_iso(), time_zone=time_zone)
1398
+ expected = date_time.to_tz(time_zone.key)
1399
+ assert result.exact_eq(expected)
1404
1400
 
1405
- @given(date_time=zoned_date_times_2000)
1406
- def test_py_date_time_zone_info(self, *, date_time: ZonedDateTime) -> None:
1407
- assert to_zoned_date_time(date_time.py_datetime()) == date_time
1401
+ @given(date_time=zoned_date_times_2000, time_zone=zone_infos())
1402
+ def test_py_date_time_zone_info(
1403
+ self, *, date_time: ZonedDateTime, time_zone: ZoneInfo
1404
+ ) -> None:
1405
+ result = to_zoned_date_time(date_time.py_datetime(), time_zone=time_zone)
1406
+ expected = date_time.to_tz(time_zone.key)
1407
+ assert result.exact_eq(expected)
1408
1408
 
1409
- @given(date_time=zoned_date_times_2000)
1410
- def test_py_date_time_dt_utc(self, *, date_time: ZonedDateTime) -> None:
1411
- result = to_zoned_date_time(date_time.py_datetime().astimezone(dt.UTC))
1412
- assert result == date_time
1409
+ @given(date_time=zoned_date_times_2000, time_zone=zone_infos())
1410
+ def test_py_date_time_dt_utc(
1411
+ self, *, date_time: ZonedDateTime, time_zone: ZoneInfo
1412
+ ) -> None:
1413
+ result = to_zoned_date_time(
1414
+ date_time.py_datetime().astimezone(dt.UTC), time_zone=time_zone
1415
+ )
1416
+ expected = date_time.to_tz(time_zone.key)
1417
+ assert result.exact_eq(expected)
1413
1418
 
1414
- @given(date_time=zoned_date_times())
1415
- def test_callable(self, *, date_time: ZonedDateTime) -> None:
1416
- assert to_zoned_date_time(lambda: date_time) == date_time
1419
+ @given(date_time=zoned_date_times(), time_zone=zone_infos())
1420
+ def test_callable(self, *, date_time: ZonedDateTime, time_zone: ZoneInfo) -> None:
1421
+ result = to_zoned_date_time(lambda: date_time, time_zone=time_zone)
1422
+ expected = date_time.to_tz(time_zone.key)
1423
+ assert result.exact_eq(expected)
1417
1424
 
1418
- def test_none(self) -> None:
1419
- assert abs(to_zoned_date_time(None) - get_now()) <= SECOND
1425
+ @given(time_zone=zone_infos())
1426
+ def test_none(self, *, time_zone: ZoneInfo) -> None:
1427
+ result = to_zoned_date_time(None, time_zone=time_zone)
1428
+ assert abs(result - get_now(time_zone)) <= SECOND
1420
1429
 
1421
- def test_sentinel(self) -> None:
1422
- assert to_zoned_date_time(sentinel) is sentinel
1430
+ @given(time_zone=zone_infos())
1431
+ def test_sentinel(self, *, time_zone: ZoneInfo) -> None:
1432
+ assert to_zoned_date_time(sentinel, time_zone=time_zone) is sentinel
1423
1433
 
1424
1434
  @given(date_times=pairs(zoned_date_times()))
1425
1435
  def test_replace_non_sentinel(
@@ -1466,12 +1476,6 @@ class TestWheneverLogRecord:
1466
1476
  def test_get_length(self) -> None:
1467
1477
  assert isinstance(WheneverLogRecord._get_length(), int)
1468
1478
 
1469
- def test_get_time_zone(self) -> None:
1470
- assert isinstance(WheneverLogRecord._get_time_zone(), ZoneInfo)
1471
-
1472
- def test_get_time_zone_key(self) -> None:
1473
- assert isinstance(WheneverLogRecord._get_time_zone_key(), str)
1474
-
1475
1479
 
1476
1480
  class TestZonedDateTimePeriod:
1477
1481
  @given(period=zoned_date_time_periods(), delta=time_deltas())
@@ -1669,7 +1673,7 @@ class TestZonedDateTimePeriod:
1669
1673
  with assume_does_not_raise(OverflowError, match="date value out of range"):
1670
1674
  result = period.to_tz(UTC)
1671
1675
  assert result.time_zone == UTC
1672
- name = get_time_zone_name(UTC)
1676
+ name = UTC.key
1673
1677
  expected = ZonedDateTimePeriod(period.start.to_tz(name), period.end.to_tz(name))
1674
1678
  assert result == expected
1675
1679
 
@@ -0,0 +1,131 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime as dt
4
+ from typing import TYPE_CHECKING, Literal, cast
5
+ from zoneinfo import ZoneInfo
6
+
7
+ from hypothesis import given
8
+ from hypothesis.strategies import DataObject, data, datetimes, just, sampled_from
9
+ from pytest import mark, param, raises
10
+
11
+ from utilities.hypothesis import zone_infos, zoned_date_times
12
+ from utilities.tzdata import HongKong, Tokyo
13
+ from utilities.tzlocal import LOCAL_TIME_ZONE, LOCAL_TIME_ZONE_NAME
14
+ from utilities.zoneinfo import (
15
+ UTC,
16
+ _ToTimeZoneNameInvalidKeyError,
17
+ _ToTimeZoneNameInvalidTZInfoError,
18
+ _ToTimeZoneNamePlainDateTimeError,
19
+ _ToZoneInfoInvalidTZInfoError,
20
+ _ToZoneInfoPlainDateTimeError,
21
+ to_time_zone_name,
22
+ to_zone_info,
23
+ )
24
+
25
+ if TYPE_CHECKING:
26
+ from utilities.types import TimeZoneLike
27
+
28
+
29
+ class TestToZoneInfo:
30
+ @given(time_zone=zone_infos())
31
+ def test_zone_info(self, *, time_zone: ZoneInfo) -> None:
32
+ result = to_zone_info(time_zone)
33
+ assert result is time_zone
34
+
35
+ @given(data=data(), time_zone=zone_infos())
36
+ def test_zoned_date_time(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
37
+ date_time = data.draw(zoned_date_times(time_zone=time_zone))
38
+ result = to_zone_info(date_time)
39
+ assert result is time_zone
40
+
41
+ @mark.parametrize("time_zone", [param("local"), param("localtime")])
42
+ def test_local(self, *, time_zone: Literal["local", "localtime"]) -> None:
43
+ result = to_zone_info(time_zone)
44
+ assert result is LOCAL_TIME_ZONE
45
+
46
+ @given(time_zone=zone_infos())
47
+ def test_str(self, *, time_zone: ZoneInfo) -> None:
48
+ result = to_zone_info(cast("TimeZoneLike", time_zone.key))
49
+ assert result is time_zone
50
+
51
+ def test_tz_info(self) -> None:
52
+ result = to_zone_info(dt.UTC)
53
+ assert result is UTC
54
+
55
+ @given(data=data(), time_zone=zone_infos())
56
+ def test_py_zoned_date_time(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
57
+ date_time = data.draw(datetimes(timezones=just(time_zone)))
58
+ result = to_zone_info(date_time)
59
+ assert result is time_zone
60
+
61
+ def test_error_invalid_tz_info(self) -> None:
62
+ time_zone = dt.timezone(dt.timedelta(hours=12))
63
+ with raises(
64
+ _ToZoneInfoInvalidTZInfoError, match=r"Invalid time-zone: UTC\+12:00"
65
+ ):
66
+ _ = to_zone_info(time_zone)
67
+
68
+ @given(date_time=datetimes())
69
+ def test_error_plain_date_time(self, *, date_time: dt.datetime) -> None:
70
+ with raises(_ToZoneInfoPlainDateTimeError, match="Plain date-time: .*"):
71
+ _ = to_zone_info(date_time)
72
+
73
+
74
+ class TestToTimeZoneName:
75
+ @given(time_zone=zone_infos())
76
+ def test_zone_info(self, *, time_zone: ZoneInfo) -> None:
77
+ result = to_time_zone_name(time_zone)
78
+ expected = time_zone.key
79
+ assert result == expected
80
+
81
+ @given(data=data(), time_zone=zone_infos())
82
+ def test_zoned_date_time(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
83
+ date_time = data.draw(zoned_date_times(time_zone=time_zone))
84
+ result = to_time_zone_name(date_time)
85
+ expected = time_zone.key
86
+ assert result == expected
87
+
88
+ @mark.parametrize("time_zone", [param("local"), param("localtime")])
89
+ def test_local(self, *, time_zone: Literal["local", "localtime"]) -> None:
90
+ result = to_time_zone_name(time_zone)
91
+ assert result == LOCAL_TIME_ZONE_NAME
92
+
93
+ @given(time_zone=zone_infos())
94
+ def test_str(self, *, time_zone: ZoneInfo) -> None:
95
+ result = to_time_zone_name(cast("TimeZoneLike", time_zone.key))
96
+ expected = time_zone.key
97
+ assert result == expected
98
+
99
+ def test_tz_info(self) -> None:
100
+ result = to_time_zone_name(dt.UTC)
101
+ expected = UTC.key
102
+ assert result == expected
103
+
104
+ @given(data=data(), time_zone=zone_infos())
105
+ def test_py_zoned_date_time(self, *, data: DataObject, time_zone: ZoneInfo) -> None:
106
+ date_time = data.draw(datetimes(timezones=just(time_zone)))
107
+ result = to_time_zone_name(date_time)
108
+ expected = time_zone.key
109
+ assert result == expected
110
+
111
+ def test_error_invalid_key(self) -> None:
112
+ with raises(
113
+ _ToTimeZoneNameInvalidKeyError, match="Invalid time-zone: 'invalid'"
114
+ ):
115
+ _ = to_time_zone_name(cast("TimeZoneLike", "invalid"))
116
+
117
+ def test_error_invalid_tz_info(self) -> None:
118
+ time_zone = dt.timezone(dt.timedelta(hours=12))
119
+ with raises(_ToTimeZoneNameInvalidTZInfoError, match="Invalid time-zone: .*"):
120
+ _ = to_time_zone_name(time_zone)
121
+
122
+ @given(date_time=datetimes())
123
+ def test_error_plain_date_time(self, *, date_time: dt.datetime) -> None:
124
+ with raises(_ToTimeZoneNamePlainDateTimeError, match="Plain date-time: .*"):
125
+ _ = to_time_zone_name(date_time)
126
+
127
+
128
+ class TestTimeZones:
129
+ @given(time_zone=sampled_from([HongKong, Tokyo, UTC]))
130
+ def test_main(self, *, time_zone: ZoneInfo) -> None:
131
+ assert isinstance(time_zone, ZoneInfo)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.160.2"
3
+ __version__ = "0.161.1"
@@ -32,6 +32,7 @@ from hypothesis.strategies import (
32
32
  sampled_from,
33
33
  sets,
34
34
  text,
35
+ timezones,
35
36
  uuids,
36
37
  )
37
38
  from hypothesis.utils.conventions import not_set
@@ -97,14 +98,16 @@ from utilities.whenever import (
97
98
  DatePeriod,
98
99
  TimePeriod,
99
100
  ZonedDateTimePeriod,
101
+ get_now,
100
102
  to_date_time_delta,
101
103
  to_days,
102
104
  to_nanoseconds,
103
105
  )
104
- from utilities.zoneinfo import UTC, ensure_time_zone
106
+ from utilities.zoneinfo import UTC, to_zone_info
105
107
 
106
108
  if TYPE_CHECKING:
107
109
  from collections.abc import Collection, Hashable, Iterable, Iterator
110
+ from zoneinfo import ZoneInfo
108
111
 
109
112
  from hypothesis.database import ExampleDatabase
110
113
  from libcst import Import, ImportFrom
@@ -835,7 +838,7 @@ def paths(
835
838
  @composite
836
839
  def _path_parts(draw: DrawFn, /) -> str:
837
840
  part = draw(text_ascii(min_size=1, max_size=10))
838
- reserved = {"AUX", "NUL", "nuL"}
841
+ reserved = {"AUX", "NUL", "nuL", "pRn"}
839
842
  _ = assume(part not in reserved)
840
843
  return part
841
844
 
@@ -1476,6 +1479,19 @@ def year_months(
1476
1479
  ##
1477
1480
 
1478
1481
 
1482
+ @composite
1483
+ def zone_infos(draw: DrawFn, /) -> ZoneInfo:
1484
+ """Strategy for generating time-zones."""
1485
+ time_zone = draw(timezones())
1486
+ _ = assume(time_zone.key not in {"Etc/UTC", "localtime"})
1487
+ with assume_does_not_raise(TimeZoneNotFoundError):
1488
+ _ = get_now(time_zone)
1489
+ return time_zone
1490
+
1491
+
1492
+ ##
1493
+
1494
+
1479
1495
  @composite
1480
1496
  def zoned_date_time_periods(
1481
1497
  draw: DrawFn,
@@ -1509,7 +1525,7 @@ def zoned_date_times(
1509
1525
  ) -> ZonedDateTime:
1510
1526
  """Strategy for generating zoned date-times."""
1511
1527
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1512
- time_zone_ = ensure_time_zone(draw2(draw, time_zone))
1528
+ time_zone_ = to_zone_info(draw2(draw, time_zone))
1513
1529
  match min_value_:
1514
1530
  case None | PlainDateTime():
1515
1531
  ...
@@ -1530,7 +1546,6 @@ def zoned_date_times(
1530
1546
  with (
1531
1547
  assume_does_not_raise(RepeatedTime),
1532
1548
  assume_does_not_raise(SkippedTime),
1533
- assume_does_not_raise(TimeZoneNotFoundError),
1534
1549
  assume_does_not_raise(ValueError, match="Resulting datetime is out of range"),
1535
1550
  ):
1536
1551
  zoned = plain.assume_tz(time_zone_.key, disambiguate="raise")
@@ -1602,6 +1617,7 @@ __all__ = [
1602
1617
  "urls",
1603
1618
  "versions",
1604
1619
  "year_months",
1620
+ "zone_infos",
1605
1621
  "zoned_date_time_periods",
1606
1622
  "zoned_date_times",
1607
1623
  "zoned_date_times_2000",
@@ -104,7 +104,7 @@ from utilities.whenever import (
104
104
  ZonedDateTimePeriod,
105
105
  to_py_time_delta,
106
106
  )
107
- from utilities.zoneinfo import UTC, ensure_time_zone, get_time_zone_name
107
+ from utilities.zoneinfo import UTC, to_time_zone_name
108
108
 
109
109
  if TYPE_CHECKING:
110
110
  from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
@@ -834,7 +834,7 @@ def convert_time_zone(
834
834
 
835
835
  def _convert_time_zone_one(sr: Series, /, *, time_zone: TimeZoneLike = UTC) -> Series:
836
836
  if isinstance(sr.dtype, Datetime):
837
- return sr.dt.convert_time_zone(get_time_zone_name(time_zone))
837
+ return sr.dt.convert_time_zone(to_time_zone_name(time_zone))
838
838
  return sr
839
839
 
840
840
 
@@ -2110,7 +2110,7 @@ def period_range(
2110
2110
  eager: bool = False,
2111
2111
  ) -> Series | Expr:
2112
2112
  """Construct a period range."""
2113
- time_zone_use = None if time_zone is None else ensure_time_zone(time_zone).key
2113
+ time_zone_use = None if time_zone is None else to_time_zone_name(time_zone)
2114
2114
  match end_or_length:
2115
2115
  case ZonedDateTime() as end:
2116
2116
  ...
@@ -2127,7 +2127,7 @@ def period_range(
2127
2127
  time_zone=time_zone_use,
2128
2128
  eager=eager,
2129
2129
  ).alias("start")
2130
- ends = (starts.dt.offset_by(interval)).alias("end")
2130
+ ends = starts.dt.offset_by(interval).alias("end")
2131
2131
  period = struct(starts, ends)
2132
2132
  return try_reify_expr(period, starts, ends)
2133
2133
 
@@ -2220,7 +2220,7 @@ def _replace_time_zone_one(
2220
2220
  sr: Series, /, *, time_zone: TimeZoneLike | None = UTC
2221
2221
  ) -> Series:
2222
2222
  if isinstance(sr.dtype, Datetime):
2223
- time_zone_use = None if time_zone is None else get_time_zone_name(time_zone)
2223
+ time_zone_use = None if time_zone is None else to_time_zone_name(time_zone)
2224
2224
  return sr.dt.replace_time_zone(time_zone_use)
2225
2225
  return sr
2226
2226
 
@@ -2611,7 +2611,7 @@ def zoned_date_time_dtype(
2611
2611
  *, time_unit: TimeUnit = "us", time_zone: TimeZoneLike = UTC
2612
2612
  ) -> Datetime:
2613
2613
  """Create a zoned date-time data type."""
2614
- return Datetime(time_unit=time_unit, time_zone=get_time_zone_name(time_zone))
2614
+ return Datetime(time_unit=time_unit, time_zone=to_time_zone_name(time_zone))
2615
2615
 
2616
2616
 
2617
2617
  def zoned_date_time_period_dtype(