dycw-utilities 0.125.20__tar.gz → 0.125.22__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 (229) hide show
  1. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/PKG-INFO +3 -3
  2. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/pyproject.toml +6 -5
  3. dycw_utilities-0.125.22/src/tests/test_contextlib.py +75 -0
  4. dycw_utilities-0.125.22/src/tests/test_psutil.py +50 -0
  5. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/__init__.py +1 -1
  6. dycw_utilities-0.125.22/src/utilities/contextlib.py +44 -0
  7. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/errors.py +1 -0
  8. dycw_utilities-0.125.22/src/utilities/psutil.py +115 -0
  9. dycw_utilities-0.125.20/src/tests/test_contextlib.py +0 -15
  10. dycw_utilities-0.125.20/src/utilities/contextlib.py +0 -23
  11. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/.gitignore +0 -0
  12. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/LICENSE +0 -0
  13. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/README.md +0 -0
  14. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/__init__.py +0 -0
  15. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/conftest.py +0 -0
  16. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/__init__.py +0 -0
  17. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_missing/__init__.py +0 -0
  18. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_missing/module.py +0 -0
  19. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/__init__.py +0 -0
  20. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/outer_1.py +0 -0
  21. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/outer_2.py +0 -0
  22. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  23. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  24. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  25. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  26. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_without/__init__.py +0 -0
  27. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_without/module_1.py +0 -0
  28. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/package_without/module_2.py +0 -0
  29. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/standalone.py +0 -0
  30. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/modules/with_imports.py +0 -0
  31. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  32. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  33. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  34. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  35. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  36. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  37. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  38. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  39. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_altair.py +0 -0
  40. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_asyncio.py +0 -0
  41. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_atomicwrites.py +0 -0
  42. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_atools.py +0 -0
  43. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_cachetools.py +0 -0
  44. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_click.py +0 -0
  45. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_concurrent.py +0 -0
  46. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_contextvars.py +0 -0
  47. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_cryptography.py +0 -0
  48. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_cvxpy.py +0 -0
  49. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_dataclasses.py +0 -0
  50. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_datetime.py +0 -0
  51. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_enum.py +0 -0
  52. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_errors.py +0 -0
  53. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_eventkit.py +0 -0
  54. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_fastapi.py +0 -0
  55. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_fpdf2.py +0 -0
  56. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_functions.py +0 -0
  57. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_functools.py +0 -0
  58. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_getpass.py +0 -0
  59. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_git.py +0 -0
  60. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_hashlib.py +0 -0
  61. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_http.py +0 -0
  62. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_hypothesis.py +0 -0
  63. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_importlib.py +0 -0
  64. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_ipython.py +0 -0
  65. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_iterables.py +0 -0
  66. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_jupyter.py +0 -0
  67. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_libcst.py +0 -0
  68. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_lightweight_charts.py +0 -0
  69. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_logging.py +0 -0
  70. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_loguru.py +0 -0
  71. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_luigi.py +0 -0
  72. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_math.py +0 -0
  73. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_memory_profiler.py +0 -0
  74. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_modules.py +0 -0
  75. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_more_itertools.py +0 -0
  76. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_numpy.py +0 -0
  77. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_operator.py +0 -0
  78. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_optuna.py +0 -0
  79. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_orjson.py +0 -0
  80. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_os.py +0 -0
  81. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_parse.py +0 -0
  82. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pathlib.py +0 -0
  83. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_period.py +0 -0
  84. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pickle.py +0 -0
  85. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_platform.py +0 -0
  86. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_polars.py +0 -0
  87. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_polars_ols.py +0 -0
  88. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pqdm.py +0 -0
  89. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pydantic.py +0 -0
  90. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pyinstrument.py +0 -0
  91. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pyrsistent.py +0 -0
  92. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pytest.py +0 -0
  93. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_pytest_regressions.py +0 -0
  94. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_python_dotenv.py +0 -0
  95. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_random.py +0 -0
  96. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_re.py +0 -0
  97. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_redis.py +0 -0
  98. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_reprlib.py +0 -0
  99. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_rich.py +0 -0
  100. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_scipy.py +0 -0
  101. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_sentinel.py +0 -0
  102. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_shelve.py +0 -0
  103. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_slack_sdk.py +0 -0
  104. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_socket.py +0 -0
  105. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_sqlalchemy.py +0 -0
  106. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_sqlalchemy_polars.py +0 -0
  107. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_statsmodel.py +0 -0
  108. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_streamlit.py +0 -0
  109. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_string.py +0 -0
  110. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_sys.py +0 -0
  111. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_tempfile.py +0 -0
  112. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_tenacity.py +0 -0
  113. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_text.py +0 -0
  114. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_threading.py +0 -0
  115. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_timer.py +0 -0
  116. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback.py +0 -0
  117. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/__init__.py +0 -0
  118. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/chain.py +0 -0
  119. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  120. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  121. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  122. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/many.py +0 -0
  123. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/one.py +0 -0
  124. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/recursive.py +0 -0
  125. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  126. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  127. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/two.py +0 -0
  128. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_traceback_funcs/untraced.py +0 -0
  129. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_types.py +0 -0
  130. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_typing.py +0 -0
  131. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_typing_funcs/__init__.py +0 -0
  132. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_typing_funcs/no_future.py +0 -0
  133. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_typing_funcs/with_future.py +0 -0
  134. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_tzdata.py +0 -0
  135. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_tzlocal.py +0 -0
  136. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_uuid.py +0 -0
  137. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_version.py +0 -0
  138. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_warnings.py +0 -0
  139. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_whenever.py +0 -0
  140. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_zipfile.py +0 -0
  141. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/tests/test_zoneinfo.py +0 -0
  142. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/altair.py +0 -0
  143. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/asyncio.py +0 -0
  144. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/atomicwrites.py +0 -0
  145. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/atools.py +0 -0
  146. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/cachetools.py +0 -0
  147. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/click.py +0 -0
  148. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/concurrent.py +0 -0
  149. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/contextvars.py +0 -0
  150. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/cryptography.py +0 -0
  151. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/cvxpy.py +0 -0
  152. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/dataclasses.py +0 -0
  153. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/datetime.py +0 -0
  154. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/enum.py +0 -0
  155. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/eventkit.py +0 -0
  156. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/fastapi.py +0 -0
  157. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/fpdf2.py +0 -0
  158. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/functions.py +0 -0
  159. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/functools.py +0 -0
  160. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/getpass.py +0 -0
  161. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/git.py +0 -0
  162. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/hashlib.py +0 -0
  163. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/http.py +0 -0
  164. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/hypothesis.py +0 -0
  165. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/importlib.py +0 -0
  166. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/ipython.py +0 -0
  167. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/iterables.py +0 -0
  168. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/jupyter.py +0 -0
  169. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/libcst.py +0 -0
  170. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/lightweight_charts.py +0 -0
  171. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/logging.py +0 -0
  172. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/loguru.py +0 -0
  173. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/luigi.py +0 -0
  174. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/math.py +0 -0
  175. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/memory_profiler.py +0 -0
  176. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/modules.py +0 -0
  177. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/more_itertools.py +0 -0
  178. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/numpy.py +0 -0
  179. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/operator.py +0 -0
  180. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/optuna.py +0 -0
  181. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/orjson.py +0 -0
  182. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/os.py +0 -0
  183. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/parse.py +0 -0
  184. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pathlib.py +0 -0
  185. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/period.py +0 -0
  186. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pickle.py +0 -0
  187. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/platform.py +0 -0
  188. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/polars.py +0 -0
  189. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/polars_ols.py +0 -0
  190. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pqdm.py +0 -0
  191. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/py.typed +0 -0
  192. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pydantic.py +0 -0
  193. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pyinstrument.py +0 -0
  194. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pyrsistent.py +0 -0
  195. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pytest.py +0 -0
  196. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/pytest_regressions.py +0 -0
  197. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/python_dotenv.py +0 -0
  198. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/random.py +0 -0
  199. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/re.py +0 -0
  200. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/redis.py +0 -0
  201. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/reprlib.py +0 -0
  202. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/rich.py +0 -0
  203. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/scipy.py +0 -0
  204. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/sentinel.py +0 -0
  205. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/shelve.py +0 -0
  206. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/slack_sdk.py +0 -0
  207. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/socket.py +0 -0
  208. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/sqlalchemy.py +0 -0
  209. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/sqlalchemy_polars.py +0 -0
  210. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/statsmodels.py +0 -0
  211. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/streamlit.py +0 -0
  212. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/string.py +0 -0
  213. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/sys.py +0 -0
  214. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/tempfile.py +0 -0
  215. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/tenacity.py +0 -0
  216. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/text.py +0 -0
  217. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/threading.py +0 -0
  218. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/timer.py +0 -0
  219. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/traceback.py +0 -0
  220. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/types.py +0 -0
  221. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/typing.py +0 -0
  222. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/tzdata.py +0 -0
  223. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/tzlocal.py +0 -0
  224. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/uuid.py +0 -0
  225. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/version.py +0 -0
  226. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/warnings.py +0 -0
  227. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/whenever.py +0 -0
  228. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/zipfile.py +0 -0
  229. {dycw_utilities-0.125.20 → dycw_utilities-0.125.22}/src/utilities/zoneinfo.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.125.20
3
+ Version: 0.125.22
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
7
7
  Requires-Dist: typing-extensions<4.14,>=4.13.1
8
8
  Provides-Extra: test
9
- Requires-Dist: hypothesis<6.132,>=6.131.30; extra == 'test'
9
+ Requires-Dist: hypothesis<6.132,>=6.131.32; extra == 'test'
10
10
  Requires-Dist: pytest-asyncio<1.1,>=1.0.0; extra == 'test'
11
11
  Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
12
12
  Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
@@ -78,7 +78,7 @@ Provides-Extra: zzz-test-hypothesis
78
78
  Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
79
79
  Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
80
80
  Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
81
- Requires-Dist: hypothesis<6.132,>=6.131.30; extra == 'zzz-test-hypothesis'
81
+ Requires-Dist: hypothesis<6.132,>=6.131.32; extra == 'zzz-test-hypothesis'
82
82
  Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
83
83
  Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-hypothesis'
84
84
  Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
@@ -25,7 +25,7 @@ dev = [
25
25
  "fpdf2 >= 2.8.3, < 2.9",
26
26
  "greenlet >= 3.2.0, < 3.3", # for sqlalchemy async
27
27
  "httpx >= 0.28.1, < 0.29", # for fastapi
28
- "hypothesis >= 6.131.30, < 6.132",
28
+ "hypothesis >= 6.131.32, < 6.132",
29
29
  "img2pdf >= 0.6.0, < 0.7",
30
30
  "lightweight-charts >= 2.1, < 2.2",
31
31
  "loguru >= 0.7.3, < 0.8",
@@ -43,6 +43,7 @@ dev = [
43
43
  "polars-ols >= 0.3.5, < 0.4",
44
44
  "pqdm >= 0.2.0, < 0.3",
45
45
  "psycopg2-binary >= 2.9.10, < 2.10", # for sqlalchemy
46
+ "psutil >= 7.0.0, < 7.1",
46
47
  "pydantic >= 2.11.4, < 2.12",
47
48
  "pyinstrument >= 5.0.2, < 5.1",
48
49
  "pyright[nodejs] >= 1.1.401, < 1.2",
@@ -93,11 +94,11 @@ dependencies = [
93
94
  name = "dycw-utilities"
94
95
  readme = "README.md"
95
96
  requires-python = ">= 3.12"
96
- version = "0.125.20"
97
+ version = "0.125.22"
97
98
 
98
99
  [project.optional-dependencies]
99
100
  test = [
100
- "hypothesis >= 6.131.30, < 6.132",
101
+ "hypothesis >= 6.131.32, < 6.132",
101
102
  "pytest >= 8.3.5, < 8.4",
102
103
  "pytest-asyncio >= 1.0.0, < 1.1",
103
104
  "pytest-cov >= 6.1.1, < 6.2",
@@ -174,7 +175,7 @@ zzz-test-hypothesis = [
174
175
  "aiosqlite >= 0.21.0, < 0.22",
175
176
  "asyncpg >= 0.30.0, < 0.31", # for sqlalchemy async
176
177
  "greenlet >= 3.2.0, < 3.3", # for sqlalchemy async
177
- "hypothesis >= 6.131.30, < 6.132",
178
+ "hypothesis >= 6.131.32, < 6.132",
178
179
  "luigi >= 3.6.0, < 3.7",
179
180
  "numpy >= 2.2.6, < 2.3",
180
181
  "pathvalidate >= 3.2.3, < 3.3",
@@ -334,7 +335,7 @@ zzz-test-zoneinfo = [
334
335
  # bump-my-version
335
336
  [tool.bumpversion]
336
337
  allow_dirty = true
337
- current_version = "0.125.20"
338
+ current_version = "0.125.22"
338
339
 
339
340
  [[tool.bumpversion.files]]
340
341
  filename = "src/utilities/__init__.py"
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import override
5
+
6
+ from pytest import raises
7
+
8
+ from utilities.contextlib import (
9
+ NoOpContextManager,
10
+ suppress_super_object_attribute_error,
11
+ )
12
+
13
+
14
+ class TestNoOpContextManager:
15
+ def test_main(self) -> None:
16
+ with NoOpContextManager():
17
+ pass
18
+
19
+ def test_error(self) -> None:
20
+ with raises(RuntimeError), NoOpContextManager():
21
+ raise RuntimeError
22
+
23
+
24
+ class TestSuppressSuperObjectAttributeError:
25
+ def test_main(self) -> None:
26
+ inits: list[str] = []
27
+
28
+ @dataclass(kw_only=True)
29
+ class A:
30
+ def __post_init__(self) -> None:
31
+ with suppress_super_object_attribute_error():
32
+ super().__post_init__() # pyright:ignore [reportAttributeAccessIssue]
33
+ nonlocal inits
34
+ inits.append("A")
35
+
36
+ @dataclass(kw_only=True)
37
+ class B: ...
38
+
39
+ @dataclass(kw_only=True)
40
+ class C:
41
+ def __post_init__(self) -> None:
42
+ with suppress_super_object_attribute_error():
43
+ super().__post_init__() # pyright:ignore [reportAttributeAccessIssue]
44
+ nonlocal inits
45
+ inits.append("C")
46
+
47
+ @dataclass(kw_only=True)
48
+ class D: ...
49
+
50
+ @dataclass(kw_only=True)
51
+ class E(A, B, C, D):
52
+ @override
53
+ def __post_init__(self) -> None:
54
+ super().__post_init__()
55
+ nonlocal inits
56
+ inits.append("E")
57
+
58
+ _ = E()
59
+ assert inits == ["C", "A", "E"]
60
+
61
+ def test_error(self) -> None:
62
+ @dataclass(kw_only=True)
63
+ class Parent:
64
+ def __post_init__(self) -> None:
65
+ with suppress_super_object_attribute_error():
66
+ _ = self.error # pyright:ignore [reportAttributeAccessIssue]
67
+
68
+ @dataclass(kw_only=True)
69
+ class Child(Parent):
70
+ @override
71
+ def __post_init__(self) -> None:
72
+ super().__post_init__()
73
+
74
+ with raises(AttributeError, match="'Child' object has no attribute 'error'"):
75
+ _ = Child()
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ from math import isfinite, isnan
4
+ from typing import TYPE_CHECKING
5
+
6
+ from pytest import approx, mark, param
7
+
8
+ from utilities.datetime import MILLISECOND, SECOND
9
+ from utilities.psutil import MemoryMonitorService, MemoryUsage
10
+
11
+ if TYPE_CHECKING:
12
+ from pathlib import Path
13
+
14
+
15
+ class TestMemoryUsage:
16
+ def test_main(self) -> None:
17
+ memory = MemoryUsage.new()
18
+ assert memory.virtual_total >= 0
19
+ assert memory.virtual_total_mb >= 0
20
+ assert memory.virtual_total >= 0
21
+ assert memory.virtual_total_mb >= 0
22
+ assert (
23
+ isfinite(memory.virtual_pct) and (0.0 <= memory.virtual_pct <= 1.0)
24
+ ) or isnan(memory.virtual_pct)
25
+ assert memory.swap_total >= 0
26
+ assert memory.swap_total_mb >= 0
27
+ assert memory.swap_total >= 0
28
+ assert memory.swap_total_mb >= 0
29
+ assert (isfinite(memory.swap_pct) and (0.0 <= memory.swap_pct <= 1.0)) or isnan(
30
+ memory.swap_pct
31
+ )
32
+
33
+
34
+ class TestMemoryMonitorService:
35
+ @mark.parametrize("console", [param(True), param(False)])
36
+ async def test_main(self, *, console: bool, tmp_path: Path) -> None:
37
+ path = tmp_path.joinpath("memory.txt")
38
+ service = MemoryMonitorService(
39
+ freq=100 * MILLISECOND,
40
+ backoff=100 * MILLISECOND,
41
+ timeout=SECOND,
42
+ path=path,
43
+ console=str(tmp_path) if console else None,
44
+ )
45
+ async with service.with_auto_start:
46
+ ...
47
+ assert path.exists()
48
+ with path.open() as fh:
49
+ lines = fh.readlines()
50
+ assert len(lines) == approx(10, rel=0.5)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.125.20"
3
+ __version__ = "0.125.22"
@@ -0,0 +1,44 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from contextlib import contextmanager
5
+ from typing import TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ from collections.abc import Iterator
9
+ from types import TracebackType
10
+
11
+
12
+ class NoOpContextManager:
13
+ """Context-manager for no-op."""
14
+
15
+ def __enter__(self) -> None:
16
+ return None
17
+
18
+ def __exit__(
19
+ self,
20
+ exc_type: type[BaseException] | None,
21
+ exc_val: BaseException | None,
22
+ traceback: TracebackType | None,
23
+ ) -> bool:
24
+ _ = (exc_type, exc_val, traceback)
25
+ return False
26
+
27
+
28
+ ##
29
+
30
+
31
+ _SUPER_OBJECT_HAS_NO_ATTRIBUTE = re.compile(r"'super' object has no attribute '\w+'")
32
+
33
+
34
+ @contextmanager
35
+ def suppress_super_object_attribute_error() -> Iterator[None]:
36
+ """Suppress the super() attribute error, for mix-ins."""
37
+ try:
38
+ yield
39
+ except AttributeError as error:
40
+ if not _SUPER_OBJECT_HAS_NO_ATTRIBUTE.search(error.args[0]):
41
+ raise
42
+
43
+
44
+ __all__ = ["NoOpContextManager", "suppress_super_object_attribute_error"]
@@ -15,6 +15,7 @@ class ImpossibleCaseError(Exception):
15
15
  def __str__(self) -> str:
16
16
  desc = ", ".join(self.case)
17
17
  return f"Case must be possible: {desc}."
18
+ ##
18
19
 
19
20
 
20
21
  ##
@@ -0,0 +1,115 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from json import dumps
5
+ from logging import getLogger
6
+ from math import isclose, nan
7
+ from pathlib import Path
8
+ from typing import TYPE_CHECKING, Self, override
9
+
10
+ from psutil import swap_memory, virtual_memory
11
+
12
+ from utilities.asyncio import Looper
13
+ from utilities.contextlib import suppress_super_object_attribute_error
14
+ from utilities.datetime import SECOND, get_now
15
+
16
+ if TYPE_CHECKING:
17
+ import datetime as dt
18
+ from logging import Logger
19
+
20
+ from utilities.types import Duration, PathLike
21
+
22
+
23
+ @dataclass(kw_only=True)
24
+ class MemoryMonitorService(Looper[None]):
25
+ """Service to monitor memory usage."""
26
+
27
+ # base
28
+ freq: Duration = field(default=10 * SECOND, repr=False)
29
+ backoff: Duration = field(default=10 * SECOND, repr=False)
30
+ # self
31
+ console: str | None = field(default=None, repr=False)
32
+ path: PathLike = "memory.txt"
33
+ _console: Logger | None = field(init=False, repr=False)
34
+ _max_age: int | None = field(default=None, init=False, repr=False)
35
+ _path: Path = field(init=False, repr=False)
36
+
37
+ @override
38
+ def __post_init__(self) -> None:
39
+ super().__post_init__()
40
+ if self.console is not None:
41
+ self._console = getLogger(self.console)
42
+ self._path = Path(self.path)
43
+
44
+ @override
45
+ async def core(self) -> None:
46
+ await super().core()
47
+ memory = MemoryUsage.new()
48
+ mapping = {
49
+ "datetime": memory.datetime.strftime("%Y-%m-%d %H:%M:%S"),
50
+ "virtual used (mb)": memory.virtual_used_mb,
51
+ "virtual total (mb)": memory.virtual_total_mb,
52
+ "virtual (%)": memory.virtual_pct,
53
+ "swap used (mb)": memory.swap_used_mb,
54
+ "swap total (mb)": memory.swap_total_mb,
55
+ "swap (%)": memory.swap_pct,
56
+ }
57
+ ser = dumps(mapping)
58
+ with self._path.open(mode="a") as fh:
59
+ _ = fh.write(f"{ser}\n")
60
+ if self._console is not None:
61
+ self._console.info("%s", mapping)
62
+
63
+
64
+ ##
65
+
66
+
67
+ @dataclass(kw_only=True)
68
+ class MemoryUsage:
69
+ """A memory usage."""
70
+
71
+ datetime: dt.datetime = field(default_factory=get_now)
72
+ virtual_used: int = field(repr=False)
73
+ virtual_used_mb: int = field(init=False)
74
+ virtual_total: int = field(repr=False)
75
+ virtual_total_mb: int = field(init=False)
76
+ virtual_pct: float = field(init=False)
77
+ swap_used: int = field(repr=False)
78
+ swap_used_mb: int = field(init=False)
79
+ swap_total: int = field(repr=False)
80
+ swap_total_mb: int = field(init=False)
81
+ swap_pct: float = field(init=False)
82
+
83
+ def __post_init__(self) -> None:
84
+ with suppress_super_object_attribute_error():
85
+ super().__post_init__() # pyright: ignore[reportAttributeAccessIssue]
86
+ self.virtual_used_mb = self._to_mb(self.virtual_used)
87
+ self.virtual_total_mb = self._to_mb(self.virtual_total)
88
+ self.virtual_pct = (
89
+ nan
90
+ if isclose(self.virtual_total, 0.0)
91
+ else self.virtual_used / self.virtual_total
92
+ )
93
+ self.swap_used_mb = self._to_mb(self.swap_used)
94
+ self.swap_total_mb = self._to_mb(self.swap_total)
95
+ self.swap_pct = (
96
+ nan if isclose(self.swap_total, 0.0) else self.swap_used / self.swap_total
97
+ )
98
+
99
+ @classmethod
100
+ def new(cls) -> Self:
101
+ virtual = virtual_memory()
102
+ virtual_total = virtual.total
103
+ swap = swap_memory()
104
+ return cls(
105
+ virtual_used=virtual_total - virtual.available,
106
+ virtual_total=virtual_total,
107
+ swap_used=swap.used,
108
+ swap_total=swap.total,
109
+ )
110
+
111
+ def _to_mb(self, bytes_: int) -> int:
112
+ return round(bytes_ / (1024**2))
113
+
114
+
115
+ __all__ = ["MemoryMonitorService", "MemoryUsage"]
@@ -1,15 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pytest import raises
4
-
5
- from utilities.contextlib import NoOpContextManager
6
-
7
-
8
- class TestNoOpContextManager:
9
- def test_main(self) -> None:
10
- with NoOpContextManager():
11
- pass
12
-
13
- def test_error(self) -> None:
14
- with raises(RuntimeError), NoOpContextManager():
15
- raise RuntimeError
@@ -1,23 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- if TYPE_CHECKING:
6
- from types import TracebackType
7
-
8
-
9
- class NoOpContextManager:
10
- def __enter__(self) -> None:
11
- return None
12
-
13
- def __exit__(
14
- self,
15
- exc_type: type[BaseException] | None,
16
- exc_val: BaseException | None,
17
- traceback: TracebackType | None,
18
- ) -> bool:
19
- _ = (exc_type, exc_val, traceback)
20
- return False
21
-
22
-
23
- __all__ = ["NoOpContextManager"]