dycw-utilities 0.109.5__tar.gz → 0.109.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 (222) hide show
  1. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/PKG-INFO +1 -1
  2. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/pyproject.toml +2 -2
  3. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_math.py +15 -1
  4. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_parse.py +69 -17
  5. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/__init__.py +1 -1
  6. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/math.py +26 -1
  7. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/parse.py +35 -10
  8. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/whenever.py +3 -4
  9. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/.gitignore +0 -0
  10. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/LICENSE +0 -0
  11. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/README.md +0 -0
  12. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/__init__.py +0 -0
  13. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/conftest.py +0 -0
  14. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/__init__.py +0 -0
  15. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_missing/__init__.py +0 -0
  16. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_missing/module.py +0 -0
  17. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/__init__.py +0 -0
  18. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/outer_1.py +0 -0
  19. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/outer_2.py +0 -0
  20. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  21. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  22. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  23. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  24. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_without/__init__.py +0 -0
  25. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_without/module_1.py +0 -0
  26. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/package_without/module_2.py +0 -0
  27. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/standalone.py +0 -0
  28. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/modules/with_imports.py +0 -0
  29. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  30. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  31. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  32. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  33. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  34. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  35. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  36. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  37. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/__init__.py +0 -0
  38. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/test_async_service/__init__.py +0 -0
  39. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/test_async_service/__main__.py +0 -0
  40. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/test_async_service/run.sh +0 -0
  41. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
  42. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
  43. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/scripts/test_queue_processor/run.sh +0 -0
  44. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_altair.py +0 -0
  45. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_astor.py +0 -0
  46. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_asyncio.py +0 -0
  47. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_atomicwrites.py +0 -0
  48. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_atools.py +0 -0
  49. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_cachetools.py +0 -0
  50. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_click.py +0 -0
  51. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_concurrent.py +0 -0
  52. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_contextlib.py +0 -0
  53. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_contextvars.py +0 -0
  54. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_cryptography.py +0 -0
  55. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_cvxpy.py +0 -0
  56. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_dataclasses.py +0 -0
  57. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_datetime.py +0 -0
  58. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_enum.py +0 -0
  59. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_errors.py +0 -0
  60. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_eventkit.py +0 -0
  61. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_fastapi.py +0 -0
  62. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_fpdf2.py +0 -0
  63. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_functions.py +0 -0
  64. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_functools.py +0 -0
  65. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_getpass.py +0 -0
  66. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_git.py +0 -0
  67. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_hashlib.py +0 -0
  68. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_http.py +0 -0
  69. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_hypothesis.py +0 -0
  70. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_ipython.py +0 -0
  71. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_iterables.py +0 -0
  72. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_jupyter.py +0 -0
  73. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_logging.py +0 -0
  74. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_loguru.py +0 -0
  75. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_luigi.py +0 -0
  76. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_memory_profiler.py +0 -0
  77. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_modules.py +0 -0
  78. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_more_itertools.py +0 -0
  79. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_numpy.py +0 -0
  80. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_operator.py +0 -0
  81. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_optuna.py +0 -0
  82. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_orjson.py +0 -0
  83. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_os.py +0 -0
  84. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pathlib.py +0 -0
  85. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_period.py +0 -0
  86. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pickle.py +0 -0
  87. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_platform.py +0 -0
  88. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_polars.py +0 -0
  89. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pqdm.py +0 -0
  90. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pydantic.py +0 -0
  91. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pyinstrument.py +0 -0
  92. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pyrsistent.py +0 -0
  93. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pytest.py +0 -0
  94. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_pytest_regressions.py +0 -0
  95. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_python_dotenv.py +0 -0
  96. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_random.py +0 -0
  97. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_re.py +0 -0
  98. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_redis.py +0 -0
  99. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_reprlib.py +0 -0
  100. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_rich.py +0 -0
  101. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_scipy.py +0 -0
  102. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_sentinel.py +0 -0
  103. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_shelve.py +0 -0
  104. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_slack_sdk.py +0 -0
  105. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_socket.py +0 -0
  106. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_sqlalchemy.py +0 -0
  107. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_sqlalchemy_polars.py +0 -0
  108. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_streamlit.py +0 -0
  109. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_sys.py +0 -0
  110. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_tempfile.py +0 -0
  111. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_tenacity.py +0 -0
  112. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_text.py +0 -0
  113. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_threading.py +0 -0
  114. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_timer.py +0 -0
  115. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback.py +0 -0
  116. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/__init__.py +0 -0
  117. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/chain.py +0 -0
  118. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  119. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  120. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  121. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/many.py +0 -0
  122. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/one.py +0 -0
  123. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/recursive.py +0 -0
  124. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  125. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  126. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/two.py +0 -0
  127. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_traceback_funcs/untraced.py +0 -0
  128. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_types.py +0 -0
  129. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_typing.py +0 -0
  130. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_typing_funcs/__init__.py +0 -0
  131. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_typing_funcs/no_future.py +0 -0
  132. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_typing_funcs/with_future.py +0 -0
  133. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_tzdata.py +0 -0
  134. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_tzlocal.py +0 -0
  135. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_uuid.py +0 -0
  136. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_version.py +0 -0
  137. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_warnings.py +0 -0
  138. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_whenever.py +0 -0
  139. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_zipfile.py +0 -0
  140. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/tests/test_zoneinfo.py +0 -0
  141. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/altair.py +0 -0
  142. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/astor.py +0 -0
  143. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/asyncio.py +0 -0
  144. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/atomicwrites.py +0 -0
  145. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/atools.py +0 -0
  146. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/cachetools.py +0 -0
  147. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/click.py +0 -0
  148. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/concurrent.py +0 -0
  149. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/contextlib.py +0 -0
  150. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/contextvars.py +0 -0
  151. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/cryptography.py +0 -0
  152. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/cvxpy.py +0 -0
  153. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/dataclasses.py +0 -0
  154. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/datetime.py +0 -0
  155. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/enum.py +0 -0
  156. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/errors.py +0 -0
  157. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/eventkit.py +0 -0
  158. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/fastapi.py +0 -0
  159. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/fpdf2.py +0 -0
  160. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/functions.py +0 -0
  161. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/functools.py +0 -0
  162. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/getpass.py +0 -0
  163. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/git.py +0 -0
  164. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/hashlib.py +0 -0
  165. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/http.py +0 -0
  166. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/hypothesis.py +0 -0
  167. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/ipython.py +0 -0
  168. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/iterables.py +0 -0
  169. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/jupyter.py +0 -0
  170. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/logging.py +0 -0
  171. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/loguru.py +0 -0
  172. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/luigi.py +0 -0
  173. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/memory_profiler.py +0 -0
  174. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/modules.py +0 -0
  175. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/more_itertools.py +0 -0
  176. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/numpy.py +0 -0
  177. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/operator.py +0 -0
  178. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/optuna.py +0 -0
  179. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/orjson.py +0 -0
  180. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/os.py +0 -0
  181. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pathlib.py +0 -0
  182. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/period.py +0 -0
  183. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pickle.py +0 -0
  184. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/platform.py +0 -0
  185. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/polars.py +0 -0
  186. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pqdm.py +0 -0
  187. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/py.typed +0 -0
  188. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pydantic.py +0 -0
  189. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pyinstrument.py +0 -0
  190. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pyrsistent.py +0 -0
  191. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pytest.py +0 -0
  192. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/pytest_regressions.py +0 -0
  193. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/python_dotenv.py +0 -0
  194. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/random.py +0 -0
  195. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/re.py +0 -0
  196. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/redis.py +0 -0
  197. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/reprlib.py +0 -0
  198. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/rich.py +0 -0
  199. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/scipy.py +0 -0
  200. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/sentinel.py +0 -0
  201. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/shelve.py +0 -0
  202. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/slack_sdk.py +0 -0
  203. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/socket.py +0 -0
  204. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/sqlalchemy.py +0 -0
  205. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/sqlalchemy_polars.py +0 -0
  206. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/streamlit.py +0 -0
  207. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/sys.py +0 -0
  208. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/tempfile.py +0 -0
  209. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/tenacity.py +0 -0
  210. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/text.py +0 -0
  211. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/threading.py +0 -0
  212. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/timer.py +0 -0
  213. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/traceback.py +0 -0
  214. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/types.py +0 -0
  215. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/typing.py +0 -0
  216. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/tzdata.py +0 -0
  217. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/tzlocal.py +0 -0
  218. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/uuid.py +0 -0
  219. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/version.py +0 -0
  220. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/warnings.py +0 -0
  221. {dycw_utilities-0.109.5 → dycw_utilities-0.109.6}/src/utilities/zipfile.py +0 -0
  222. {dycw_utilities-0.109.5 → dycw_utilities-0.109.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.109.5
3
+ Version: 0.109.6
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -89,7 +89,7 @@ dependencies = [
89
89
  name = "dycw-utilities"
90
90
  readme = "README.md"
91
91
  requires-python = ">= 3.12"
92
- version = "0.109.5"
92
+ version = "0.109.6"
93
93
 
94
94
  [project.optional-dependencies]
95
95
  test = [
@@ -332,7 +332,7 @@ zzz-test-zoneinfo = [
332
332
  # bump-my-version
333
333
  [tool.bumpversion]
334
334
  allow_dirty = true
335
- current_version = "0.109.5"
335
+ current_version = "0.109.6"
336
336
 
337
337
  [[tool.bumpversion.files]]
338
338
  filename = "src/utilities/__init__.py"
@@ -16,7 +16,7 @@ from hypothesis.strategies import (
16
16
  from numpy import iinfo, int8, int16, int32, int64, uint8, uint16, uint32, uint64
17
17
  from pytest import approx, raises
18
18
 
19
- from utilities.hypothesis import int32s, pairs
19
+ from utilities.hypothesis import int32s, numbers, pairs
20
20
  from utilities.math import (
21
21
  MAX_INT8,
22
22
  MAX_INT16,
@@ -36,6 +36,7 @@ from utilities.math import (
36
36
  MIN_UINT64,
37
37
  CheckIntegerError,
38
38
  NumberOfDecimalsError,
39
+ ParseNumberError,
39
40
  SafeRoundError,
40
41
  _EWMParameters,
41
42
  _EWMParametersAlphaError,
@@ -91,6 +92,7 @@ from utilities.math import (
91
92
  is_zero_or_non_micro_or_nan,
92
93
  number_of_decimals,
93
94
  order_of_magnitude,
95
+ parse_number,
94
96
  round_,
95
97
  round_float_imprecisions,
96
98
  round_to_float,
@@ -895,6 +897,18 @@ class TestOrderOfMagnitude:
895
897
  assert res_int == exp_int
896
898
 
897
899
 
900
+ class TestParseNumber:
901
+ @given(number=numbers())
902
+ def test_main(self, *, number: Number) -> None:
903
+ serialized = str(number)
904
+ result = parse_number(serialized)
905
+ assert result == number
906
+
907
+ def test_error(self) -> None:
908
+ with raises(ParseNumberError, match="Unable to parse number; got 'invalid'"):
909
+ _ = parse_number("invalid")
910
+
911
+
898
912
  class TestRound:
899
913
  @given(
900
914
  case=sampled_from([
@@ -19,7 +19,9 @@ from tests.test_typing_funcs.with_future import (
19
19
  )
20
20
  from utilities.functions import ensure_path
21
21
  from utilities.hypothesis import (
22
+ datetime_durations,
22
23
  local_datetimes,
24
+ numbers,
23
25
  paths,
24
26
  text_ascii,
25
27
  timedeltas_2w,
@@ -33,10 +35,12 @@ from utilities.parse import (
33
35
  parse_text,
34
36
  )
35
37
  from utilities.sentinel import Sentinel, sentinel
38
+ from utilities.types import Duration, Number
36
39
  from utilities.version import Version
37
40
  from utilities.whenever import (
38
41
  serialize_date,
39
42
  serialize_datetime,
43
+ serialize_duration,
40
44
  serialize_time,
41
45
  serialize_timedelta,
42
46
  )
@@ -61,6 +65,12 @@ class TestParseText:
61
65
  result = parse_text(dt.datetime, text)
62
66
  assert result == datetime
63
67
 
68
+ @given(duration=datetime_durations(two_way=True))
69
+ def test_duration(self, *, duration: Duration) -> None:
70
+ text = serialize_duration(duration)
71
+ result = parse_text(Duration, text)
72
+ assert result == duration
73
+
64
74
  @given(truth=sampled_from(TruthEnum))
65
75
  def test_enum(self, *, truth: TruthEnum) -> None:
66
76
  text = truth.name
@@ -95,17 +105,6 @@ class TestParseText:
95
105
  result = parse_text(TrueOrFalseFutureLit, truth)
96
106
  assert result == truth
97
107
 
98
- def test_nullable_int_none(self) -> None:
99
- text = str(None)
100
- result = parse_text(int | None, text)
101
- assert result is None
102
-
103
- @given(value=integers())
104
- def test_nullable_int_int(self, *, value: int) -> None:
105
- text = str(value)
106
- result = parse_text(int | None, text)
107
- assert result == value
108
-
109
108
  def test_none(self) -> None:
110
109
  text = str(None)
111
110
  result = parse_text(None, text)
@@ -116,6 +115,12 @@ class TestParseText:
116
115
  result = parse_text(NoneType, text)
117
116
  assert result is None
118
117
 
118
+ @given(number=numbers())
119
+ def test_number(self, *, number: Number) -> None:
120
+ text = str(number)
121
+ result = parse_text(Number, text)
122
+ assert result == number
123
+
119
124
  @given(path=paths())
120
125
  def test_path(self, *, path: Path) -> None:
121
126
  text = str(path)
@@ -129,6 +134,39 @@ class TestParseText:
129
134
  result = ensure_path(parse_text(Path, text))
130
135
  assert result == result.expanduser()
131
136
 
137
+ def test_nullable_number_none(self) -> None:
138
+ text = str(None)
139
+ result = parse_text(Number | None, text)
140
+ assert result is None
141
+
142
+ @given(number=numbers())
143
+ def test_nullable_number_number(self, *, number: Number) -> None:
144
+ text = str(number)
145
+ result = parse_text(Number | None, text)
146
+ assert result == number
147
+
148
+ def test_nullable_duration_none(self) -> None:
149
+ text = str(None)
150
+ result = parse_text(Duration | None, text)
151
+ assert result is None
152
+
153
+ @given(duration=datetime_durations(two_way=True))
154
+ def test_nullable_duration_duration(self, *, duration: Duration) -> None:
155
+ text = serialize_duration(duration)
156
+ result = parse_text(Duration | None, text)
157
+ assert result == duration
158
+
159
+ def test_nullable_int_none(self) -> None:
160
+ text = str(None)
161
+ result = parse_text(int | None, text)
162
+ assert result is None
163
+
164
+ @given(value=integers())
165
+ def test_nullable_int_int(self, *, value: int) -> None:
166
+ text = str(value)
167
+ result = parse_text(int | None, text)
168
+ assert result == value
169
+
132
170
  def test_sentinel(self) -> None:
133
171
  text = str(sentinel)
134
172
  result = parse_text(Sentinel, text)
@@ -188,6 +226,12 @@ class TestParseText:
188
226
  ):
189
227
  _ = parse_text(dt.datetime, "invalid")
190
228
 
229
+ def test_error_duration(self) -> None:
230
+ with raises(
231
+ _ParseTextParseError, match=r"Unable to parse Duration; got 'invalid'"
232
+ ):
233
+ _ = parse_text(Duration, "invalid")
234
+
191
235
  def test_error_enum(self) -> None:
192
236
  with raises(
193
237
  _ParseTextParseError,
@@ -264,6 +308,12 @@ class TestParseText:
264
308
  ):
265
309
  _ = parse_text(Iterable[None] | None, "invalid")
266
310
 
311
+ def test_error_number(self) -> None:
312
+ with raises(
313
+ _ParseTextParseError, match=r"Unable to parse Number; got 'invalid'"
314
+ ):
315
+ _ = parse_text(Number, "invalid")
316
+
267
317
  def test_error_sentinel(self) -> None:
268
318
  with raises(
269
319
  _ParseTextParseError,
@@ -306,15 +356,17 @@ class TestParseText:
306
356
  _ = parse_text(int | str, "invalid")
307
357
 
308
358
  def test_error_unknown_type(self) -> None:
309
- @dataclass(kw_only=True)
310
- class Example:
311
- pass
312
-
313
359
  with raises(
314
360
  _ParseTextParseError,
315
- match=r"Unable to parse <class 'tests\.test_parse\.TestParseText\.test_error_unknown_type\.<locals>\.Example'>; got 'invalid'",
361
+ match=r"Unable to parse <class 'tests\.test_typing_funcs\.with_future\.DataClassFutureInt'>; got 'invalid'",
362
+ ):
363
+ _ = parse_text(DataClassFutureInt, "invalid")
364
+
365
+ def test_error_unknown_union_type(self) -> None:
366
+ with raises(
367
+ _ParseTextParseError, match=r"Unable to parse <class '.*'>; got 'invalid'"
316
368
  ):
317
- _ = parse_text(Example, "invalid")
369
+ _ = parse_text(DataClassFutureInt | DataClassFutureInt, "invalid")
318
370
 
319
371
  def test_error_version(self) -> None:
320
372
  with raises(
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.109.5"
3
+ __version__ = "0.109.6"
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
+ from contextlib import suppress
4
5
  from dataclasses import dataclass
5
6
  from math import ceil, exp, floor, isclose, isfinite, isinf, isnan, log, log10, modf
6
7
  from re import Match, search
@@ -9,7 +10,8 @@ from typing import TYPE_CHECKING, Literal, assert_never, overload, override
9
10
  from utilities.errors import ImpossibleCaseError
10
11
 
11
12
  if TYPE_CHECKING:
12
- from utilities.types import RoundMode
13
+ from utilities.types import Number, RoundMode
14
+
13
15
 
14
16
  MIN_FLOAT32, MAX_FLOAT32 = -3.4028234663852886e38, 3.4028234663852886e38
15
17
  MIN_FLOAT64, MAX_FLOAT64 = -1.7976931348623157e308, 1.7976931348623157e308
@@ -681,6 +683,27 @@ def order_of_magnitude(x: float, /, *, round_: bool = False) -> float:
681
683
  ##
682
684
 
683
685
 
686
+ def parse_number(number: str, /) -> Number:
687
+ """Convert text into a number."""
688
+ with suppress(ValueError):
689
+ return int(number)
690
+ with suppress(ValueError):
691
+ return float(number)
692
+ raise ParseNumberError(number=number)
693
+
694
+
695
+ @dataclass(kw_only=True, slots=True)
696
+ class ParseNumberError(Exception):
697
+ number: str
698
+
699
+ @override
700
+ def __str__(self) -> str:
701
+ return f"Unable to parse number; got {self.number!r}"
702
+
703
+
704
+ ##
705
+
706
+
684
707
  def round_(
685
708
  x: float,
686
709
  /,
@@ -887,6 +910,7 @@ __all__ = [
887
910
  "MIN_UINT64",
888
911
  "CheckIntegerError",
889
912
  "EWMParametersError",
913
+ "ParseNumberError",
890
914
  "SafeRoundError",
891
915
  "check_integer",
892
916
  "ewm_parameters",
@@ -934,6 +958,7 @@ __all__ = [
934
958
  "is_zero_or_non_micro_or_nan",
935
959
  "number_of_decimals",
936
960
  "order_of_magnitude",
961
+ "parse_number",
937
962
  "round_",
938
963
  "round_float_imprecisions",
939
964
  "round_to_float",
@@ -13,10 +13,18 @@ from utilities.datetime import is_subclass_date_not_datetime
13
13
  from utilities.enum import ParseEnumError, parse_enum
14
14
  from utilities.functions import is_subclass_int_not_bool
15
15
  from utilities.iterables import OneEmptyError, OneNonUniqueError, one, one_str
16
+ from utilities.math import ParseNumberError, parse_number
16
17
  from utilities.re import ExtractGroupError, extract_group
17
18
  from utilities.sentinel import ParseSentinelError, Sentinel, parse_sentinel
18
19
  from utilities.text import ParseBoolError, ParseNoneError, parse_bool, parse_none
19
- from utilities.typing import get_args, is_literal_type, is_optional_type, is_tuple_type
20
+ from utilities.types import Duration, Number
21
+ from utilities.typing import (
22
+ get_args,
23
+ is_literal_type,
24
+ is_optional_type,
25
+ is_tuple_type,
26
+ is_union_type,
27
+ )
20
28
  from utilities.version import ParseVersionError, Version, parse_version
21
29
 
22
30
  if TYPE_CHECKING:
@@ -31,8 +39,8 @@ def parse_text(
31
39
  text: str,
32
40
  /,
33
41
  *,
34
- case_sensitive: bool = False,
35
42
  head: bool = False,
43
+ case_sensitive: bool = False,
36
44
  extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
37
45
  ) -> Any:
38
46
  """Parse text."""
@@ -49,13 +57,12 @@ def parse_text(
49
57
  with suppress(ParseNoneError):
50
58
  return parse_none(text)
51
59
  inner = one(arg for arg in get_args(obj) if arg is not NoneType)
52
- if isinstance(
53
- inner := one(arg for arg in get_args(obj) if arg is not NoneType), type
54
- ):
55
- try:
56
- return _parse_text_type(inner, text, case_sensitive=case_sensitive)
57
- except _ParseTextParseError:
58
- raise _ParseTextParseError(obj=obj, text=text) from None
60
+ try:
61
+ return parse_text(
62
+ inner, text, head=head, case_sensitive=case_sensitive, extra=extra
63
+ )
64
+ except _ParseTextParseError:
65
+ raise _ParseTextParseError(obj=obj, text=text) from None
59
66
  if is_tuple_type(obj):
60
67
  args = get_args(obj)
61
68
  try:
@@ -65,9 +72,11 @@ def parse_text(
65
72
  if len(args) != len(texts):
66
73
  raise _ParseTextParseError(obj=obj, text=text)
67
74
  return tuple(
68
- parse_text(arg, text, case_sensitive=case_sensitive, head=head)
75
+ parse_text(arg, text, head=head, case_sensitive=case_sensitive, extra=extra)
69
76
  for arg, text in zip(args, texts, strict=True)
70
77
  )
78
+ if is_union_type(obj):
79
+ return _parse_text_union_type(obj, text)
71
80
  raise _ParseTextParseError(obj=obj, text=text) from None
72
81
 
73
82
 
@@ -161,6 +170,22 @@ def _parse_text_type(
161
170
  raise _ParseTextParseError(obj=cls, text=text) from None
162
171
 
163
172
 
173
+ def _parse_text_union_type(obj: Any, text: str, /) -> Any:
174
+ if obj is Number:
175
+ try:
176
+ return parse_number(text)
177
+ except ParseNumberError:
178
+ raise _ParseTextParseError(obj=obj, text=text) from None
179
+ if obj is Duration:
180
+ from utilities.whenever import ParseDurationError, parse_duration
181
+
182
+ try:
183
+ return parse_duration(text)
184
+ except ParseDurationError:
185
+ raise _ParseTextParseError(obj=obj, text=text) from None
186
+ raise _ParseTextParseError(obj=obj, text=text) from None
187
+
188
+
164
189
  @dataclass
165
190
  class ParseTextError(Exception):
166
191
  obj: Any
@@ -17,6 +17,7 @@ from utilities.datetime import (
17
17
  parse_two_digit_year,
18
18
  timedelta_to_microseconds,
19
19
  )
20
+ from utilities.math import ParseNumberError, parse_number
20
21
  from utilities.re import (
21
22
  ExtractGroupError,
22
23
  ExtractGroupsError,
@@ -298,10 +299,8 @@ class ParseDateTimeError(Exception):
298
299
 
299
300
  def parse_duration(duration: str, /) -> Duration:
300
301
  """Parse a string into a Duration."""
301
- with suppress(ValueError):
302
- return int(duration)
303
- with suppress(ValueError):
304
- return float(duration)
302
+ with suppress(ParseNumberError):
303
+ return parse_number(duration)
305
304
  try:
306
305
  return parse_timedelta(duration)
307
306
  except ParseTimedeltaError: