dycw-utilities 0.138.3__tar.gz → 0.138.5__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 (216) hide show
  1. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/PKG-INFO +1 -1
  2. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/pyproject.toml +2 -2
  3. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pathlib.py +91 -21
  4. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/__init__.py +1 -1
  5. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pathlib.py +54 -9
  6. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pytest.py +2 -5
  7. dycw_utilities-0.138.3/src/tests/test_git.py +0 -27
  8. dycw_utilities-0.138.3/src/utilities/git.py +0 -40
  9. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/.gitignore +0 -0
  10. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/LICENSE +0 -0
  11. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/README.md +0 -0
  12. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/__init__.py +0 -0
  13. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/conftest.py +0 -0
  14. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/__init__.py +0 -0
  15. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_missing/__init__.py +0 -0
  16. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_missing/module.py +0 -0
  17. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/__init__.py +0 -0
  18. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/outer_1.py +0 -0
  19. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/outer_2.py +0 -0
  20. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  21. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  22. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  23. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  24. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_without/__init__.py +0 -0
  25. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_without/module_1.py +0 -0
  26. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/package_without/module_2.py +0 -0
  27. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/standalone.py +0 -0
  28. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/modules/with_imports.py +0 -0
  29. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  30. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  31. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  32. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  33. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  34. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  35. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  36. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  37. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_aiolimiter.py +0 -0
  38. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_altair.py +0 -0
  39. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_asyncio.py +0 -0
  40. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_asyncio_classes/__init__.py +0 -0
  41. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_asyncio_classes/loopers.py +0 -0
  42. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_asyncio_classes/redis.py +0 -0
  43. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_atomicwrites.py +0 -0
  44. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_atools.py +0 -0
  45. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_cachetools.py +0 -0
  46. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_click.py +0 -0
  47. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_concurrent.py +0 -0
  48. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_contextlib.py +0 -0
  49. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_contextvars.py +0 -0
  50. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_cryptography.py +0 -0
  51. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_cvxpy.py +0 -0
  52. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_dataclasses.py +0 -0
  53. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_enum.py +0 -0
  54. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_errors.py +0 -0
  55. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_eventkit.py +0 -0
  56. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_fastapi.py +0 -0
  57. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_fpdf2.py +0 -0
  58. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_functions.py +0 -0
  59. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_functools.py +0 -0
  60. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_getpass.py +0 -0
  61. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_hashlib.py +0 -0
  62. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_http.py +0 -0
  63. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_hypothesis.py +0 -0
  64. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_importlib.py +0 -0
  65. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_inflect.py +0 -0
  66. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_ipython.py +0 -0
  67. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_iterables.py +0 -0
  68. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_jupyter.py +0 -0
  69. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_libcst.py +0 -0
  70. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_lightweight_charts.py +0 -0
  71. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_logging.py +0 -0
  72. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_luigi.py +0 -0
  73. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_math.py +0 -0
  74. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_memory_profiler.py +0 -0
  75. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_modules.py +0 -0
  76. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_more_itertools.py +0 -0
  77. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_numpy.py +0 -0
  78. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_objects/__init__.py +0 -0
  79. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_objects/objects.py +0 -0
  80. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_operator.py +0 -0
  81. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_optuna.py +0 -0
  82. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_orjson.py +0 -0
  83. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_os.py +0 -0
  84. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_parse.py +0 -0
  85. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_period.py +0 -0
  86. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pickle.py +0 -0
  87. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_platform.py +0 -0
  88. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_polars.py +0 -0
  89. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_polars_ols.py +0 -0
  90. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pottery.py +0 -0
  91. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pqdm.py +0 -0
  92. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_psutil.py +0 -0
  93. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pydantic.py +0 -0
  94. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pyinstrument.py +0 -0
  95. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pytest.py +0 -0
  96. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_pytest_regressions.py +0 -0
  97. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_python_dotenv.py +0 -0
  98. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_random.py +0 -0
  99. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_re.py +0 -0
  100. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_redis.py +0 -0
  101. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_reprlib.py +0 -0
  102. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_scipy.py +0 -0
  103. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_sentinel.py +0 -0
  104. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_shelve.py +0 -0
  105. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_slack_sdk.py +0 -0
  106. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_socket.py +0 -0
  107. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_sqlalchemy.py +0 -0
  108. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_sqlalchemy_polars.py +0 -0
  109. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_statsmodels.py +0 -0
  110. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_streamlit.py +0 -0
  111. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_string.py +0 -0
  112. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_tempfile.py +0 -0
  113. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_text.py +0 -0
  114. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_threading.py +0 -0
  115. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_timer.py +0 -0
  116. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_traceback.py +0 -0
  117. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_typed_settings.py +0 -0
  118. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_types.py +0 -0
  119. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_typing.py +0 -0
  120. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_typing_funcs/__init__.py +0 -0
  121. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_typing_funcs/no_future.py +0 -0
  122. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_typing_funcs/with_future.py +0 -0
  123. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_tzdata.py +0 -0
  124. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_tzlocal.py +0 -0
  125. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_uuid.py +0 -0
  126. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_version.py +0 -0
  127. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_warnings.py +0 -0
  128. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_whenever.py +0 -0
  129. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_zipfile.py +0 -0
  130. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/tests/test_zoneinfo.py +0 -0
  131. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/aiolimiter.py +0 -0
  132. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/altair.py +0 -0
  133. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/asyncio.py +0 -0
  134. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/atomicwrites.py +0 -0
  135. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/atools.py +0 -0
  136. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/cachetools.py +0 -0
  137. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/click.py +0 -0
  138. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/concurrent.py +0 -0
  139. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/contextlib.py +0 -0
  140. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/contextvars.py +0 -0
  141. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/cryptography.py +0 -0
  142. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/cvxpy.py +0 -0
  143. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/dataclasses.py +0 -0
  144. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/enum.py +0 -0
  145. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/errors.py +0 -0
  146. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/eventkit.py +0 -0
  147. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/fastapi.py +0 -0
  148. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/fpdf2.py +0 -0
  149. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/functions.py +0 -0
  150. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/functools.py +0 -0
  151. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/getpass.py +0 -0
  152. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/hashlib.py +0 -0
  153. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/http.py +0 -0
  154. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/hypothesis.py +0 -0
  155. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/importlib.py +0 -0
  156. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/inflect.py +0 -0
  157. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/ipython.py +0 -0
  158. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/iterables.py +0 -0
  159. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/jupyter.py +0 -0
  160. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/libcst.py +0 -0
  161. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/lightweight_charts.py +0 -0
  162. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/logging.py +0 -0
  163. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/luigi.py +0 -0
  164. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/math.py +0 -0
  165. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/memory_profiler.py +0 -0
  166. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/modules.py +0 -0
  167. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/more_itertools.py +0 -0
  168. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/numpy.py +0 -0
  169. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/operator.py +0 -0
  170. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/optuna.py +0 -0
  171. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/orjson.py +0 -0
  172. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/os.py +0 -0
  173. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/parse.py +0 -0
  174. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/period.py +0 -0
  175. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pickle.py +0 -0
  176. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/platform.py +0 -0
  177. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/polars.py +0 -0
  178. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/polars_ols.py +0 -0
  179. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pottery.py +0 -0
  180. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pqdm.py +0 -0
  181. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/psutil.py +0 -0
  182. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/py.typed +0 -0
  183. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pydantic.py +0 -0
  184. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pyinstrument.py +0 -0
  185. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/pytest_regressions.py +0 -0
  186. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/python_dotenv.py +0 -0
  187. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/random.py +0 -0
  188. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/re.py +0 -0
  189. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/redis.py +0 -0
  190. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/reprlib.py +0 -0
  191. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/scipy.py +0 -0
  192. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/sentinel.py +0 -0
  193. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/shelve.py +0 -0
  194. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/slack_sdk.py +0 -0
  195. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/socket.py +0 -0
  196. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/sqlalchemy.py +0 -0
  197. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/sqlalchemy_polars.py +0 -0
  198. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/statsmodels.py +0 -0
  199. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/streamlit.py +0 -0
  200. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/string.py +0 -0
  201. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/tempfile.py +0 -0
  202. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/text.py +0 -0
  203. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/threading.py +0 -0
  204. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/timer.py +0 -0
  205. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/traceback.py +0 -0
  206. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/typed_settings.py +0 -0
  207. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/types.py +0 -0
  208. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/typing.py +0 -0
  209. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/tzdata.py +0 -0
  210. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/tzlocal.py +0 -0
  211. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/uuid.py +0 -0
  212. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/version.py +0 -0
  213. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/warnings.py +0 -0
  214. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/whenever.py +0 -0
  215. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/zipfile.py +0 -0
  216. {dycw_utilities-0.138.3 → dycw_utilities-0.138.5}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.138.3
3
+ Version: 0.138.5
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -105,7 +105,7 @@ dependencies = [
105
105
  name = "dycw-utilities"
106
106
  readme = "README.md"
107
107
  requires-python = ">= 3.12"
108
- version = "0.138.3"
108
+ version = "0.138.5"
109
109
 
110
110
  [project.optional-dependencies]
111
111
  logging = [
@@ -133,7 +133,7 @@ test = [
133
133
  # bump-my-version
134
134
  [tool.bumpversion]
135
135
  allow_dirty = true
136
- current_version = "0.138.3"
136
+ current_version = "0.138.5"
137
137
 
138
138
  [[tool.bumpversion.files]]
139
139
  filename = "src/utilities/__init__.py"
@@ -2,10 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
4
  from pathlib import Path
5
+ from shutil import copytree
5
6
  from typing import TYPE_CHECKING, Self
6
7
 
7
- from hypothesis import given, settings
8
- from hypothesis.strategies import integers, sets
8
+ from hypothesis import HealthCheck, given, settings
9
+ from hypothesis.strategies import DataObject, data, integers, sets
9
10
  from pytest import mark, param, raises
10
11
 
11
12
  from tests.conftest import SKIPIF_CI_AND_WINDOWS
@@ -17,13 +18,15 @@ from utilities.pathlib import (
17
18
  expand_path,
18
19
  get_path,
19
20
  get_root,
21
+ is_sub_path,
20
22
  list_dir,
21
23
  temp_cwd,
22
24
  )
23
25
  from utilities.sentinel import Sentinel, sentinel
26
+ from utilities.tempfile import TemporaryDirectory
24
27
 
25
28
  if TYPE_CHECKING:
26
- from utilities.types import MaybeCallablePathLike
29
+ from utilities.types import MaybeCallablePathLike, PathLike
27
30
 
28
31
 
29
32
  class TestEnsureSuffix:
@@ -98,34 +101,101 @@ class TestGetPath:
98
101
 
99
102
 
100
103
  class TestGetRoot:
101
- @given(repo=git_repos())
102
- @settings(max_examples=1)
103
- def test_git(self, *, repo: Path) -> None:
104
- root = get_root(path=repo)
104
+ @given(data=data(), repo=git_repos())
105
+ @settings(
106
+ max_examples=1, suppress_health_check={HealthCheck.function_scoped_fixture}
107
+ )
108
+ def test_git_dir(self, *, data: DataObject, repo: Path) -> None:
109
+ path = repo.joinpath(data.draw(paths()))
110
+ path.mkdir(parents=True, exist_ok=True)
111
+ root = get_root(path=path)
105
112
  expected = repo.resolve()
106
113
  assert root == expected
107
114
 
108
- @given(root=temp_paths())
109
- @settings(max_examples=1)
110
- def test_envrc(self, *, root: Path) -> None:
111
- root.joinpath(".envrc").touch()
112
- result = get_root(path=root)
113
- assert result == root
114
-
115
- @given(root=temp_paths())
116
- @settings(max_examples=1)
117
- def test_envrc_from_inside(self, *, root: Path) -> None:
118
- root.joinpath(".envrc").touch()
119
- path = root.joinpath("foo", "bar", "baz")
120
- path.mkdir(parents=True)
115
+ @given(data=data(), repo=git_repos())
116
+ @settings(
117
+ max_examples=1, suppress_health_check={HealthCheck.function_scoped_fixture}
118
+ )
119
+ def test_git_file(self, *, data: DataObject, repo: Path) -> None:
120
+ path = repo.joinpath(data.draw(paths(min_depth=1)))
121
+ path.touch()
122
+ root = get_root(path=path)
123
+ expected = repo.resolve()
124
+ assert root == expected
125
+
126
+ @given(data=data())
127
+ @settings(
128
+ max_examples=1, suppress_health_check={HealthCheck.function_scoped_fixture}
129
+ )
130
+ def test_envrc(self, *, data: DataObject, tmp_path: Path) -> None:
131
+ tmp_path.joinpath(".envrc").touch()
132
+ path = tmp_path.joinpath(data.draw(paths()))
121
133
  result = get_root(path=path)
122
- assert result == root
134
+ expected = tmp_path.resolve()
135
+ assert result == expected
136
+
137
+ @given(data=data(), repo=git_repos())
138
+ @settings(
139
+ max_examples=1, suppress_health_check={HealthCheck.function_scoped_fixture}
140
+ )
141
+ def test_git_and_envrc(self, *, data: DataObject, repo: Path) -> None:
142
+ repo.joinpath(".envrc").touch()
143
+ path = repo.joinpath(data.draw(paths()))
144
+ root = get_root(path=path)
145
+ expected = repo.resolve()
146
+ assert root == expected
147
+
148
+ @given(data=data(), repo=git_repos())
149
+ @settings(
150
+ max_examples=1, suppress_health_check={HealthCheck.function_scoped_fixture}
151
+ )
152
+ def test_git_with_envrc_inside(self, *, data: DataObject, repo: Path) -> None:
153
+ path = repo.joinpath(data.draw(paths(min_depth=1)))
154
+ path.mkdir(parents=True)
155
+ path.joinpath(".envrc").touch()
156
+ root = get_root(path=path)
157
+ expected = path.resolve()
158
+ assert root == expected
159
+
160
+ @given(data=data(), repo=git_repos())
161
+ @settings(
162
+ max_examples=1, suppress_health_check={HealthCheck.function_scoped_fixture}
163
+ )
164
+ def test_envrc_with_git_inside(self, *, data: DataObject, repo: Path) -> None:
165
+ with TemporaryDirectory() as temp:
166
+ temp.joinpath(".envrc").touch()
167
+ path = temp.joinpath(data.draw(paths(min_depth=1)))
168
+ _ = copytree(repo, path)
169
+ root = get_root(path=path)
170
+ expected = path.resolve()
171
+ assert root == expected
123
172
 
124
173
  def test_error(self, *, tmp_path: Path) -> None:
125
174
  with raises(GetRootError, match="Unable to determine root from '.*'"):
126
175
  _ = get_root(path=tmp_path)
127
176
 
128
177
 
178
+ class TestIsSubPath:
179
+ @mark.parametrize(
180
+ ("x", "y", "strict", "expected"),
181
+ [
182
+ param("foo", "foo", False, True),
183
+ param("foo", "foo", True, False),
184
+ param("foo/bar", "foo", False, True),
185
+ param("foo/bar", "foo", True, True),
186
+ param("foo/bar", "foo/baz", False, False),
187
+ param("foo/bar", "foo/baz", True, False),
188
+ param("foo", "foo/bar", False, False),
189
+ param("foo", "foo/bar", True, False),
190
+ ],
191
+ )
192
+ def test_main(
193
+ self, *, x: PathLike, y: PathLike, strict: bool, expected: bool
194
+ ) -> None:
195
+ result = is_sub_path(x, y, strict=strict)
196
+ assert result is expected
197
+
198
+
129
199
  class TestListDir:
130
200
  @given(root=temp_paths(), nums=sets(integers(0, 100), max_size=10))
131
201
  def test_main(self, *, root: Path, nums: set[str]) -> None:
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.138.3"
3
+ __version__ = "0.138.5"
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import Callable
4
- from contextlib import contextmanager, suppress
4
+ from contextlib import contextmanager
5
5
  from dataclasses import dataclass
6
6
  from itertools import chain
7
7
  from os import chdir
@@ -11,6 +11,7 @@ from re import IGNORECASE, search
11
11
  from subprocess import PIPE, CalledProcessError, check_output
12
12
  from typing import TYPE_CHECKING, assert_never, overload, override
13
13
 
14
+ from utilities.errors import ImpossibleCaseError
14
15
  from utilities.sentinel import Sentinel, sentinel
15
16
 
16
17
  if TYPE_CHECKING:
@@ -73,23 +74,50 @@ def get_path(
73
74
  def get_root(*, path: MaybeCallablePathLike | None = None) -> Path:
74
75
  """Get the root of a path."""
75
76
  path = get_path(path=path)
77
+ path_dir = path.parent if path.is_file() else path
76
78
  try:
77
79
  output = check_output(
78
- ["git", "rev-parse", "--show-toplevel"], stderr=PIPE, cwd=path, text=True
80
+ ["git", "rev-parse", "--show-toplevel"],
81
+ stderr=PIPE,
82
+ cwd=path_dir,
83
+ text=True,
79
84
  )
80
85
  except CalledProcessError as error:
81
86
  # newer versions of git report "Not a git repository", whilst older
82
87
  # versions report "not a git repository"
83
88
  if not search("fatal: not a git repository", error.stderr, flags=IGNORECASE):
84
89
  raise # pragma: no cover
90
+ root_git = None
85
91
  else:
86
- return Path(output.strip("\n"))
87
- all_paths = list(chain([path], path.parents))
88
- with suppress(StopIteration):
89
- return next(
90
- p for p in all_paths if any(p_i.name == ".envrc" for p_i in p.iterdir())
92
+ root_git = Path(output.strip("\n")).resolve()
93
+ all_paths = list(chain([path_dir], path_dir.parents))
94
+ try:
95
+ root_envrc = next(
96
+ p.resolve()
97
+ for p in all_paths
98
+ if any(p_i.name == ".envrc" for p_i in p.iterdir())
91
99
  )
92
- raise GetRootError(path=path)
100
+ except StopIteration:
101
+ root_envrc = None
102
+ match root_git, root_envrc:
103
+ case None, None:
104
+ raise GetRootError(path=path)
105
+ case Path(), None:
106
+ return root_git
107
+ case None, Path():
108
+ return root_envrc
109
+ case Path(), Path():
110
+ if root_git == root_envrc:
111
+ return root_git
112
+ if is_sub_path(root_git, root_envrc, strict=True):
113
+ return root_git
114
+ if is_sub_path(root_envrc, root_git, strict=True):
115
+ return root_envrc
116
+ raise ImpossibleCaseError( # pragma: no cover
117
+ case=[f"{root_git=}", f"{root_envrc=}"]
118
+ )
119
+ case _ as never:
120
+ assert_never(never)
93
121
 
94
122
 
95
123
  @dataclass(kw_only=True, slots=True)
@@ -104,6 +132,15 @@ class GetRootError(Exception):
104
132
  ##
105
133
 
106
134
 
135
+ def is_sub_path(x: PathLike, y: PathLike, /, *, strict: bool = False) -> bool:
136
+ """Check if a path is a sub path of another."""
137
+ x, y = [Path(i).resolve() for i in [x, y]]
138
+ return x.is_relative_to(y) and not (strict and y.is_relative_to(x))
139
+
140
+
141
+ ##
142
+
143
+
107
144
  def list_dir(path: PathLike, /) -> Sequence[Path]:
108
145
  """List the contents of a directory."""
109
146
  return sorted(Path(path).iterdir())
@@ -123,4 +160,12 @@ def temp_cwd(path: PathLike, /) -> Iterator[None]:
123
160
  chdir(prev)
124
161
 
125
162
 
126
- __all__ = ["PWD", "ensure_suffix", "expand_path", "get_path", "list_dir", "temp_cwd"]
163
+ __all__ = [
164
+ "PWD",
165
+ "ensure_suffix",
166
+ "expand_path",
167
+ "get_path",
168
+ "is_sub_path",
169
+ "list_dir",
170
+ "temp_cwd",
171
+ ]
@@ -12,9 +12,8 @@ from whenever import ZonedDateTime
12
12
 
13
13
  from utilities.atomicwrites import writer
14
14
  from utilities.functools import cache
15
- from utilities.git import get_repo_root
16
15
  from utilities.hashlib import md5_hash
17
- from utilities.pathlib import ensure_suffix
16
+ from utilities.pathlib import ensure_suffix, get_root
18
17
  from utilities.platform import (
19
18
  IS_LINUX,
20
19
  IS_MAC,
@@ -241,9 +240,7 @@ def _skipif_recent(*, root: PathLike | None = None, delta: TimeDelta = SECOND) -
241
240
 
242
241
  def _get_path(*, root: PathLike | None = None) -> Path:
243
242
  if root is None:
244
- root_use = get_repo_root().joinpath( # pragma: no cover
245
- ".pytest_cache", "throttle"
246
- )
243
+ root_use = get_root().joinpath(".pytest_cache", "throttle") # pragma: no cover
247
244
  else:
248
245
  root_use = root
249
246
  return Path(root_use, _md5_hash_cached(_get_name()))
@@ -1,27 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- from hypothesis import given, settings
6
- from pytest import raises
7
-
8
- from utilities.git import GetRepoRootError, get_repo_root
9
- from utilities.hypothesis import git_repos
10
-
11
- if TYPE_CHECKING:
12
- from pathlib import Path
13
-
14
-
15
- class TestGetRepoRoot:
16
- @given(repo=git_repos())
17
- @settings(max_examples=1)
18
- def test_main(self, *, repo: Path) -> None:
19
- root = get_repo_root(path=repo)
20
- expected = repo.resolve()
21
- assert root == expected
22
-
23
- def test_error(self, *, tmp_path: Path) -> None:
24
- with raises(
25
- GetRepoRootError, match="Path is not part of a `git` repository: .*"
26
- ):
27
- _ = get_repo_root(path=tmp_path)
@@ -1,40 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from pathlib import Path
5
- from re import IGNORECASE, search
6
- from subprocess import PIPE, CalledProcessError, check_output
7
- from typing import TYPE_CHECKING, override
8
-
9
- from utilities.pathlib import PWD
10
-
11
- if TYPE_CHECKING:
12
- from utilities.types import PathLike
13
-
14
-
15
- def get_repo_root(*, path: PathLike = PWD) -> Path:
16
- """Get the repo root."""
17
- try:
18
- output = check_output(
19
- ["git", "rev-parse", "--show-toplevel"], stderr=PIPE, cwd=path, text=True
20
- )
21
- except CalledProcessError as error:
22
- # newer versions of git report "Not a git repository", whilst older
23
- # versions report "not a git repository"
24
- if search("fatal: not a git repository", error.stderr, flags=IGNORECASE):
25
- raise GetRepoRootError(cwd=path) from error
26
- raise # pragma: no cover
27
- else:
28
- return Path(output.strip("\n"))
29
-
30
-
31
- @dataclass(kw_only=True, slots=True)
32
- class GetRepoRootError(Exception):
33
- cwd: PathLike
34
-
35
- @override
36
- def __str__(self) -> str:
37
- return f"Path is not part of a `git` repository: {self.cwd}"
38
-
39
-
40
- __all__ = ["GetRepoRootError", "get_repo_root"]