dycw-utilities 0.165.0__tar.gz → 0.165.2__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.165.0 → dycw_utilities-0.165.2}/PKG-INFO +1 -1
  2. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/pyproject.toml +2 -2
  3. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_contextlib.py +19 -0
  4. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_typing.py +90 -11
  5. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_typing_funcs/no_future.py +11 -1
  6. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_typing_funcs/with_future.py +6 -1
  7. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/__init__.py +1 -1
  8. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/contextlib.py +3 -1
  9. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/typing.py +53 -10
  10. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/.gitignore +0 -0
  11. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/LICENSE +0 -0
  12. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/README.md +0 -0
  13. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/__init__.py +0 -0
  14. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/conftest.py +0 -0
  15. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/__init__.py +0 -0
  16. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_missing/__init__.py +0 -0
  17. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_missing/module.py +0 -0
  18. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/__init__.py +0 -0
  19. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/outer_1.py +0 -0
  20. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/outer_2.py +0 -0
  21. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  22. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  23. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  24. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  25. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_without/__init__.py +0 -0
  26. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_without/module_1.py +0 -0
  27. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/package_without/module_2.py +0 -0
  28. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/standalone.py +0 -0
  29. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/modules/with_imports.py +0 -0
  30. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  31. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  32. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  33. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  34. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  35. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  36. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  37. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  38. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_aeventkit.py +0 -0
  39. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_altair.py +0 -0
  40. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_asyncio.py +0 -0
  41. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_atomicwrites.py +0 -0
  42. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_atools.py +0 -0
  43. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_cachetools.py +0 -0
  44. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_click.py +0 -0
  45. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_concurrent.py +0 -0
  46. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_contextvars.py +0 -0
  47. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_cryptography.py +0 -0
  48. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_cvxpy.py +0 -0
  49. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_dataclasses.py +0 -0
  50. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_enum.py +0 -0
  51. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_errors.py +0 -0
  52. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_fastapi.py +0 -0
  53. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_fpdf2.py +0 -0
  54. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_functions.py +0 -0
  55. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_functools.py +0 -0
  56. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_getpass.py +0 -0
  57. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_gzip.py +0 -0
  58. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_hashlib.py +0 -0
  59. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_http.py +0 -0
  60. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_hypothesis.py +0 -0
  61. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_importlib.py +0 -0
  62. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_inflect.py +0 -0
  63. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_ipython.py +0 -0
  64. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_iterables.py +0 -0
  65. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_json.py +0 -0
  66. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_jupyter.py +0 -0
  67. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_libcst.py +0 -0
  68. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_lightweight_charts.py +0 -0
  69. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_logging.py +0 -0
  70. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_math.py +0 -0
  71. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_memory_profiler.py +0 -0
  72. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_modules.py +0 -0
  73. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_more_itertools.py +0 -0
  74. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_numpy.py +0 -0
  75. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_objects/__init__.py +0 -0
  76. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_objects/objects.py +0 -0
  77. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_operator.py +0 -0
  78. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_optuna.py +0 -0
  79. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_orjson.py +0 -0
  80. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_os.py +0 -0
  81. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_parse.py +0 -0
  82. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pathlib.py +0 -0
  83. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pickle.py +0 -0
  84. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_platform.py +0 -0
  85. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_polars.py +0 -0
  86. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_polars_ols.py +0 -0
  87. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_postgres.py +0 -0
  88. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pottery.py +0 -0
  89. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pqdm.py +0 -0
  90. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_psutil.py +0 -0
  91. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pyinstrument.py +0 -0
  92. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pytest.py +0 -0
  93. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pytest_randomly.py +0 -0
  94. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_pytest_regressions.py +0 -0
  95. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_random.py +0 -0
  96. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_re.py +0 -0
  97. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_redis.py +0 -0
  98. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_reprlib.py +0 -0
  99. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_scipy.py +0 -0
  100. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_sentinel.py +0 -0
  101. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_shelve.py +0 -0
  102. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_slack_sdk.py +0 -0
  103. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_socket.py +0 -0
  104. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_sqlalchemy.py +0 -0
  105. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_sqlalchemy_polars.py +0 -0
  106. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_statsmodels.py +0 -0
  107. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_string.py +0 -0
  108. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_tempfile.py +0 -0
  109. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_testbook.py +0 -0
  110. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_text.py +0 -0
  111. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_threading.py +0 -0
  112. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_timer.py +0 -0
  113. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_traceback.py +0 -0
  114. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_typed_settings.py +0 -0
  115. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_types.py +0 -0
  116. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_typing_funcs/__init__.py +0 -0
  117. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_tzdata.py +0 -0
  118. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_tzlocal.py +0 -0
  119. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_uuid.py +0 -0
  120. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_version.py +0 -0
  121. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_warnings.py +0 -0
  122. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_whenever.py +0 -0
  123. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_zipfile.py +0 -0
  124. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/tests/test_zoneinfo.py +0 -0
  125. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/aeventkit.py +0 -0
  126. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/altair.py +0 -0
  127. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/asyncio.py +0 -0
  128. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/atomicwrites.py +0 -0
  129. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/atools.py +0 -0
  130. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/cachetools.py +0 -0
  131. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/click.py +0 -0
  132. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/concurrent.py +0 -0
  133. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/contextvars.py +0 -0
  134. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/cryptography.py +0 -0
  135. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/cvxpy.py +0 -0
  136. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/dataclasses.py +0 -0
  137. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/enum.py +0 -0
  138. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/errors.py +0 -0
  139. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/fastapi.py +0 -0
  140. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/fpdf2.py +0 -0
  141. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/functions.py +0 -0
  142. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/functools.py +0 -0
  143. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/getpass.py +0 -0
  144. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/gzip.py +0 -0
  145. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/hashlib.py +0 -0
  146. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/http.py +0 -0
  147. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/hypothesis.py +0 -0
  148. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/importlib.py +0 -0
  149. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/inflect.py +0 -0
  150. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/ipython.py +0 -0
  151. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/iterables.py +0 -0
  152. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/json.py +0 -0
  153. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/jupyter.py +0 -0
  154. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/libcst.py +0 -0
  155. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/lightweight_charts.py +0 -0
  156. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/logging.py +0 -0
  157. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/math.py +0 -0
  158. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/memory_profiler.py +0 -0
  159. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/modules.py +0 -0
  160. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/more_itertools.py +0 -0
  161. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/numpy.py +0 -0
  162. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/operator.py +0 -0
  163. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/optuna.py +0 -0
  164. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/orjson.py +0 -0
  165. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/os.py +0 -0
  166. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/parse.py +0 -0
  167. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pathlib.py +0 -0
  168. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pickle.py +0 -0
  169. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/platform.py +0 -0
  170. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/polars.py +0 -0
  171. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/polars_ols.py +0 -0
  172. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/postgres.py +0 -0
  173. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pottery.py +0 -0
  174. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pqdm.py +0 -0
  175. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/psutil.py +0 -0
  176. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/py.typed +0 -0
  177. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pyinstrument.py +0 -0
  178. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pytest.py +0 -0
  179. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pytest_plugins/__init__.py +0 -0
  180. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pytest_plugins/pytest_randomly.py +0 -0
  181. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pytest_plugins/pytest_regressions.py +0 -0
  182. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/pytest_regressions.py +0 -0
  183. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/random.py +0 -0
  184. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/re.py +0 -0
  185. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/redis.py +0 -0
  186. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/reprlib.py +0 -0
  187. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/scipy.py +0 -0
  188. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/sentinel.py +0 -0
  189. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/shelve.py +0 -0
  190. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/slack_sdk.py +0 -0
  191. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/socket.py +0 -0
  192. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/sqlalchemy.py +0 -0
  193. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/sqlalchemy_polars.py +0 -0
  194. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/statsmodels.py +0 -0
  195. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/string.py +0 -0
  196. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/tempfile.py +0 -0
  197. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/testbook.py +0 -0
  198. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/text.py +0 -0
  199. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/threading.py +0 -0
  200. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/timer.py +0 -0
  201. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/traceback.py +0 -0
  202. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/typed_settings.py +0 -0
  203. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/types.py +0 -0
  204. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/tzdata.py +0 -0
  205. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/tzlocal.py +0 -0
  206. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/uuid.py +0 -0
  207. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/version.py +0 -0
  208. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/warnings.py +0 -0
  209. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/whenever.py +0 -0
  210. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/zipfile.py +0 -0
  211. {dycw_utilities-0.165.0 → dycw_utilities-0.165.2}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.165.0
3
+ Version: 0.165.2
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -233,7 +233,7 @@ dependencies = [
233
233
  name = "dycw-utilities"
234
234
  readme = "README.md"
235
235
  requires-python = ">= 3.12"
236
- version = "0.165.0"
236
+ version = "0.165.2"
237
237
 
238
238
  [project.entry-points.pytest11]
239
239
  pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
@@ -266,7 +266,7 @@ test = [
266
266
  # bump-my-version
267
267
  [tool.bumpversion]
268
268
  allow_dirty = true
269
- current_version = "0.165.0"
269
+ current_version = "0.165.2"
270
270
 
271
271
  [[tool.bumpversion.files]]
272
272
  filename = "src/utilities/__init__.py"
@@ -4,6 +4,7 @@ import asyncio
4
4
  import time
5
5
  from asyncio import run
6
6
  from dataclasses import dataclass
7
+ from inspect import signature
7
8
  from multiprocessing import Process
8
9
  from pathlib import Path
9
10
  from typing import TYPE_CHECKING, override
@@ -103,6 +104,15 @@ class TestEnhancedContextManager:
103
104
  assert not cleared
104
105
  assert cleared
105
106
 
107
+ def test_sync_signature(self) -> None:
108
+ @enhanced_context_manager
109
+ def yield_marker(x: int, y: int, /) -> Iterator[int]:
110
+ yield x + y
111
+
112
+ sig = set(signature(yield_marker).parameters)
113
+ expected = {"x", "y"}
114
+ assert sig == expected
115
+
106
116
  @given(
107
117
  sigabrt=booleans(),
108
118
  sigfpe=booleans(),
@@ -142,6 +152,15 @@ class TestEnhancedContextManager:
142
152
  assert not cleared
143
153
  assert cleared
144
154
 
155
+ def test_async_signature(self) -> None:
156
+ @enhanced_async_context_manager
157
+ async def yield_marker(x: int, y: int, /) -> AsyncIterator[int]:
158
+ yield x + y
159
+
160
+ sig = set(signature(yield_marker).parameters)
161
+ expected = {"x", "y"}
162
+ assert sig == expected
163
+
145
164
  @mark.parametrize(
146
165
  "target",
147
166
  [
@@ -10,9 +10,11 @@ from typing import (
10
10
  TYPE_CHECKING,
11
11
  Any,
12
12
  Final,
13
+ ForwardRef,
13
14
  Literal,
14
15
  NamedTuple,
15
- TypedDict,
16
+ NotRequired,
17
+ _TypedDictMeta, # pyright: ignore[reportAttributeAccessIssue]
16
18
  assert_never,
17
19
  )
18
20
  from uuid import UUID
@@ -50,6 +52,8 @@ from tests.test_typing_funcs.no_future import (
50
52
  DataClassNoFutureNestedInnerFirstOuter,
51
53
  DataClassNoFutureNestedOuterFirstInner,
52
54
  DataClassNoFutureNestedOuterFirstOuter,
55
+ TypedDictNoFutureIntFloat,
56
+ TypedDictNoFutureIntFloatOptional,
53
57
  )
54
58
  from tests.test_typing_funcs.with_future import (
55
59
  DataClassFutureDate,
@@ -80,10 +84,11 @@ from tests.test_typing_funcs.with_future import (
80
84
  TrueOrFalseFutureLit,
81
85
  TrueOrFalseFutureTypeLit,
82
86
  TypedDictFutureIntFloat,
87
+ TypedDictFutureIntFloatOptional,
83
88
  )
84
89
  from utilities.hypothesis import text_ascii
85
90
  from utilities.sentinel import Sentinel
86
- from utilities.types import LogLevel, Number, Parallelism, Seed
91
+ from utilities.types import LogLevel, Number, Parallelism, Seed, StrMapping
87
92
  from utilities.typing import (
88
93
  IsInstanceGenError,
89
94
  IsSubclassGenError,
@@ -92,6 +97,7 @@ from utilities.typing import (
92
97
  _GetUnionTypeClassesInternalTypeError,
93
98
  _GetUnionTypeClassesUnionTypeError,
94
99
  get_args,
100
+ get_forward_ref_args,
95
101
  get_literal_elements,
96
102
  get_type_classes,
97
103
  get_type_hints,
@@ -107,6 +113,8 @@ from utilities.typing import (
107
113
  is_mapping_type,
108
114
  is_namedtuple_class,
109
115
  is_namedtuple_instance,
116
+ is_not_required_annotation,
117
+ is_not_required_type,
110
118
  is_optional_type,
111
119
  is_sequence_of,
112
120
  is_sequence_of_tuple_or_str_mapping,
@@ -158,6 +166,13 @@ class TestGetArgs:
158
166
  assert result == expected
159
167
 
160
168
 
169
+ class TestGetForwardRefArgs:
170
+ def test_main(self) -> None:
171
+ args = get_forward_ref_args(TypedDictFutureIntFloat)
172
+ expected = {"int_": "int", "float_": "float"}
173
+ assert args == expected
174
+
175
+
161
176
  type _PlusOrMinusOneLit = Literal[1, -1]
162
177
  type _TruthLit = Literal["true", "false"]
163
178
  type _True = Literal["true"]
@@ -495,13 +510,23 @@ class TestGetTypeHints:
495
510
  expected = {"truth": TrueOrFalseFutureTypeLit}
496
511
  assert hints == expected
497
512
 
498
- def test_typed_dict(self) -> None:
499
- class Example(TypedDict):
500
- int_: int
501
- float_: float
502
-
503
- hints = get_type_hints(Example)
504
- expected = {"int_": int, "float_": float}
513
+ @mark.parametrize(
514
+ ("obj", "expected"),
515
+ [
516
+ param(TypedDictNoFutureIntFloat, {"int_": int, "float_": float}),
517
+ param(TypedDictFutureIntFloat, {"int_": int, "float_": float}),
518
+ param(
519
+ TypedDictNoFutureIntFloatOptional,
520
+ {"int_": int, "float_": NotRequired[float]},
521
+ ),
522
+ param(
523
+ TypedDictFutureIntFloatOptional,
524
+ {"int_": int, "float_": NotRequired[float]},
525
+ ),
526
+ ],
527
+ )
528
+ def test_typed_dict(self, *, obj: _TypedDictMeta, expected: StrMapping) -> None:
529
+ hints = get_type_hints(obj)
505
530
  assert hints == expected
506
531
 
507
532
  @given(data=data())
@@ -637,6 +662,8 @@ class TestIsAnnotationOfType:
637
662
  param(is_mapping_type, list[int], False),
638
663
  param(is_mapping_type, set[int], False),
639
664
  param(is_mapping_type, tuple[int, int], False),
665
+ param(is_not_required_type, NotRequired, True),
666
+ param(is_not_required_type, NotRequired[int], True),
640
667
  param(is_optional_type, Literal["a", "b", "c"] | None, True),
641
668
  param(is_optional_type, Literal["a", "b", "c"], False),
642
669
  param(is_optional_type, int | None, True),
@@ -824,8 +851,39 @@ class TestIsInstanceGen:
824
851
  param({"int_": 0, "float_": 0.0, "extra": None}, True),
825
852
  ],
826
853
  )
827
- def test_typed_dict(self, *, obj: Any, expected: bool) -> None:
828
- result = is_instance_gen(obj, TypedDictFutureIntFloat)
854
+ @mark.parametrize(
855
+ "cls", [param(TypedDictNoFutureIntFloat), param(TypedDictFutureIntFloat)]
856
+ )
857
+ def test_typed_dict(self, *, obj: Any, cls: _TypedDictMeta, expected: bool) -> None:
858
+ result = is_instance_gen(obj, cls)
859
+ assert result is expected
860
+
861
+ @mark.parametrize(
862
+ ("obj", "expected"),
863
+ [
864
+ param(None, False),
865
+ param({}, False),
866
+ param({None: False}, False),
867
+ param({"int_": None}, False),
868
+ param({"int_": 0}, True),
869
+ param({"int_": None, "float_": None}, False),
870
+ param({"int_": 0, "float_": None}, True),
871
+ param({"int_": None, "float_": 0.0}, False),
872
+ param({"int_": 0, "float_": 0.0}, True),
873
+ param({"int_": 0, "float_": 0.0, "extra": None}, True),
874
+ ],
875
+ )
876
+ @mark.parametrize(
877
+ "cls",
878
+ [
879
+ param(TypedDictNoFutureIntFloatOptional),
880
+ param(TypedDictFutureIntFloatOptional),
881
+ ],
882
+ )
883
+ def test_typed_dict_optional(
884
+ self, *, obj: Any, cls: _TypedDictMeta, expected: bool
885
+ ) -> None:
886
+ result = is_instance_gen(obj, cls)
829
887
  assert result is expected
830
888
 
831
889
  def test_error(self) -> None:
@@ -884,6 +942,27 @@ class TestIsNamedTuple:
884
942
  assert not is_namedtuple_instance(Example(x=0))
885
943
 
886
944
 
945
+ class TestIsNotRequiredAnnotation:
946
+ @mark.parametrize(
947
+ ("obj", "expected"),
948
+ [
949
+ param(NotRequired, True),
950
+ param(NotRequired[int], True),
951
+ param(int, False),
952
+ param("NotRequired", True),
953
+ param("NotRequired[int]", True),
954
+ param("int", False),
955
+ param(ForwardRef("NotRequired"), True),
956
+ param(ForwardRef("NotRequired[int]"), True),
957
+ param(ForwardRef("int"), False),
958
+ param(None, False),
959
+ ],
960
+ )
961
+ def test_main(self, *, obj: Any, expected: bool) -> None:
962
+ result = is_not_required_annotation(obj)
963
+ assert result is expected
964
+
965
+
887
966
  class TestIsSequenceOf:
888
967
  @mark.parametrize(
889
968
  ("obj", "expected"),
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import Literal
2
+ from typing import Literal, NotRequired, TypedDict
3
3
 
4
4
  TrueOrFalseNoFutureLit = Literal["true", "false"]
5
5
  type TrueOrFalseNoFutureTypeLit = Literal["true", "false"]
@@ -33,3 +33,13 @@ class DataClassNoFutureNestedOuterFirstOuter:
33
33
  @dataclass(kw_only=True)
34
34
  class DataClassNoFutureNestedOuterFirstInner:
35
35
  int_: int
36
+
37
+
38
+ class TypedDictNoFutureIntFloat(TypedDict):
39
+ int_: int
40
+ float_: float
41
+
42
+
43
+ class TypedDictNoFutureIntFloatOptional(TypedDict):
44
+ int_: int
45
+ float_: NotRequired[float]
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING, Literal, TypedDict, override
4
+ from typing import TYPE_CHECKING, Literal, NotRequired, TypedDict, override
5
5
 
6
6
  if TYPE_CHECKING:
7
7
  from pathlib import Path
@@ -239,3 +239,8 @@ class DataClassFutureZonedDateTimePeriod:
239
239
  class TypedDictFutureIntFloat(TypedDict):
240
240
  int_: int
241
241
  float_: float
242
+
243
+
244
+ class TypedDictFutureIntFloatOptional(TypedDict):
245
+ int_: int
246
+ float_: NotRequired[float]
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.165.0"
3
+ __version__ = "0.165.2"
@@ -8,7 +8,7 @@ from contextlib import (
8
8
  asynccontextmanager,
9
9
  contextmanager,
10
10
  )
11
- from functools import partial
11
+ from functools import partial, wraps
12
12
  from signal import SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, getsignal, signal
13
13
  from typing import TYPE_CHECKING, Any, assert_never, cast, overload
14
14
 
@@ -77,6 +77,7 @@ def enhanced_context_manager[**P, T_co](
77
77
  make_gcm = contextmanager(func)
78
78
 
79
79
  @contextmanager
80
+ @wraps(func)
80
81
  def wrapped(*args: P.args, **kwargs: P.kwargs) -> Iterator[T_co]:
81
82
  gcm = make_gcm(*args, **kwargs)
82
83
  sigabrt0 = _swap_handler(SIGABRT, gcm) if sigabrt else None
@@ -159,6 +160,7 @@ def enhanced_async_context_manager[**P, T_co](
159
160
  make_agcm = asynccontextmanager(func)
160
161
 
161
162
  @asynccontextmanager
163
+ @wraps(func)
162
164
  async def wrapped(*args: P.args, **kwargs: P.kwargs) -> AsyncIterator[T_co]:
163
165
  agcm = make_agcm(*args, **kwargs)
164
166
  sigabrt0 = _swap_handler(SIGABRT, agcm) if sigabrt else None
@@ -6,12 +6,14 @@ from dataclasses import dataclass, is_dataclass
6
6
  from functools import partial
7
7
  from itertools import chain
8
8
  from pathlib import Path
9
+ from re import search
9
10
  from types import NoneType, UnionType
10
11
  from typing import (
11
12
  Any,
12
13
  ForwardRef,
13
14
  Literal,
14
15
  NamedTuple,
16
+ NotRequired,
15
17
  Optional, # pyright: ignore[reportDeprecated]
16
18
  TypeAliasType,
17
19
  TypeGuard,
@@ -56,6 +58,18 @@ def get_args(obj: Any, /, *, optional_drop_none: bool = False) -> tuple[Any, ...
56
58
  ##
57
59
 
58
60
 
61
+ def get_forward_ref_args(obj: Any, /) -> Mapping[str, str]:
62
+ """Get the forward args."""
63
+ return {
64
+ k: v.__forward_arg__
65
+ for k, v in obj.__annotations__.items()
66
+ if isinstance(v, ForwardRef)
67
+ }
68
+
69
+
70
+ ##
71
+
72
+
59
73
  def get_literal_elements(obj: Any, /) -> list[Any]:
60
74
  """Get the elements of a literal annotation."""
61
75
  return _get_literal_elements_inner(obj)
@@ -151,21 +165,20 @@ def get_type_hints(
151
165
  globalns_use = globals() | ({} if globalns is None else dict(globalns))
152
166
  localns_use = {} if localns is None else dict(localns)
153
167
  result: dict[str, Any] = obj.__annotations__
154
- result = {
155
- k: v.__forward_arg__ if isinstance(v, ForwardRef) else v
156
- for k, v in result.items()
157
- }
168
+ result = result | dict(get_forward_ref_args(obj))
158
169
  try:
159
- hints = _get_type_hints(obj, globalns=globalns_use, localns=localns_use)
170
+ hints = _get_type_hints(
171
+ obj, globalns=globalns_use, localns=localns_use, include_extras=True
172
+ )
160
173
  except NameError as error:
161
174
  if warn_name_errors:
162
175
  warn(f"Error getting type hints for {obj!r}; {error}", stacklevel=2)
163
176
  else:
164
- result.update({
177
+ result = result | {
165
178
  key: value
166
179
  for key, value in hints.items()
167
180
  if (key not in result) or isinstance(result[key], str)
168
- })
181
+ }
169
182
  return result
170
183
 
171
184
 
@@ -393,17 +406,21 @@ def _is_instance_typed_dict[T: _TypedDictMeta](
393
406
  hints = get_type_hints(
394
407
  type_, globalns=globalns, localns=localns, warn_name_errors=warn_name_errors
395
408
  )
396
- if not set(obj).issuperset(hints):
409
+ optional = {
410
+ k for k, v in type_.__annotations__.items() if is_not_required_annotation(v)
411
+ }
412
+ required = {k: v for k, v in hints.items() if k not in optional}
413
+ if not set(obj).issuperset(required):
397
414
  return False
398
415
  return all(
399
416
  is_instance_gen(
400
417
  obj[k],
401
- hints[k],
418
+ required[k],
402
419
  globalns=globalns,
403
420
  localns=localns,
404
421
  warn_name_errors=warn_name_errors,
405
422
  )
406
- for k in hints
423
+ for k in required
407
424
  )
408
425
 
409
426
 
@@ -577,6 +594,30 @@ def _is_namedtuple_core(obj: Any, /) -> bool:
577
594
  ##
578
595
 
579
596
 
597
+ def is_not_required_annotation(obj: Any) -> bool:
598
+ """Check if an annotation is not required."""
599
+ if is_not_required_type(obj):
600
+ return True
601
+ match obj:
602
+ case str() as text:
603
+ return bool(search("NotRequired", text))
604
+ case ForwardRef() as fr:
605
+ return is_not_required_annotation(fr.__forward_arg__)
606
+ case _:
607
+ return False
608
+
609
+
610
+ ##
611
+
612
+
613
+ def is_not_required_type(obj: Any, /) -> bool:
614
+ """Check if an object is a not-required type annotation."""
615
+ return (obj is NotRequired) or _is_annotation_of_type(obj, NotRequired)
616
+
617
+
618
+ ##
619
+
620
+
580
621
  def is_optional_type(obj: Any, /) -> bool:
581
622
  """Check if an object is an optional type annotation."""
582
623
  is_optional = _is_annotation_of_type(obj, Optional) # pyright: ignore[reportDeprecated]
@@ -889,6 +930,8 @@ __all__ = [
889
930
  "is_mapping_type",
890
931
  "is_namedtuple_class",
891
932
  "is_namedtuple_instance",
933
+ "is_not_required_annotation",
934
+ "is_not_required_type",
892
935
  "is_optional_type",
893
936
  "is_sequence_of",
894
937
  "is_sequence_of_tuple_or_str_mapping",