dycw-utilities 0.110.6__tar.gz → 0.110.8__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 (228) hide show
  1. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/PKG-INFO +1 -1
  2. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/pyproject.toml +2 -2
  3. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_functions.py +55 -13
  4. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_typing.py +33 -1
  5. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/__init__.py +1 -1
  6. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/functions.py +39 -8
  7. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/parse.py +2 -2
  8. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/typing.py +46 -4
  9. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/.gitignore +0 -0
  10. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/LICENSE +0 -0
  11. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/README.md +0 -0
  12. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/__init__.py +0 -0
  13. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/conftest.py +0 -0
  14. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/__init__.py +0 -0
  15. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_missing/__init__.py +0 -0
  16. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_missing/module.py +0 -0
  17. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/__init__.py +0 -0
  18. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/outer_1.py +0 -0
  19. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/outer_2.py +0 -0
  20. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  21. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  22. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  23. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  24. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_without/__init__.py +0 -0
  25. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_without/module_1.py +0 -0
  26. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/package_without/module_2.py +0 -0
  27. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/standalone.py +0 -0
  28. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/modules/with_imports.py +0 -0
  29. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  30. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  31. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  32. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  33. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  34. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  35. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  36. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  37. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/__init__.py +0 -0
  38. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/test_async_service/__init__.py +0 -0
  39. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/test_async_service/__main__.py +0 -0
  40. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/test_async_service/run.sh +0 -0
  41. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
  42. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
  43. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/scripts/test_queue_processor/run.sh +0 -0
  44. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_altair.py +0 -0
  45. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_astor.py +0 -0
  46. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_asyncio.py +0 -0
  47. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_atomicwrites.py +0 -0
  48. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_atools.py +0 -0
  49. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_cachetools.py +0 -0
  50. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_click.py +0 -0
  51. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_concurrent.py +0 -0
  52. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_contextlib.py +0 -0
  53. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_contextvars.py +0 -0
  54. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_cryptography.py +0 -0
  55. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_cvxpy.py +0 -0
  56. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_dataclasses.py +0 -0
  57. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_datetime.py +0 -0
  58. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_enum.py +0 -0
  59. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_errors.py +0 -0
  60. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_eventkit.py +0 -0
  61. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_fastapi.py +0 -0
  62. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_fpdf2.py +0 -0
  63. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_functools.py +0 -0
  64. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_getpass.py +0 -0
  65. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_git.py +0 -0
  66. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_hashlib.py +0 -0
  67. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_http.py +0 -0
  68. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_hypothesis.py +0 -0
  69. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_ipython.py +0 -0
  70. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_iterables.py +0 -0
  71. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_jupyter.py +0 -0
  72. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_lightweight_charts.py +0 -0
  73. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_logging.py +0 -0
  74. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_loguru.py +0 -0
  75. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_luigi.py +0 -0
  76. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_math.py +0 -0
  77. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_memory_profiler.py +0 -0
  78. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_modules.py +0 -0
  79. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_more_itertools.py +0 -0
  80. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_numpy.py +0 -0
  81. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_operator.py +0 -0
  82. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_optuna.py +0 -0
  83. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_orjson.py +0 -0
  84. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_os.py +0 -0
  85. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_parse.py +0 -0
  86. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pathlib.py +0 -0
  87. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_period.py +0 -0
  88. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pickle.py +0 -0
  89. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_platform.py +0 -0
  90. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_polars.py +0 -0
  91. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_polars_ols.py +0 -0
  92. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pqdm.py +0 -0
  93. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pydantic.py +0 -0
  94. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pyinstrument.py +0 -0
  95. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pyrsistent.py +0 -0
  96. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pytest.py +0 -0
  97. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_pytest_regressions.py +0 -0
  98. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_python_dotenv.py +0 -0
  99. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_random.py +0 -0
  100. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_re.py +0 -0
  101. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_redis.py +0 -0
  102. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_reprlib.py +0 -0
  103. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_rich.py +0 -0
  104. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_scipy.py +0 -0
  105. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_sentinel.py +0 -0
  106. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_shelve.py +0 -0
  107. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_slack_sdk.py +0 -0
  108. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_socket.py +0 -0
  109. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_sqlalchemy.py +0 -0
  110. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_sqlalchemy_polars.py +0 -0
  111. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_statsmodel.py +0 -0
  112. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_streamlit.py +0 -0
  113. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_sys.py +0 -0
  114. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_tempfile.py +0 -0
  115. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_tenacity.py +0 -0
  116. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_text.py +0 -0
  117. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_threading.py +0 -0
  118. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_timer.py +0 -0
  119. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback.py +0 -0
  120. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/__init__.py +0 -0
  121. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/chain.py +0 -0
  122. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  123. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  124. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  125. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/many.py +0 -0
  126. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/one.py +0 -0
  127. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/recursive.py +0 -0
  128. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  129. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  130. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/two.py +0 -0
  131. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_traceback_funcs/untraced.py +0 -0
  132. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_types.py +0 -0
  133. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_typing_funcs/__init__.py +0 -0
  134. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_typing_funcs/no_future.py +0 -0
  135. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_typing_funcs/with_future.py +0 -0
  136. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_tzdata.py +0 -0
  137. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_tzlocal.py +0 -0
  138. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_uuid.py +0 -0
  139. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_version.py +0 -0
  140. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_warnings.py +0 -0
  141. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_whenever.py +0 -0
  142. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_zipfile.py +0 -0
  143. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/tests/test_zoneinfo.py +0 -0
  144. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/altair.py +0 -0
  145. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/astor.py +0 -0
  146. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/asyncio.py +0 -0
  147. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/atomicwrites.py +0 -0
  148. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/atools.py +0 -0
  149. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/cachetools.py +0 -0
  150. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/click.py +0 -0
  151. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/concurrent.py +0 -0
  152. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/contextlib.py +0 -0
  153. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/contextvars.py +0 -0
  154. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/cryptography.py +0 -0
  155. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/cvxpy.py +0 -0
  156. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/dataclasses.py +0 -0
  157. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/datetime.py +0 -0
  158. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/enum.py +0 -0
  159. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/errors.py +0 -0
  160. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/eventkit.py +0 -0
  161. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/fastapi.py +0 -0
  162. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/fpdf2.py +0 -0
  163. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/functools.py +0 -0
  164. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/getpass.py +0 -0
  165. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/git.py +0 -0
  166. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/hashlib.py +0 -0
  167. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/http.py +0 -0
  168. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/hypothesis.py +0 -0
  169. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/ipython.py +0 -0
  170. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/iterables.py +0 -0
  171. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/jupyter.py +0 -0
  172. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/lightweight_charts.py +0 -0
  173. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/logging.py +0 -0
  174. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/loguru.py +0 -0
  175. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/luigi.py +0 -0
  176. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/math.py +0 -0
  177. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/memory_profiler.py +0 -0
  178. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/modules.py +0 -0
  179. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/more_itertools.py +0 -0
  180. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/numpy.py +0 -0
  181. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/operator.py +0 -0
  182. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/optuna.py +0 -0
  183. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/orjson.py +0 -0
  184. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/os.py +0 -0
  185. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pathlib.py +0 -0
  186. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/period.py +0 -0
  187. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pickle.py +0 -0
  188. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/platform.py +0 -0
  189. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/polars.py +0 -0
  190. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/polars_ols.py +0 -0
  191. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pqdm.py +0 -0
  192. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/py.typed +0 -0
  193. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pydantic.py +0 -0
  194. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pyinstrument.py +0 -0
  195. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pyrsistent.py +0 -0
  196. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pytest.py +0 -0
  197. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/pytest_regressions.py +0 -0
  198. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/python_dotenv.py +0 -0
  199. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/random.py +0 -0
  200. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/re.py +0 -0
  201. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/redis.py +0 -0
  202. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/reprlib.py +0 -0
  203. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/rich.py +0 -0
  204. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/scipy.py +0 -0
  205. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/sentinel.py +0 -0
  206. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/shelve.py +0 -0
  207. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/slack_sdk.py +0 -0
  208. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/socket.py +0 -0
  209. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/sqlalchemy.py +0 -0
  210. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/sqlalchemy_polars.py +0 -0
  211. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/statsmodels.py +0 -0
  212. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/streamlit.py +0 -0
  213. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/sys.py +0 -0
  214. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/tempfile.py +0 -0
  215. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/tenacity.py +0 -0
  216. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/text.py +0 -0
  217. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/threading.py +0 -0
  218. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/timer.py +0 -0
  219. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/traceback.py +0 -0
  220. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/types.py +0 -0
  221. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/tzdata.py +0 -0
  222. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/tzlocal.py +0 -0
  223. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/uuid.py +0 -0
  224. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/version.py +0 -0
  225. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/warnings.py +0 -0
  226. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/whenever.py +0 -0
  227. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/zipfile.py +0 -0
  228. {dycw_utilities-0.110.6 → dycw_utilities-0.110.8}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.110.6
3
+ Version: 0.110.8
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.110.6"
97
+ version = "0.110.8"
98
98
 
99
99
  [project.optional-dependencies]
100
100
  test = [
@@ -337,7 +337,7 @@ zzz-test-zoneinfo = [
337
337
  # bump-my-version
338
338
  [tool.bumpversion]
339
339
  allow_dirty = true
340
- current_version = "0.110.6"
340
+ current_version = "0.110.8"
341
341
 
342
342
  [[tool.bumpversion.files]]
343
343
  filename = "src/utilities/__init__.py"
@@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, ParamSpec, TypeVar, cast
12
12
  from hypothesis import given
13
13
  from hypothesis.strategies import (
14
14
  DataObject,
15
+ SearchStrategy,
15
16
  booleans,
16
17
  builds,
17
18
  data,
@@ -73,7 +74,7 @@ from utilities.functions import (
73
74
  is_dataclass_class,
74
75
  is_dataclass_instance,
75
76
  is_hashable,
76
- is_instance_int_not_bool,
77
+ is_instance_not_bool_int,
77
78
  is_iterable_of,
78
79
  is_none,
79
80
  is_not_none,
@@ -82,7 +83,7 @@ from utilities.functions import (
82
83
  is_sized,
83
84
  is_sized_not_str,
84
85
  is_string_mapping,
85
- is_subclass_int_not_bool,
86
+ is_subclass_not_bool_int,
86
87
  is_tuple,
87
88
  is_tuple_or_str_mapping,
88
89
  make_isinstance,
@@ -621,14 +622,37 @@ class TestIsHashable:
621
622
  assert is_hashable(obj) is expected
622
623
 
623
624
 
624
- class TestIsInstanceIntNotBool:
625
- @given(int_=integers())
626
- def test_int(self, *, int_: int) -> None:
627
- assert is_instance_int_not_bool(int_)
625
+ class TestIsInstanceNotIntBool:
626
+ @given(
627
+ data=data(),
628
+ case=sampled_from([
629
+ (booleans(), bool, True),
630
+ (booleans(), int, False),
631
+ (integers(), bool, False),
632
+ (integers(), int, True),
633
+ (booleans(), (bool, int), True),
634
+ (integers(), (bool, int), True),
635
+ ]),
636
+ )
637
+ def test_main(
638
+ self, *, data: DataObject, case: tuple[SearchStrategy[Any], type[Any], bool]
639
+ ) -> None:
640
+ strategy, type_, expected = case
641
+ value = data.draw(strategy)
642
+ assert is_instance_not_bool_int(value, type_) is expected
628
643
 
629
644
  @given(bool_=booleans())
630
- def test_bool(self, *, bool_: bool) -> None:
631
- assert not is_instance_int_not_bool(bool_)
645
+ def test_bool_value_vs_custom_int(self, *, bool_: bool) -> None:
646
+ class MyInt(int): ...
647
+
648
+ assert not is_instance_not_bool_int(bool_, MyInt)
649
+
650
+ @given(int_=integers())
651
+ def test_int_value_vs_custom_int(self, *, int_: int) -> None:
652
+ class MyInt(int): ...
653
+
654
+ assert not is_instance_not_bool_int(int_, MyInt)
655
+ assert is_instance_not_bool_int(MyInt(int_), MyInt)
632
656
 
633
657
 
634
658
  class TestIsIterableOf:
@@ -751,11 +775,29 @@ class TestIsStringMapping:
751
775
  assert result is expected
752
776
 
753
777
 
754
- class TestIsSubclassIntNotBool:
755
- @given(case=sampled_from([(int, True), (bool, False)]))
756
- def test_main(self, *, case: tuple[type[Any], bool]) -> None:
757
- type_, expected = case
758
- assert is_subclass_int_not_bool(type_) is expected
778
+ class TestIsSubclassNotBoolInt:
779
+ @given(
780
+ case=sampled_from([
781
+ (bool, bool, True),
782
+ (bool, int, False),
783
+ (int, bool, False),
784
+ (int, int, True),
785
+ (bool, (bool, int), True),
786
+ (int, (bool, int), True),
787
+ ])
788
+ )
789
+ def test_main(self, *, case: tuple[type[Any], type[Any], bool]) -> None:
790
+ child, parent, expected = case
791
+ assert is_subclass_not_bool_int(child, parent) is expected
792
+
793
+ def test_custom_int(self) -> None:
794
+ class MyInt(int): ...
795
+
796
+ assert not is_subclass_not_bool_int(bool, MyInt)
797
+ assert not is_subclass_not_bool_int(MyInt, bool)
798
+ assert not is_subclass_not_bool_int(int, MyInt)
799
+ assert is_subclass_not_bool_int(MyInt, int)
800
+ assert is_subclass_not_bool_int(MyInt, MyInt)
759
801
 
760
802
 
761
803
  class TestIsTuple:
@@ -4,6 +4,7 @@ import datetime as dt
4
4
  from collections.abc import Mapping, Sequence
5
5
  from dataclasses import dataclass
6
6
  from pathlib import Path
7
+ from random import Random
7
8
  from types import NoneType
8
9
  from typing import TYPE_CHECKING, Any, Literal, NamedTuple, Self
9
10
  from uuid import UUID
@@ -39,12 +40,15 @@ from tests.test_typing_funcs.with_future import (
39
40
  TrueOrFalseFutureTypeLit,
40
41
  )
41
42
  from utilities.sentinel import Sentinel
42
- from utilities.types import LogLevel, Parallelism
43
+ from utilities.types import Duration, LogLevel, Number, Parallelism, Seed
43
44
  from utilities.typing import (
45
+ _GetUnionTypeClassesNotATypeError,
46
+ _GetUnionTypeClassesNotAUnionTypeError,
44
47
  contains_self,
45
48
  get_args,
46
49
  get_literal_elements,
47
50
  get_type_hints,
51
+ get_union_type_classes,
48
52
  is_dict_type,
49
53
  is_frozenset_type,
50
54
  is_list_type,
@@ -335,6 +339,34 @@ class TestGetTypeHints:
335
339
  _ = get_type_hints(Outer, warn_name_errors=True)
336
340
 
337
341
 
342
+ class TestGetUnionTypeClasses:
343
+ @given(
344
+ case=sampled_from([
345
+ (Duration, (int, float, dt.timedelta)),
346
+ (Number, (int, float)),
347
+ (Seed, (int, float, str, bytes, bytearray, Random)),
348
+ ])
349
+ )
350
+ def test_main(self, *, case: tuple[Any, tuple[type[Any], ...]]) -> None:
351
+ obj, expected = case
352
+ result = get_union_type_classes(obj)
353
+ assert result == expected
354
+
355
+ def test_error_not_a_union_type(self) -> None:
356
+ with raises(
357
+ _GetUnionTypeClassesNotAUnionTypeError,
358
+ match="Object must be a Union type; got None",
359
+ ):
360
+ _ = get_union_type_classes(None)
361
+
362
+ def test_error_not_a_type(self) -> None:
363
+ with raises(
364
+ _GetUnionTypeClassesNotATypeError,
365
+ match=r"Union type must contain types only; got typing\.Literal\[True\]",
366
+ ):
367
+ _ = get_union_type_classes(Literal[True] | None)
368
+
369
+
338
370
  class TestIsAnnotationOfType:
339
371
  @mark.parametrize(
340
372
  ("func", "obj", "expected"),
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.110.6"
3
+ __version__ = "0.110.8"
@@ -22,6 +22,7 @@ from typing import (
22
22
  Literal,
23
23
  TypeGuard,
24
24
  TypeVar,
25
+ assert_never,
25
26
  cast,
26
27
  overload,
27
28
  override,
@@ -182,6 +183,8 @@ def ensure_class(
182
183
  *,
183
184
  nullable: Literal[False] = False,
184
185
  ) -> _T1 | _T2 | _T3 | _T4 | _T5: ...
186
+ @overload
187
+ def ensure_class(obj: Any, cls: TypeLike[_T], /, *, nullable: bool = False) -> Any: ...
185
188
  def ensure_class(obj: Any, cls: TypeLike[_T], /, *, nullable: bool = False) -> Any:
186
189
  """Ensure an object is of the required class."""
187
190
  if isinstance(obj, cls) or ((obj is None) and nullable):
@@ -657,9 +660,23 @@ def is_hashable(obj: Any, /) -> TypeGuard[Hashable]:
657
660
  ##
658
661
 
659
662
 
660
- def is_instance_int_not_bool(obj: Any, /) -> TypeGuard[int]:
661
- """Check if an object is an integer, and not a boolean."""
662
- return isinstance(obj, int) and not isinstance(obj, bool)
663
+ def is_instance_not_bool_int(
664
+ obj: Any, class_or_tuple: TypeLike[Any], /
665
+ ) -> TypeGuard[int]:
666
+ """Check if an instance relationship holds, except bool<int."""
667
+ match class_or_tuple:
668
+ case type() as type_:
669
+ return _is_instance_not_bool_int(obj, type_)
670
+ case tuple() as types:
671
+ return any(_is_instance_not_bool_int(obj, p) for p in types)
672
+ case _ as never:
673
+ assert_never(never)
674
+
675
+
676
+ def _is_instance_not_bool_int(obj: Any, type_: type[Any], /) -> bool:
677
+ return isinstance(obj, type_) and not (
678
+ isinstance(obj, bool) and issubclass(type_, int) and not issubclass(type_, bool)
679
+ )
663
680
 
664
681
 
665
682
  ##
@@ -779,9 +796,23 @@ def is_string_mapping(obj: Any, /) -> TypeGuard[StrMapping]:
779
796
  ##
780
797
 
781
798
 
782
- def is_subclass_int_not_bool(cls: type[Any], /) -> TypeGuard[type[int]]:
783
- """Check if a class is an integer, and not a boolean."""
784
- return issubclass(cls, int) and not issubclass(cls, bool)
799
+ def is_subclass_not_bool_int(cls: type[Any], class_or_tuple: TypeLike[Any], /) -> bool:
800
+ """Check if a subclass relationship holds, except bool<int."""
801
+ match class_or_tuple:
802
+ case type() as parent:
803
+ return _is_subclass_int_not_bool_one(cls, parent)
804
+ case tuple() as parents:
805
+ return any(_is_subclass_int_not_bool_one(cls, p) for p in parents)
806
+ case _ as never:
807
+ assert_never(never)
808
+
809
+
810
+ def _is_subclass_int_not_bool_one(cls: type[Any], parent: type[Any], /) -> bool:
811
+ return issubclass(cls, parent) and not (
812
+ issubclass(cls, bool)
813
+ and issubclass(parent, int)
814
+ and not issubclass(parent, bool)
815
+ )
785
816
 
786
817
 
787
818
  ##
@@ -1044,7 +1075,7 @@ __all__ = [
1044
1075
  "is_dataclass_class",
1045
1076
  "is_dataclass_instance",
1046
1077
  "is_hashable",
1047
- "is_instance_int_not_bool",
1078
+ "is_instance_not_bool_int",
1048
1079
  "is_iterable_of",
1049
1080
  "is_none",
1050
1081
  "is_not_none",
@@ -1052,7 +1083,7 @@ __all__ = [
1052
1083
  "is_sized",
1053
1084
  "is_sized_not_str",
1054
1085
  "is_string_mapping",
1055
- "is_subclass_int_not_bool",
1086
+ "is_subclass_not_bool_int",
1056
1087
  "is_tuple",
1057
1088
  "is_tuple_or_str_mapping",
1058
1089
  "make_isinstance",
@@ -14,7 +14,7 @@ from utilities.datetime import (
14
14
  is_subclass_date_not_datetime,
15
15
  )
16
16
  from utilities.enum import ParseEnumError, parse_enum
17
- from utilities.functions import is_subclass_int_not_bool
17
+ from utilities.functions import is_subclass_not_bool_int
18
18
  from utilities.iterables import OneEmptyError, OneNonUniqueError, one, one_str
19
19
  from utilities.math import ParseNumberError, parse_number
20
20
  from utilities.re import ExtractGroupError, extract_group
@@ -174,7 +174,7 @@ def _parse_object_type(
174
174
  return parse_bool(text)
175
175
  except ParseBoolError:
176
176
  raise _ParseObjectParseError(type_=cls, text=text) from None
177
- if is_subclass_int_not_bool(cls):
177
+ if is_subclass_not_bool_int(cls, int):
178
178
  try:
179
179
  return int(text)
180
180
  except ValueError:
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import datetime as dt
4
4
  from collections.abc import Mapping, Sequence
5
+ from dataclasses import dataclass
5
6
  from itertools import chain
6
7
  from pathlib import Path
7
8
  from types import NoneType, UnionType
@@ -15,6 +16,7 @@ from typing import (
15
16
  TypeGuard,
16
17
  Union, # pyright: ignore[reportDeprecated]
17
18
  get_origin,
19
+ override,
18
20
  )
19
21
  from typing import get_args as _get_args
20
22
  from typing import get_type_hints as _get_type_hints
@@ -64,7 +66,7 @@ def _get_literal_elements_inner(obj: Any, /) -> list[Any]:
64
66
 
65
67
 
66
68
  def get_type_hints(
67
- cls: Any,
69
+ obj: Any,
68
70
  /,
69
71
  *,
70
72
  globalns: StrMapping | None = None,
@@ -72,15 +74,15 @@ def get_type_hints(
72
74
  warn_name_errors: bool = False,
73
75
  ) -> dict[str, Any]:
74
76
  """Get the type hints of an object."""
75
- result: dict[str, Any] = cls.__annotations__
77
+ result: dict[str, Any] = obj.__annotations__
76
78
  _ = {Literal, Path, Sentinel, StrMapping, UUID, dt}
77
79
  globalns_use = globals() | ({} if globalns is None else dict(globalns))
78
80
  localns_use = {} if localns is None else dict(localns)
79
81
  try:
80
- hints = _get_type_hints(cls, globalns=globalns_use, localns=localns_use)
82
+ hints = _get_type_hints(obj, globalns=globalns_use, localns=localns_use)
81
83
  except NameError as error:
82
84
  if warn_name_errors:
83
- warn(f"Error getting type hints for {cls!r}; {error}", stacklevel=2)
85
+ warn(f"Error getting type hints for {obj!r}; {error}", stacklevel=2)
84
86
  else:
85
87
  result.update({
86
88
  key: value
@@ -93,6 +95,44 @@ def get_type_hints(
93
95
  ##
94
96
 
95
97
 
98
+ def get_union_type_classes(obj: Any, /) -> tuple[type[Any], ...]:
99
+ if not is_union_type(obj):
100
+ raise _GetUnionTypeClassesNotAUnionTypeError(obj=obj)
101
+ types_: Sequence[type[Any]] = []
102
+ for arg in get_args(obj):
103
+ if isinstance(arg, type):
104
+ types_.append(arg)
105
+ elif is_union_type(arg):
106
+ types_.extend(get_union_type_classes(arg))
107
+ else:
108
+ raise _GetUnionTypeClassesNotATypeError(obj=obj, inner=arg)
109
+ return tuple(types_)
110
+
111
+
112
+ @dataclass(kw_only=True, slots=True)
113
+ class GetUnionTypeClassesError(Exception):
114
+ obj: Any
115
+
116
+
117
+ @dataclass(kw_only=True, slots=True)
118
+ class _GetUnionTypeClassesNotAUnionTypeError(GetUnionTypeClassesError):
119
+ @override
120
+ def __str__(self) -> str:
121
+ return f"Object must be a Union type; got {self.obj}"
122
+
123
+
124
+ @dataclass(kw_only=True, slots=True)
125
+ class _GetUnionTypeClassesNotATypeError(GetUnionTypeClassesError):
126
+ inner: Any
127
+
128
+ @override
129
+ def __str__(self) -> str:
130
+ return f"Union type must contain types only; got {self.inner}"
131
+
132
+
133
+ ##
134
+
135
+
96
136
  def is_dict_type(obj: Any, /) -> bool:
97
137
  """Check if an object is a dict type annotation."""
98
138
  return _is_annotation_of_type(obj, dict)
@@ -207,9 +247,11 @@ def _is_annotation_of_type(obj: Any, origin: Any, /) -> bool:
207
247
 
208
248
 
209
249
  __all__ = [
250
+ "GetUnionTypeClassesError",
210
251
  "contains_self",
211
252
  "get_literal_elements",
212
253
  "get_type_hints",
254
+ "get_union_type_classes",
213
255
  "is_dict_type",
214
256
  "is_frozenset_type",
215
257
  "is_list_type",