dycw-utilities 0.166.27__tar.gz → 0.174.19__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 (227) hide show
  1. dycw_utilities-0.174.19/PKG-INFO +41 -0
  2. dycw_utilities-0.174.19/pyproject.toml +332 -0
  3. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/__init__.py +1 -1
  4. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/aeventkit.py +2 -1
  5. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/altair.py +6 -3
  6. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/asyncio.py +10 -16
  7. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/cachetools.py +9 -6
  8. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/click.py +76 -20
  9. dycw_utilities-0.174.19/src/utilities/docker.py +293 -0
  10. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/functions.py +1 -1
  11. dycw_utilities-0.174.19/src/utilities/grp.py +28 -0
  12. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/hypothesis.py +38 -6
  13. dycw_utilities-0.174.19/src/utilities/jinja2.py +148 -0
  14. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/logging.py +7 -9
  15. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/orjson.py +18 -18
  16. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/os.py +39 -1
  17. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/parse.py +2 -2
  18. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pathlib.py +18 -1
  19. dycw_utilities-0.174.19/src/utilities/permissions.py +298 -0
  20. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/platform.py +1 -1
  21. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/polars.py +4 -1
  22. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/postgres.py +28 -29
  23. dycw_utilities-0.174.19/src/utilities/pwd.py +28 -0
  24. dycw_utilities-0.174.19/src/utilities/pydantic.py +11 -0
  25. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pydantic_settings.py +81 -8
  26. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pydantic_settings_sops.py +13 -0
  27. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pytest.py +121 -29
  28. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pytest_regressions.py +1 -2
  29. dycw_utilities-0.174.19/src/utilities/shutil.py +25 -0
  30. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/sqlalchemy.py +15 -0
  31. dycw_utilities-0.174.19/src/utilities/subprocess.py +1253 -0
  32. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/tempfile.py +36 -1
  33. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/text.py +48 -32
  34. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/timer.py +2 -2
  35. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/traceback.py +1 -1
  36. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/types.py +5 -0
  37. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/typing.py +8 -2
  38. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/whenever.py +36 -5
  39. dycw_utilities-0.166.27/.gitignore +0 -169
  40. dycw_utilities-0.166.27/LICENSE +0 -21
  41. dycw_utilities-0.166.27/PKG-INFO +0 -41
  42. dycw_utilities-0.166.27/pyproject.toml +0 -498
  43. dycw_utilities-0.166.27/src/tests/__init__.py +0 -0
  44. dycw_utilities-0.166.27/src/tests/conftest.py +0 -193
  45. dycw_utilities-0.166.27/src/tests/modules/package_missing/__init__.py +0 -1
  46. dycw_utilities-0.166.27/src/tests/modules/package_missing/module.py +0 -5
  47. dycw_utilities-0.166.27/src/tests/modules/package_with/__init__.py +0 -1
  48. dycw_utilities-0.166.27/src/tests/modules/package_with/outer_1.py +0 -17
  49. dycw_utilities-0.166.27/src/tests/modules/package_with/outer_2.py +0 -17
  50. dycw_utilities-0.166.27/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  51. dycw_utilities-0.166.27/src/tests/modules/package_with/subpackage/inner_1.py +0 -17
  52. dycw_utilities-0.166.27/src/tests/modules/package_with/subpackage/inner_2.py +0 -17
  53. dycw_utilities-0.166.27/src/tests/modules/package_with/subpackage/inner_3.py +0 -17
  54. dycw_utilities-0.166.27/src/tests/modules/package_without/__init__.py +0 -1
  55. dycw_utilities-0.166.27/src/tests/modules/package_without/module_1.py +0 -17
  56. dycw_utilities-0.166.27/src/tests/modules/package_without/module_2.py +0 -17
  57. dycw_utilities-0.166.27/src/tests/modules/standalone.py +0 -17
  58. dycw_utilities-0.166.27/src/tests/modules/with_imports.py +0 -7
  59. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -5
  60. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -71
  61. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -5
  62. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -5
  63. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -5
  64. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -9
  65. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -74
  66. dycw_utilities-0.166.27/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -71
  67. dycw_utilities-0.166.27/src/tests/test_aeventkit.py +0 -282
  68. dycw_utilities-0.166.27/src/tests/test_altair.py +0 -169
  69. dycw_utilities-0.166.27/src/tests/test_asyncio.py +0 -492
  70. dycw_utilities-0.166.27/src/tests/test_atomicwrites.py +0 -198
  71. dycw_utilities-0.166.27/src/tests/test_atools.py +0 -67
  72. dycw_utilities-0.166.27/src/tests/test_cachetools.py +0 -85
  73. dycw_utilities-0.166.27/src/tests/test_click.py +0 -439
  74. dycw_utilities-0.166.27/src/tests/test_concurrent.py +0 -86
  75. dycw_utilities-0.166.27/src/tests/test_contextlib.py +0 -242
  76. dycw_utilities-0.166.27/src/tests/test_contextvars.py +0 -37
  77. dycw_utilities-0.166.27/src/tests/test_cryptography.py +0 -38
  78. dycw_utilities-0.166.27/src/tests/test_cvxpy.py +0 -649
  79. dycw_utilities-0.166.27/src/tests/test_dataclasses.py +0 -1012
  80. dycw_utilities-0.166.27/src/tests/test_enum.py +0 -222
  81. dycw_utilities-0.166.27/src/tests/test_errors.py +0 -82
  82. dycw_utilities-0.166.27/src/tests/test_fastapi.py +0 -43
  83. dycw_utilities-0.166.27/src/tests/test_fpdf2.py +0 -22
  84. dycw_utilities-0.166.27/src/tests/test_functions.py +0 -778
  85. dycw_utilities-0.166.27/src/tests/test_functools.py +0 -59
  86. dycw_utilities-0.166.27/src/tests/test_getpass.py +0 -8
  87. dycw_utilities-0.166.27/src/tests/test_git.py +0 -19
  88. dycw_utilities-0.166.27/src/tests/test_gzip.py +0 -21
  89. dycw_utilities-0.166.27/src/tests/test_hashlib.py +0 -14
  90. dycw_utilities-0.166.27/src/tests/test_http.py +0 -20
  91. dycw_utilities-0.166.27/src/tests/test_hypothesis.py +0 -1273
  92. dycw_utilities-0.166.27/src/tests/test_importlib.py +0 -22
  93. dycw_utilities-0.166.27/src/tests/test_inflect.py +0 -29
  94. dycw_utilities-0.166.27/src/tests/test_ipython.py +0 -15
  95. dycw_utilities-0.166.27/src/tests/test_iterables.py +0 -1397
  96. dycw_utilities-0.166.27/src/tests/test_json.py +0 -52
  97. dycw_utilities-0.166.27/src/tests/test_jupyter.py +0 -64
  98. dycw_utilities-0.166.27/src/tests/test_libcst.py +0 -168
  99. dycw_utilities-0.166.27/src/tests/test_lightweight_charts.py +0 -64
  100. dycw_utilities-0.166.27/src/tests/test_logging.py +0 -534
  101. dycw_utilities-0.166.27/src/tests/test_math.py +0 -1383
  102. dycw_utilities-0.166.27/src/tests/test_memory_profiler.py +0 -21
  103. dycw_utilities-0.166.27/src/tests/test_modules.py +0 -144
  104. dycw_utilities-0.166.27/src/tests/test_more_itertools.py +0 -354
  105. dycw_utilities-0.166.27/src/tests/test_numpy.py +0 -1178
  106. dycw_utilities-0.166.27/src/tests/test_objects/__init__.py +0 -1
  107. dycw_utilities-0.166.27/src/tests/test_objects/objects.py +0 -225
  108. dycw_utilities-0.166.27/src/tests/test_operator.py +0 -127
  109. dycw_utilities-0.166.27/src/tests/test_optuna.py +0 -76
  110. dycw_utilities-0.166.27/src/tests/test_orjson.py +0 -799
  111. dycw_utilities-0.166.27/src/tests/test_os.py +0 -160
  112. dycw_utilities-0.166.27/src/tests/test_parse.py +0 -757
  113. dycw_utilities-0.166.27/src/tests/test_pathlib.py +0 -325
  114. dycw_utilities-0.166.27/src/tests/test_pickle.py +0 -21
  115. dycw_utilities-0.166.27/src/tests/test_platform.py +0 -97
  116. dycw_utilities-0.166.27/src/tests/test_polars.py +0 -3207
  117. dycw_utilities-0.166.27/src/tests/test_polars_ols.py +0 -110
  118. dycw_utilities-0.166.27/src/tests/test_postgres.py +0 -162
  119. dycw_utilities-0.166.27/src/tests/test_pottery.py +0 -109
  120. dycw_utilities-0.166.27/src/tests/test_pqdm.py +0 -105
  121. dycw_utilities-0.166.27/src/tests/test_psutil.py +0 -24
  122. dycw_utilities-0.166.27/src/tests/test_pydantic_settings.py +0 -126
  123. dycw_utilities-0.166.27/src/tests/test_pydantic_settings_sops.py +0 -48
  124. dycw_utilities-0.166.27/src/tests/test_pyinstrument.py +0 -19
  125. dycw_utilities-0.166.27/src/tests/test_pytest.py +0 -459
  126. dycw_utilities-0.166.27/src/tests/test_pytest_randomly.py +0 -8
  127. dycw_utilities-0.166.27/src/tests/test_pytest_regressions.py +0 -68
  128. dycw_utilities-0.166.27/src/tests/test_random.py +0 -85
  129. dycw_utilities-0.166.27/src/tests/test_re.py +0 -129
  130. dycw_utilities-0.166.27/src/tests/test_redis.py +0 -768
  131. dycw_utilities-0.166.27/src/tests/test_reprlib.py +0 -87
  132. dycw_utilities-0.166.27/src/tests/test_scipy.py +0 -48
  133. dycw_utilities-0.166.27/src/tests/test_sentinel.py +0 -53
  134. dycw_utilities-0.166.27/src/tests/test_shelve.py +0 -26
  135. dycw_utilities-0.166.27/src/tests/test_slack_sdk.py +0 -34
  136. dycw_utilities-0.166.27/src/tests/test_socket.py +0 -8
  137. dycw_utilities-0.166.27/src/tests/test_sqlalchemy.py +0 -1455
  138. dycw_utilities-0.166.27/src/tests/test_sqlalchemy_polars.py +0 -639
  139. dycw_utilities-0.166.27/src/tests/test_statsmodels.py +0 -51
  140. dycw_utilities-0.166.27/src/tests/test_string.py +0 -51
  141. dycw_utilities-0.166.27/src/tests/test_tempfile.py +0 -31
  142. dycw_utilities-0.166.27/src/tests/test_testbook.py +0 -38
  143. dycw_utilities-0.166.27/src/tests/test_text.py +0 -377
  144. dycw_utilities-0.166.27/src/tests/test_threading.py +0 -42
  145. dycw_utilities-0.166.27/src/tests/test_timer.py +0 -130
  146. dycw_utilities-0.166.27/src/tests/test_traceback.py +0 -168
  147. dycw_utilities-0.166.27/src/tests/test_typed_settings.py +0 -321
  148. dycw_utilities-0.166.27/src/tests/test_types.py +0 -53
  149. dycw_utilities-0.166.27/src/tests/test_typing.py +0 -1166
  150. dycw_utilities-0.166.27/src/tests/test_typing_funcs/__init__.py +0 -0
  151. dycw_utilities-0.166.27/src/tests/test_typing_funcs/no_future.py +0 -45
  152. dycw_utilities-0.166.27/src/tests/test_typing_funcs/with_future.py +0 -246
  153. dycw_utilities-0.166.27/src/tests/test_tzdata.py +0 -14
  154. dycw_utilities-0.166.27/src/tests/test_tzlocal.py +0 -17
  155. dycw_utilities-0.166.27/src/tests/test_uuid.py +0 -96
  156. dycw_utilities-0.166.27/src/tests/test_version.py +0 -144
  157. dycw_utilities-0.166.27/src/tests/test_warnings.py +0 -74
  158. dycw_utilities-0.166.27/src/tests/test_whenever.py +0 -1805
  159. dycw_utilities-0.166.27/src/tests/test_zipfile.py +0 -37
  160. dycw_utilities-0.166.27/src/tests/test_zoneinfo.py +0 -131
  161. dycw_utilities-0.166.27/src/utilities/pytest_plugins/__init__.py +0 -1
  162. dycw_utilities-0.166.27/src/utilities/typed_settings.py +0 -152
  163. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/README.md +0 -0
  164. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/atomicwrites.py +0 -0
  165. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/atools.py +0 -0
  166. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/concurrent.py +0 -0
  167. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/contextlib.py +0 -0
  168. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/contextvars.py +0 -0
  169. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/cryptography.py +0 -0
  170. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/cvxpy.py +0 -0
  171. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/dataclasses.py +0 -0
  172. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/enum.py +0 -0
  173. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/errors.py +0 -0
  174. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/fastapi.py +0 -0
  175. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/fpdf2.py +0 -0
  176. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/functools.py +0 -0
  177. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/getpass.py +0 -0
  178. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/git.py +0 -0
  179. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/gzip.py +0 -0
  180. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/hashlib.py +0 -0
  181. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/http.py +0 -0
  182. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/importlib.py +0 -0
  183. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/inflect.py +0 -0
  184. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/ipython.py +0 -0
  185. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/iterables.py +0 -0
  186. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/json.py +0 -0
  187. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/jupyter.py +0 -0
  188. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/libcst.py +0 -0
  189. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/lightweight_charts.py +0 -0
  190. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/math.py +0 -0
  191. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/memory_profiler.py +0 -0
  192. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/modules.py +0 -0
  193. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/more_itertools.py +0 -0
  194. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/numpy.py +0 -0
  195. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/operator.py +0 -0
  196. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/optuna.py +0 -0
  197. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pickle.py +0 -0
  198. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/polars_ols.py +0 -0
  199. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pottery.py +0 -0
  200. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pqdm.py +0 -0
  201. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/psutil.py +0 -0
  202. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/py.typed +0 -0
  203. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pyinstrument.py +0 -0
  204. {dycw_utilities-0.166.27/src/tests/modules → dycw_utilities-0.174.19/src/utilities/pytest_plugins}/__init__.py +0 -0
  205. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pytest_plugins/pytest_randomly.py +0 -0
  206. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/pytest_plugins/pytest_regressions.py +0 -0
  207. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/random.py +0 -0
  208. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/re.py +0 -0
  209. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/redis.py +0 -0
  210. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/reprlib.py +0 -0
  211. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/scipy.py +0 -0
  212. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/sentinel.py +0 -0
  213. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/shelve.py +0 -0
  214. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/slack_sdk.py +0 -0
  215. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/socket.py +0 -0
  216. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/sqlalchemy_polars.py +0 -0
  217. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/statsmodels.py +0 -0
  218. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/string.py +0 -0
  219. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/testbook.py +0 -0
  220. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/threading.py +0 -0
  221. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/tzdata.py +0 -0
  222. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/tzlocal.py +0 -0
  223. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/uuid.py +0 -0
  224. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/version.py +0 -0
  225. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/warnings.py +0 -0
  226. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/zipfile.py +0 -0
  227. {dycw_utilities-0.166.27 → dycw_utilities-0.174.19}/src/utilities/zoneinfo.py +0 -0
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.3
2
+ Name: dycw-utilities
3
+ Version: 0.174.19
4
+ Author: Derek Wan
5
+ Author-email: Derek Wan <d.wan@icloud.com>
6
+ Requires-Dist: atomicwrites>=1.4.1,<1.5
7
+ Requires-Dist: typing-extensions>=4.15.0,<4.16
8
+ Requires-Dist: tzlocal>=5.3.1,<5.4
9
+ Requires-Dist: whenever>=0.9.4,<0.10
10
+ Requires-Dist: coloredlogs>=15.0.1,<15.1 ; extra == 'logging'
11
+ Requires-Dist: dycw-pytest-only>=2.1.1,<2.2 ; extra == 'test'
12
+ Requires-Dist: hypothesis>=6.148.8,<6.149 ; extra == 'test'
13
+ Requires-Dist: pytest>=9.0.2,<9.1 ; extra == 'test'
14
+ Requires-Dist: pytest-asyncio>=1.3.0,<1.4 ; extra == 'test'
15
+ Requires-Dist: pytest-cov>=7.0.0,<7.1 ; extra == 'test'
16
+ Requires-Dist: pytest-instafail>=0.5.0,<0.6 ; extra == 'test'
17
+ Requires-Dist: pytest-lazy-fixtures>=1.4.0,<1.5 ; extra == 'test'
18
+ Requires-Dist: pytest-randomly>=4.0.1,<4.1 ; extra == 'test'
19
+ Requires-Dist: pytest-regressions>=2.8.3,<2.9 ; extra == 'test'
20
+ Requires-Dist: pytest-repeat>=0.9.4,<0.10 ; extra == 'test'
21
+ Requires-Dist: pytest-rerunfailures>=16.1,<16.2 ; extra == 'test'
22
+ Requires-Dist: pytest-rng>=1.0.0,<1.1 ; extra == 'test'
23
+ Requires-Dist: pytest-timeout>=2.4.0,<2.5 ; extra == 'test'
24
+ Requires-Dist: pytest-xdist>=3.8.0,<3.9 ; extra == 'test'
25
+ Requires-Dist: testbook>=0.4.2,<0.5 ; extra == 'test'
26
+ Requires-Python: >=3.12
27
+ Provides-Extra: logging
28
+ Provides-Extra: test
29
+ Description-Content-Type: text/markdown
30
+
31
+ [![PyPI version](https://badge.fury.io/py/dycw-utilities.svg)](https://badge.fury.io/py/dycw-utilities)
32
+
33
+ # `dycw-utilities`
34
+
35
+ [All the Python functions I don't want to write twice.](https://github.com/nvim-lua/plenary.nvim)
36
+
37
+ ## Installation
38
+
39
+ - `pip install dycw-utilities`
40
+
41
+ or with [extras](https://github.com/dycw/python-utilities/blob/master/pyproject.toml).
@@ -0,0 +1,332 @@
1
+ # build-system
2
+ [build-system]
3
+ build-backend = "uv_build"
4
+ requires = ["uv_build"]
5
+
6
+ # dependency groups
7
+ [dependency-groups]
8
+ aeventkit = ["aeventkit >=2.1.0, <2.2"]
9
+ altair = ["altair >=5.5.0, <5.6"]
10
+ altair-test = ["polars", "img2pdf", "vl-convert-python"]
11
+ atools = ["atools >=0.14.2, <0.15"]
12
+ cachetools = ["cachetools >=6.2.4, <6.3"]
13
+ click = ["click >=8.3.1, <8.4"]
14
+ core = [
15
+ "atomicwrites >=1.4.1, <1.5",
16
+ "typing-extensions >=4.15.0, <4.16",
17
+ "tzlocal >=5.3.1, <5.4",
18
+ "whenever >=0.9.4, <0.10",
19
+ ]
20
+ cryptography = ["cryptography >=46.0.3, <46.1"]
21
+ cvxpy = ["cvxpy >=1.7.5, <1.8"]
22
+ dataclasses-test = ["orjson", "polars"]
23
+ dev = [
24
+ "coloredlogs >=15.0.1, <15.1",
25
+ "coverage-conditional-plugin >=0.9.0, <0.10",
26
+ "dycw-pytest-only >=2.1.1, <2.2",
27
+ "pyright[nodejs] >=1.1.407, <1.2",
28
+ "pytest-cov >=7.0.0, <7.1",
29
+ "pytest-timeout >=2.4.0, <2.5",
30
+ ]
31
+ fastapi = ["fastapi >=0.128.0, <0.129"]
32
+ fastapi-test = ["httpx", "uvicorn"]
33
+ fpdf2 = ["fpdf2 >=2.8.5, <2.9"]
34
+ gitpython = ["gitpython >=3.1.45, <3.2"]
35
+ hashlib-test = ["orjson"]
36
+ http-test = ["orjson"]
37
+ hypothesis = ["hypothesis >=6.148.8, <6.149"]
38
+ hypothesis-test = ["libcst", "numpy", "pathvalidate", "pytest-rerunfailures"]
39
+ inflect = ["inflect >=7.5.0, <7.6"]
40
+ jinja2 = ["jinja2 >=3.1.6, <3.2"]
41
+ jupyter-test = ["pandas", "polars"]
42
+ libcst = ["libcst >=1.8.6, <1.9"]
43
+ lightweight-charts = ["lightweight-charts >=2.1, <2.2"]
44
+ lightweight-charts-test = ["polars", "pyarrow"]
45
+ math-test = ["numpy"]
46
+ memory-profiler = ["memory-profiler >=0.61.0, <0.62"]
47
+ more-itertools = ["more-itertools >=10.8.0, <10.9"]
48
+ numpy = ["numpy >=2.4.0, <2.5"]
49
+ operator = ["polars"]
50
+ optuna = ["optuna >=4.6.0, <4.7"]
51
+ orjson = ["orjson >=3.11.5, <3.12"]
52
+ orjson-test = ["polars"]
53
+ polars = ["polars >=1.36.1, <1.37"]
54
+ polars-ols = ["polars-ols >=0.3.5, <0.4"]
55
+ polars-ols-test = ["scikit-learn"]
56
+ polars-test = ["numpy", "scipy", "statsmodels"]
57
+ pottery = ["pottery >=3.0.1, <3.1"]
58
+ pottery-test = ["orjson"]
59
+ pqdm = ["pqdm >=0.2.0, <0.3"]
60
+ psutil = ["psutil >=7.2.0, <7.3"]
61
+ pydantic = ["pydantic >=2.12.5, <2.13"]
62
+ pydantic-settings = ["pydantic-settings >=2.12.0, <2.13"]
63
+ pydantic-settings-sops = ["pydantic-settings-sops"]
64
+ pydantic-settings-test = ["pyyaml", "tomlkit"]
65
+ pyinstrument = ["pyinstrument >=5.1.1, <5.2"]
66
+ pytest = [
67
+ "pytest >=9.0.2, <9.1",
68
+ "pytest-asyncio >=1.3.0, <1.4",
69
+ "pytest-randomly >=4.0.1, <4.1",
70
+ "pytest-timeout >=2.4.0, <2.5",
71
+ "pytest-xdist >=3.8.0, <3.9",
72
+ ]
73
+ pytest-regressions = ["pytest-regressions >=2.8.3, <2.9"]
74
+ pytest-regressions-test = ["orjson", "polars"]
75
+ pytest-test = ["orjson", "pytest-rerunfailures", "pytest-rng"]
76
+ redis = ["redis >=7.1.0, <7.2", "orjson"]
77
+ redis-test = ["pytest-rerunfailures"]
78
+ reprlib-test = ["rich"]
79
+ scipy = ["scipy >=1.16.3, <1.17"]
80
+ sklearn = ["scikit-learn >=1.8.0, <1.9"]
81
+ slack-sdk = ["slack-sdk >=3.39.0, <3.40"]
82
+ slack-sdk-test = ["aiohttp"]
83
+ sqlalchemy = ["sqlalchemy >=2.0.45, <2.1", "psycopg"]
84
+ sqlalchemy-polars = ["sqlalchemy", "polars"]
85
+ sqlalchemy-polars-test = ["aiosqlite", "asyncpg", "greenlet"]
86
+ sqlalchemy-test = ["aiosqlite", "asyncpg", "greenlet"]
87
+ statsmodels = ["statsmodels >=0.14.6, <0.15"]
88
+ testbook = ["testbook >=0.4.2, <0.5"]
89
+ tzdata = ["tzdata >=2025.3, <2025.4"]
90
+ whenever-test = ["pathvalidate"]
91
+
92
+ # project
93
+ [project]
94
+ authors = [{ email = "d.wan@icloud.com", name = "Derek Wan" }]
95
+ dependencies = [
96
+ "atomicwrites >=1.4.1, <1.5",
97
+ "typing-extensions >=4.15.0, <4.16",
98
+ "tzlocal >=5.3.1, <5.4",
99
+ "whenever >=0.9.4, <0.10",
100
+ ]
101
+ name = "dycw-utilities"
102
+ readme = "README.md"
103
+ requires-python = ">= 3.12"
104
+ version = "0.174.19"
105
+
106
+ [project.entry-points.pytest11]
107
+ pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
108
+ pytest-regressions = "utilities.pytest_plugins.pytest_regressions"
109
+
110
+ [project.optional-dependencies]
111
+ logging = ["coloredlogs >=15.0.1, <15.1"]
112
+ test = [
113
+ "dycw-pytest-only >=2.1.1, <2.2",
114
+ "hypothesis >=6.148.8, <6.149",
115
+ "pytest >=9.0.2, <9.1",
116
+ "pytest-asyncio >=1.3.0, <1.4",
117
+ "pytest-cov >=7.0.0, <7.1",
118
+ "pytest-instafail >=0.5.0, <0.6",
119
+ "pytest-lazy-fixtures >=1.4.0, <1.5",
120
+ "pytest-randomly >=4.0.1, <4.1",
121
+ "pytest-regressions >=2.8.3, <2.9",
122
+ "pytest-repeat >=0.9.4, <0.10",
123
+ "pytest-rerunfailures >=16.1, <16.2",
124
+ "pytest-rng >=1.0.0, <1.1",
125
+ "pytest-timeout >=2.4.0, <2.5",
126
+ "pytest-xdist >=3.8.0, <3.9",
127
+ "testbook >=0.4.2, <0.5",
128
+ ]
129
+
130
+ [project.scripts]
131
+
132
+ # tool
133
+ [tool]
134
+
135
+ # bump-my-version
136
+ [tool.bumpversion]
137
+ allow_dirty = true
138
+ current_version = "0.174.19"
139
+
140
+ [[tool.bumpversion.files]]
141
+ filename = "src/utilities/__init__.py"
142
+ replace = "__version__ = \"{new_version}\""
143
+ search = "__version__ = \"{current_version}\""
144
+
145
+ # coverage
146
+ [tool.coverage]
147
+ [tool.coverage.coverage_conditional_plugin]
148
+ [tool.coverage.coverage_conditional_plugin.rules]
149
+ skipif-ci = '"CI" in os_environ'
150
+ skipif-ci-and-mac = '("CI" in os_environ) and (sys_platform == "darwin")'
151
+ skipif-ci-and-not-linux = '("CI" in os_environ) and (sys_platform != "linux")'
152
+ skipif-ci-or-mac = '("CI" in os_environ) or (sys_platform == "darwin")'
153
+ skipif-linux = 'sys_platform == "linux"'
154
+ skipif-mac = 'sys_platform == "darwin"'
155
+ skipif-not-linux = 'sys_platform != "linux"'
156
+ skipif-not-macos = 'sys_platform != "darwin"'
157
+ skipif-not-windows = 'sys_platform != "windows"'
158
+ skipif-windows = 'sys_platform == "darwin"'
159
+
160
+ [tool.coverage.html]
161
+ directory = ".coverage/html"
162
+
163
+ [tool.coverage.report]
164
+ exclude_also = [
165
+ "@overload",
166
+ "assert_never",
167
+ "case never:",
168
+ "if TYPE_CHECKING:",
169
+ ]
170
+ fail_under = 100.0
171
+ skip_covered = true
172
+ skip_empty = true
173
+
174
+ [tool.coverage.run]
175
+ branch = true
176
+ data_file = ".coverage/data"
177
+ omit = [
178
+ "src/utilities/__init__.py",
179
+ "src/utilities/pytest_plugins/*.py",
180
+ "src/utilities/streamlit.py",
181
+ ]
182
+ parallel = true
183
+ plugins = ["coverage_conditional_plugin"]
184
+ source = ["src/utilities"]
185
+
186
+ # pyright
187
+ [tool.pyright]
188
+ deprecateTypingAliases = true
189
+ enableReachabilityAnalysis = false
190
+ ignore = ["**/_typeshed/**"]
191
+ pythonVersion = "3.12"
192
+ reportCallInDefaultInitializer = true
193
+ reportImplicitOverride = true
194
+ reportImplicitStringConcatenation = true
195
+ reportImportCycles = true
196
+ reportMissingSuperCall = true
197
+ reportMissingTypeArgument = false
198
+ reportMissingTypeStubs = false
199
+ reportPrivateUsage = false
200
+ reportPropertyTypeMismatch = true
201
+ reportUninitializedInstanceVariable = true
202
+ reportUnknownArgumentType = false
203
+ reportUnknownMemberType = false
204
+ reportUnknownParameterType = false
205
+ reportUnknownVariableType = false
206
+ reportUnnecessaryComparison = false
207
+ reportUnnecessaryTypeIgnoreComment = true
208
+ reportUnusedCallResult = true
209
+ reportUnusedImport = false
210
+ reportUnusedVariable = false
211
+ typeCheckingMode = "strict"
212
+
213
+ # pytest
214
+ [tool.pytest]
215
+ addopts = [
216
+ "-ra",
217
+ "-vv",
218
+ "--color=auto",
219
+ "--durations=10",
220
+ "--durations-min=10",
221
+ "--timeout=600",
222
+ ]
223
+ asyncio_default_fixture_loop_scope = "function"
224
+ asyncio_mode = "auto"
225
+ collect_imported_tests = false
226
+ empty_parameter_set_mark = "fail_at_collect"
227
+ filterwarnings = [
228
+ "error",
229
+ "ignore:<aiosqlite.*core.*Connection .*> was delete before being closed:ResourceWarning", # sqlalchemy
230
+ "ignore:Exception ignored in.* <coroutine object .* at .*>:pytest.PytestUnraisableExceptionWarning",
231
+ "ignore:Exception in thread Thread-.*:pytest.PytestUnhandledThreadExceptionWarning",
232
+ "ignore:Jupyter is migrating its paths to use standard platformdirs:DeprecationWarning", # jupyter
233
+ "ignore:ResourceTracker called reentrantly for resource cleanup, which is unsupported:UserWarning",
234
+ "ignore:The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <Connection(.*)>:RuntimeWarning", # sqlalchemy
235
+ "ignore:Using fork.* can cause Polars to deadlock in the child process:RuntimeWarning", # polars/pqdm
236
+ "ignore:coroutine 'AsyncConnection.close' was never awaited:RuntimeWarning",
237
+ "ignore:loop is closed:ResourceWarning", # redis
238
+ "ignore:unclosed <StreamWriter .*>:ResourceWarning", # redis
239
+ "ignore:unclosed <socket.*socket .*>:ResourceWarning", # redis
240
+ "ignore:unclosed Connection <redis.*asyncio.*connection.*Connection.*>:ResourceWarning", # redis
241
+ "ignore:unclosed connection <asyncpg.*connection.*Connection.*>:ResourceWarning", # asyncpg
242
+ "ignore:unclosed database in <sqlite3.*Connection .*>:ResourceWarning", # sqlalchemy
243
+ "ignore:unclosed event loop <_UnixSelectorEventLoop .*>:ResourceWarning", # redis
244
+ "ignore:unclosed file <_io.*TextIOWrapper .*>:ResourceWarning", # logging
245
+ "ignore:unclosed transport <_SelectorSocketTransport .*>:ResourceWarning", # redis
246
+ "ignore:Do not expect file_or_dir in Namespace:UserWarning", # pytest
247
+ ]
248
+ minversion = "9.0"
249
+ strict = true
250
+ testpaths = ["src/tests"]
251
+ timeout = "600"
252
+ xfail_strict = true
253
+
254
+ # ruff
255
+ [tool.ruff]
256
+ src = ["src"]
257
+ target-version = "py312"
258
+ unsafe-fixes = true
259
+
260
+ [tool.ruff.format]
261
+ preview = true
262
+ skip-magic-trailing-comma = true
263
+
264
+ [tool.ruff.lint]
265
+ explicit-preview-rules = true
266
+ fixable = ["ALL"]
267
+ ignore = [
268
+ "ANN401", # any-type
269
+ "A005", # stdlib-module-shadowing
270
+ "ASYNC109", # async-function-with-timeout
271
+ "C901", # complex-structure
272
+ "CPY", # flake8-copyright
273
+ "D", # pydocstyle
274
+ "DOC", # pydoclint
275
+ "E501", # line-too-long
276
+ "PD", # pandas-vet
277
+ "PERF203", # try-except-in-loop
278
+ "PLC0415", # import-outside-top-level
279
+ "PLR0911", # too-many-return-statements
280
+ "PLR0912", # too-many-branches
281
+ "PLR0913", # too-many-arguments
282
+ "PLR0915", # too-many-statements
283
+ "PLR2004", # magic-value-comparison
284
+ "PT012", # pytest-raises-with-multiple-statements
285
+ "PT013", # pytest-incorrect-pytest-import
286
+ "S202", # tarfile-unsafe-members
287
+ "S310", # suspicious-url-open-usage
288
+ "S311", # suspicious-non-cryptographic-random-usage
289
+ "S602", # subprocess-popen-with-shell-equals-true
290
+ "S603", # subprocess-without-shell-equals-true
291
+ "S607", # start-process-with-partial-path
292
+ # preview
293
+ "S101", # assert
294
+ # formatter
295
+ "W191", # tab-indentation
296
+ "E111", # indentation-with-invalid-multiple
297
+ "E114", # indentation-with-invalid-multiple-comment
298
+ "E117", # over-indented
299
+ "COM812", # missing-trailing-comma
300
+ "COM819", # prohibited-trailing-comma
301
+ "ISC001", # single-line-implicit-string-concatenation
302
+ "ISC002", # multi-line-implicit-string-concatenation
303
+ ]
304
+ preview = true
305
+ select = [
306
+ "ALL",
307
+ "RUF022", # unsorted-dunder-all
308
+ ]
309
+
310
+ [tool.ruff.lint.extend-per-file-ignores]
311
+ "src/tests/**/*.py" = [
312
+ "S101", # assert
313
+ "SLF001", # private-member-access
314
+ ]
315
+ "src/tests/test_typing_funcs/no_future.py" = [
316
+ "I002",
317
+ ] # missing-required-import
318
+
319
+ [tool.ruff.lint.flake8-tidy-imports]
320
+ ban-relative-imports = "all"
321
+
322
+ [tool.ruff.lint.isort]
323
+ required-imports = ["from __future__ import annotations"]
324
+ split-on-trailing-comma = false
325
+
326
+ # uv
327
+ [tool.uv]
328
+ default-groups = "all"
329
+
330
+ [tool.uv.build-backend]
331
+ module-name = "utilities"
332
+ module-root = "src"
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.166.27"
3
+ __version__ = "0.174.19"
@@ -169,7 +169,8 @@ class LiftedEvent[F: Callable[..., MaybeCoro[None]]]:
169
169
  def __await__(self) -> Any:
170
170
  return self.event.__await__() # pragma: no cover
171
171
 
172
- __aiter__ = aiter
172
+ def __aiter__(self) -> Any:
173
+ return self.event.aiter() # pragma: no cover
173
174
 
174
175
  def __contains__(self, c: Any, /) -> bool:
175
176
  return self.event.__contains__(c) # pragma: no cover
@@ -94,7 +94,8 @@ def plot_dataframes(
94
94
  # lines
95
95
  selection = selection_point(bind="legend", fields=[var_name], nearest=False)
96
96
  lines = [
97
- chart.mark_line(interpolate=interpolate)
97
+ chart
98
+ .mark_line(interpolate=interpolate)
98
99
  .encode(
99
100
  x=x_use,
100
101
  y=Y(value_name).scale(zero=False),
@@ -124,7 +125,8 @@ def plot_dataframes(
124
125
  else:
125
126
  tooltip_format_use = Undefined
126
127
  rules = [
127
- chart.transform_pivot(var_name, value=value_name, groupby=[x_use])
128
+ chart
129
+ .transform_pivot(var_name, value=value_name, groupby=[x_use])
128
130
  .mark_rule(color="gray")
129
131
  .encode(
130
132
  x=x_use,
@@ -227,7 +229,8 @@ def plot_intraday_dataframe(
227
229
  )
228
230
 
229
231
  data4 = (
230
- data3.group_by("_date_index")
232
+ data3
233
+ .group_by("_date_index")
231
234
  .agg(
232
235
  col(f"_{datetime}_index").min().alias(f"{datetime}_index_min"),
233
236
  (col(f"_{datetime}_index").max() + 1).alias(f"{datetime}_index_max"),
@@ -513,27 +513,21 @@ class StreamCommandOutput:
513
513
 
514
514
  @property
515
515
  def return_code(self) -> int:
516
- return ensure_int(self.process.returncode) # skipif-not-windows
516
+ return ensure_int(self.process.returncode)
517
517
 
518
518
 
519
519
  async def stream_command(cmd: str, /) -> StreamCommandOutput:
520
520
  """Run a shell command asynchronously and stream its output in real time."""
521
- process = await create_subprocess_shell( # skipif-not-windows
522
- cmd, stdout=PIPE, stderr=PIPE
523
- )
524
- proc_stdout = ensure_not_none( # skipif-not-windows
525
- process.stdout, desc="process.stdout"
526
- )
527
- proc_stderr = ensure_not_none( # skipif-not-windows
528
- process.stderr, desc="process.stderr"
529
- )
530
- ret_stdout = StringIO() # skipif-not-windows
531
- ret_stderr = StringIO() # skipif-not-windows
532
- async with TaskGroup() as tg: # skipif-not-windows
521
+ process = await create_subprocess_shell(cmd, stdout=PIPE, stderr=PIPE)
522
+ proc_stdout = ensure_not_none(process.stdout, desc="process.stdout")
523
+ proc_stderr = ensure_not_none(process.stderr, desc="process.stderr")
524
+ ret_stdout = StringIO()
525
+ ret_stderr = StringIO()
526
+ async with TaskGroup() as tg:
533
527
  _ = tg.create_task(_stream_one(proc_stdout, stdout, ret_stdout))
534
528
  _ = tg.create_task(_stream_one(proc_stderr, stderr, ret_stderr))
535
- _ = await process.wait() # skipif-not-windows
536
- return StreamCommandOutput( # skipif-not-windows
529
+ _ = await process.wait()
530
+ return StreamCommandOutput(
537
531
  process=process, stdout=ret_stdout.getvalue(), stderr=ret_stderr.getvalue()
538
532
  )
539
533
 
@@ -542,7 +536,7 @@ async def _stream_one(
542
536
  input_: StreamReader, out_stream: TextIO, ret_stream: StringIO, /
543
537
  ) -> None:
544
538
  """Asynchronously read from a stream and write to the target output stream."""
545
- while True: # skipif-not-windows
539
+ while True:
546
540
  line = await input_.readline()
547
541
  if not line:
548
542
  break
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from collections.abc import Callable, Hashable, Iterable, Iterator, MutableSet
4
4
  from math import inf
5
5
  from time import monotonic
6
- from typing import TYPE_CHECKING, Any, override
6
+ from typing import TYPE_CHECKING, Any, cast, override
7
7
 
8
8
  import cachetools
9
9
  from cachetools.func import ttl_cache
@@ -100,11 +100,14 @@ def cache[F: Callable](
100
100
  typed_: bool = False,
101
101
  ) -> Callable[[F], F]:
102
102
  """Decorate a function with `max_size` and/or `ttl` settings."""
103
- return ttl_cache(
104
- maxsize=inf if max_size is None else max_size,
105
- ttl=inf if max_duration is None else max_duration.in_seconds(),
106
- timer=timer,
107
- typed=typed_,
103
+ return cast(
104
+ "F",
105
+ ttl_cache(
106
+ maxsize=max_size,
107
+ ttl=inf if max_duration is None else max_duration.in_seconds(),
108
+ timer=timer,
109
+ typed=typed_,
110
+ ),
108
111
  )
109
112
 
110
113