dycw-utilities 0.132.1__tar.gz → 0.132.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/PKG-INFO +1 -1
  2. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/pyproject.toml +2 -2
  3. dycw_utilities-0.132.2/src/tests/test_typed_settings.py +147 -0
  4. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/__init__.py +1 -1
  5. dycw_utilities-0.132.2/src/utilities/typed_settings.py +124 -0
  6. dycw_utilities-0.132.1/src/tests/test_typed_settings.py +0 -99
  7. dycw_utilities-0.132.1/src/utilities/typed_settings.py +0 -61
  8. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/.gitignore +0 -0
  9. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/LICENSE +0 -0
  10. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/README.md +0 -0
  11. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/__init__.py +0 -0
  12. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/conftest.py +0 -0
  13. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/__init__.py +0 -0
  14. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_missing/__init__.py +0 -0
  15. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_missing/module.py +0 -0
  16. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/__init__.py +0 -0
  17. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/outer_1.py +0 -0
  18. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/outer_2.py +0 -0
  19. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  20. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  21. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  22. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  23. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_without/__init__.py +0 -0
  24. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_without/module_1.py +0 -0
  25. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/package_without/module_2.py +0 -0
  26. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/standalone.py +0 -0
  27. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/modules/with_imports.py +0 -0
  28. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  29. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  30. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  31. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  32. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  33. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  34. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  35. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  36. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_aiolimiter.py +0 -0
  37. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_altair.py +0 -0
  38. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_asyncio.py +0 -0
  39. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_asyncio_classes/__init__.py +0 -0
  40. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_asyncio_classes/loopers.py +0 -0
  41. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_asyncio_classes/redis.py +0 -0
  42. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_atomicwrites.py +0 -0
  43. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_atools.py +0 -0
  44. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_cachetools.py +0 -0
  45. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_click.py +0 -0
  46. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_concurrent.py +0 -0
  47. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_contextlib.py +0 -0
  48. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_contextvars.py +0 -0
  49. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_cryptography.py +0 -0
  50. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_cvxpy.py +0 -0
  51. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_dataclasses.py +0 -0
  52. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_enum.py +0 -0
  53. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_errors.py +0 -0
  54. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_eventkit.py +0 -0
  55. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_fastapi.py +0 -0
  56. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_fpdf2.py +0 -0
  57. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_functions.py +0 -0
  58. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_functools.py +0 -0
  59. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_getpass.py +0 -0
  60. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_git.py +0 -0
  61. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_hashlib.py +0 -0
  62. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_http.py +0 -0
  63. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_hypothesis.py +0 -0
  64. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_importlib.py +0 -0
  65. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_inflect.py +0 -0
  66. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_ipython.py +0 -0
  67. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_iterables.py +0 -0
  68. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_jupyter.py +0 -0
  69. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_libcst.py +0 -0
  70. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_lightweight_charts.py +0 -0
  71. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_logging.py +0 -0
  72. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_luigi.py +0 -0
  73. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_math.py +0 -0
  74. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_memory_profiler.py +0 -0
  75. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_modules.py +0 -0
  76. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_more_itertools.py +0 -0
  77. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_numpy.py +0 -0
  78. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_objects/__init__.py +0 -0
  79. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_objects/objects.py +0 -0
  80. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_operator.py +0 -0
  81. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_optuna.py +0 -0
  82. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_orjson.py +0 -0
  83. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_os.py +0 -0
  84. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_parse.py +0 -0
  85. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pathlib.py +0 -0
  86. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_period.py +0 -0
  87. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pickle.py +0 -0
  88. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_platform.py +0 -0
  89. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_polars.py +0 -0
  90. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_polars_ols.py +0 -0
  91. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pottery.py +0 -0
  92. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pqdm.py +0 -0
  93. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_psutil.py +0 -0
  94. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pydantic.py +0 -0
  95. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pyinstrument.py +0 -0
  96. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pyrsistent.py +0 -0
  97. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pytest.py +0 -0
  98. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_pytest_regressions.py +0 -0
  99. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_python_dotenv.py +0 -0
  100. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_random.py +0 -0
  101. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_re.py +0 -0
  102. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_redis.py +0 -0
  103. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_reprlib.py +0 -0
  104. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_scipy.py +0 -0
  105. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_sentinel.py +0 -0
  106. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_shelve.py +0 -0
  107. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_slack_sdk.py +0 -0
  108. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_socket.py +0 -0
  109. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_sqlalchemy.py +0 -0
  110. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_sqlalchemy_polars.py +0 -0
  111. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_statsmodel.py +0 -0
  112. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_streamlit.py +0 -0
  113. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_string.py +0 -0
  114. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_tempfile.py +0 -0
  115. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_text.py +0 -0
  116. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_threading.py +0 -0
  117. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_timer.py +0 -0
  118. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_traceback.py +0 -0
  119. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_types.py +0 -0
  120. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_typing.py +0 -0
  121. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_typing_funcs/__init__.py +0 -0
  122. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_typing_funcs/no_future.py +0 -0
  123. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_typing_funcs/with_future.py +0 -0
  124. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_tzdata.py +0 -0
  125. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_tzlocal.py +0 -0
  126. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_uuid.py +0 -0
  127. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_version.py +0 -0
  128. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_warnings.py +0 -0
  129. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_whenever.py +0 -0
  130. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_zipfile.py +0 -0
  131. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/tests/test_zoneinfo.py +0 -0
  132. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/aiolimiter.py +0 -0
  133. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/altair.py +0 -0
  134. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/asyncio.py +0 -0
  135. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/atomicwrites.py +0 -0
  136. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/atools.py +0 -0
  137. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/cachetools.py +0 -0
  138. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/click.py +0 -0
  139. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/concurrent.py +0 -0
  140. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/contextlib.py +0 -0
  141. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/contextvars.py +0 -0
  142. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/cryptography.py +0 -0
  143. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/cvxpy.py +0 -0
  144. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/dataclasses.py +0 -0
  145. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/enum.py +0 -0
  146. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/errors.py +0 -0
  147. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/eventkit.py +0 -0
  148. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/fastapi.py +0 -0
  149. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/fpdf2.py +0 -0
  150. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/functions.py +0 -0
  151. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/functools.py +0 -0
  152. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/getpass.py +0 -0
  153. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/git.py +0 -0
  154. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/hashlib.py +0 -0
  155. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/http.py +0 -0
  156. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/hypothesis.py +0 -0
  157. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/importlib.py +0 -0
  158. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/inflect.py +0 -0
  159. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/ipython.py +0 -0
  160. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/iterables.py +0 -0
  161. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/jupyter.py +0 -0
  162. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/libcst.py +0 -0
  163. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/lightweight_charts.py +0 -0
  164. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/logging.py +0 -0
  165. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/luigi.py +0 -0
  166. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/math.py +0 -0
  167. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/memory_profiler.py +0 -0
  168. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/modules.py +0 -0
  169. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/more_itertools.py +0 -0
  170. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/numpy.py +0 -0
  171. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/operator.py +0 -0
  172. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/optuna.py +0 -0
  173. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/orjson.py +0 -0
  174. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/os.py +0 -0
  175. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/parse.py +0 -0
  176. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pathlib.py +0 -0
  177. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/period.py +0 -0
  178. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pickle.py +0 -0
  179. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/platform.py +0 -0
  180. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/polars.py +0 -0
  181. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/polars_ols.py +0 -0
  182. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pottery.py +0 -0
  183. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pqdm.py +0 -0
  184. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/psutil.py +0 -0
  185. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/py.typed +0 -0
  186. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pydantic.py +0 -0
  187. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pyinstrument.py +0 -0
  188. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pyrsistent.py +0 -0
  189. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pytest.py +0 -0
  190. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/pytest_regressions.py +0 -0
  191. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/python_dotenv.py +0 -0
  192. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/random.py +0 -0
  193. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/re.py +0 -0
  194. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/redis.py +0 -0
  195. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/reprlib.py +0 -0
  196. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/scipy.py +0 -0
  197. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/sentinel.py +0 -0
  198. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/shelve.py +0 -0
  199. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/slack_sdk.py +0 -0
  200. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/socket.py +0 -0
  201. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/sqlalchemy.py +0 -0
  202. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/sqlalchemy_polars.py +0 -0
  203. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/statsmodels.py +0 -0
  204. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/streamlit.py +0 -0
  205. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/string.py +0 -0
  206. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/tempfile.py +0 -0
  207. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/text.py +0 -0
  208. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/threading.py +0 -0
  209. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/timer.py +0 -0
  210. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/traceback.py +0 -0
  211. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/types.py +0 -0
  212. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/typing.py +0 -0
  213. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/tzdata.py +0 -0
  214. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/tzlocal.py +0 -0
  215. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/uuid.py +0 -0
  216. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/version.py +0 -0
  217. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/warnings.py +0 -0
  218. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/whenever.py +0 -0
  219. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/zipfile.py +0 -0
  220. {dycw_utilities-0.132.1 → dycw_utilities-0.132.2}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.132.1
3
+ Version: 0.132.2
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -94,7 +94,7 @@ dependencies = [
94
94
  name = "dycw-utilities"
95
95
  readme = "README.md"
96
96
  requires-python = ">= 3.12"
97
- version = "0.132.1"
97
+ version = "0.132.2"
98
98
 
99
99
  [project.optional-dependencies]
100
100
  logging = [
@@ -121,7 +121,7 @@ test = [
121
121
  # bump-my-version
122
122
  [tool.bumpversion]
123
123
  allow_dirty = true
124
- current_version = "0.132.1"
124
+ current_version = "0.132.2"
125
125
 
126
126
  [[tool.bumpversion.files]]
127
127
  filename = "src/utilities/__init__.py"
@@ -0,0 +1,147 @@
1
+ from collections.abc import Callable
2
+ from dataclasses import dataclass
3
+ from ipaddress import IPv4Address, IPv6Address
4
+ from pathlib import Path
5
+ from typing import TypeVar
6
+
7
+ import typed_settings
8
+ from hypothesis import given
9
+ from hypothesis.strategies import DataObject, SearchStrategy, data, ip_addresses, tuples
10
+ from pytest import mark, param, raises
11
+ from typed_settings import EnvLoader, FileLoader, TomlFormat
12
+ from whenever import (
13
+ Date,
14
+ DateDelta,
15
+ DateTimeDelta,
16
+ PlainDateTime,
17
+ Time,
18
+ TimeDelta,
19
+ ZonedDateTime,
20
+ )
21
+
22
+ from utilities.hypothesis import (
23
+ date_deltas,
24
+ date_time_deltas,
25
+ dates,
26
+ plain_datetimes,
27
+ temp_paths,
28
+ text_ascii,
29
+ time_deltas,
30
+ times,
31
+ zoned_datetimes,
32
+ )
33
+ from utilities.os import temp_environ
34
+ from utilities.text import strip_and_dedent
35
+ from utilities.typed_settings import (
36
+ ExtendedTSConverter,
37
+ LoadSettingsError,
38
+ load_settings,
39
+ )
40
+
41
+ app_names = text_ascii(min_size=1).map(str.lower)
42
+
43
+
44
+ _T = TypeVar("_T")
45
+
46
+
47
+ class TestExtendedTSConverter:
48
+ @given(data=data(), root=temp_paths(), app_name=app_names)
49
+ @mark.parametrize(
50
+ ("test_cls", "strategy", "serialize"),
51
+ [
52
+ param(Date, dates(), Date.format_common_iso),
53
+ param(DateDelta, date_deltas(parsable=True), DateDelta.format_common_iso),
54
+ param(
55
+ DateTimeDelta,
56
+ date_time_deltas(parsable=True),
57
+ DateTimeDelta.format_common_iso,
58
+ ),
59
+ param(IPv4Address, ip_addresses(v=4), IPv4Address),
60
+ param(IPv6Address, ip_addresses(v=6), IPv6Address),
61
+ param(PlainDateTime, plain_datetimes(), PlainDateTime.format_common_iso),
62
+ param(Time, times(), Time.format_common_iso),
63
+ param(TimeDelta, time_deltas(), TimeDelta.format_common_iso),
64
+ param(ZonedDateTime, zoned_datetimes(), ZonedDateTime.format_common_iso),
65
+ ],
66
+ )
67
+ def test_main(
68
+ self,
69
+ *,
70
+ data: DataObject,
71
+ root: Path,
72
+ app_name: str,
73
+ test_cls: type[_T],
74
+ strategy: SearchStrategy[_T],
75
+ serialize: Callable[[_T], str],
76
+ ) -> None:
77
+ default, value = data.draw(tuples(strategy, strategy))
78
+
79
+ @dataclass(frozen=True, kw_only=True, slots=True)
80
+ class Settings:
81
+ value: test_cls = default # pyright: ignore[reportInvalidTypeForm]
82
+
83
+ settings_default = typed_settings.load_settings(
84
+ Settings, loaders=[], converter=ExtendedTSConverter()
85
+ )
86
+ assert settings_default.value == default
87
+ file = Path(root, "file.toml")
88
+ _ = file.write_text(
89
+ strip_and_dedent(f"""
90
+ [{app_name}]
91
+ value = '{serialize(value)}'
92
+ """)
93
+ )
94
+ settings_loaded = typed_settings.load_settings(
95
+ Settings,
96
+ loaders=[
97
+ FileLoader(formats={"*.toml": TomlFormat(app_name)}, files=[file])
98
+ ],
99
+ converter=ExtendedTSConverter(),
100
+ )
101
+ assert settings_loaded.value == value
102
+
103
+
104
+ class TestLoadSettings:
105
+ @given(root=temp_paths(), datetime=zoned_datetimes())
106
+ def test_main(self, *, root: Path, datetime: ZonedDateTime) -> None:
107
+ @dataclass(frozen=True, kw_only=True, slots=True)
108
+ class Settings:
109
+ datetime: ZonedDateTime
110
+
111
+ file = Path(root, "file.toml")
112
+ _ = file.write_text("")
113
+ _ = file.write_text(
114
+ strip_and_dedent(f"""
115
+ [app_name]
116
+ datetime = '{datetime.format_common_iso()}'
117
+ """)
118
+ )
119
+ settings = load_settings(
120
+ Settings, "app_name", filenames="file.toml", start_dir=root
121
+ )
122
+ assert settings.datetime == datetime
123
+
124
+ @given(
125
+ prefix=app_names.map(lambda text: f"TEST_{text}".upper()),
126
+ datetime=zoned_datetimes(),
127
+ )
128
+ def test_loaders(self, *, prefix: str, datetime: ZonedDateTime) -> None:
129
+ key = f"{prefix}__DATETIME"
130
+
131
+ @dataclass(frozen=True, kw_only=True, slots=True)
132
+ class Settings:
133
+ datetime: ZonedDateTime
134
+
135
+ with temp_environ({key: datetime.format_common_iso()}):
136
+ settings = load_settings(
137
+ Settings, "app_name", loaders=[EnvLoader(prefix=f"{prefix}__")]
138
+ )
139
+ assert settings.datetime == datetime
140
+
141
+ @mark.parametrize("app_name", [param("app_"), param("app1"), param("app__name")])
142
+ def test_error(self, *, app_name: str) -> None:
143
+ @dataclass(frozen=True, kw_only=True, slots=True)
144
+ class Settings: ...
145
+
146
+ with raises(LoadSettingsError, match="Invalid app name; got '.+'"):
147
+ _ = load_settings(Settings, app_name)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.132.1"
3
+ __version__ = "0.132.2"
@@ -0,0 +1,124 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from ipaddress import IPv4Address, IPv6Address
5
+ from pathlib import Path
6
+ from re import search
7
+ from typing import TYPE_CHECKING, Any, TypeVar, override
8
+
9
+ import typed_settings
10
+ from typed_settings import EnvLoader, FileLoader, find
11
+ from typed_settings.converters import TSConverter
12
+ from typed_settings.loaders import TomlFormat
13
+ from whenever import (
14
+ Date,
15
+ DateDelta,
16
+ DateTimeDelta,
17
+ PlainDateTime,
18
+ Time,
19
+ TimeDelta,
20
+ ZonedDateTime,
21
+ )
22
+
23
+ from utilities.iterables import always_iterable
24
+
25
+ if TYPE_CHECKING:
26
+ from collections.abc import Callable
27
+
28
+ from typed_settings.loaders import Loader
29
+ from typed_settings.processors import Processor
30
+
31
+ from utilities.types import MaybeIterable, PathLike
32
+
33
+
34
+ _T = TypeVar("_T")
35
+
36
+
37
+ ##
38
+
39
+
40
+ class ExtendedTSConverter(TSConverter):
41
+ """An extension of the TSConverter for custom types."""
42
+
43
+ @override
44
+ def __init__(
45
+ self,
46
+ *,
47
+ resolve_paths: bool = True,
48
+ strlist_sep: str | Callable[[str], list] | None = ":",
49
+ ) -> None:
50
+ super().__init__(resolve_paths=resolve_paths, strlist_sep=strlist_sep)
51
+ cases: list[tuple[type[Any], Callable[..., Any]]] = [
52
+ (Date, Date.parse_common_iso),
53
+ (DateDelta, DateDelta.parse_common_iso),
54
+ (DateTimeDelta, DateTimeDelta.parse_common_iso),
55
+ (IPv4Address, IPv4Address),
56
+ (IPv6Address, IPv6Address),
57
+ (PlainDateTime, PlainDateTime.parse_common_iso),
58
+ (Time, Time.parse_common_iso),
59
+ (TimeDelta, TimeDelta.parse_common_iso),
60
+ (ZonedDateTime, ZonedDateTime.parse_common_iso),
61
+ ]
62
+ extras = {cls: _make_converter(cls, func) for cls, func in cases}
63
+ self.scalar_converters |= extras
64
+
65
+
66
+ def _make_converter(
67
+ cls: type[_T], parser: Callable[[str], _T], /
68
+ ) -> Callable[[Any, type[Any]], Any]:
69
+ def hook(value: _T | str, _: type[_T] = cls, /) -> Any:
70
+ if not isinstance(value, (cls, str)): # pragma: no cover
71
+ msg = f"Invalid type {type(value).__name__!r}; expected '{cls.__name__}' or 'str'"
72
+ raise TypeError(msg)
73
+ if isinstance(value, str):
74
+ return parser(value)
75
+ return value
76
+
77
+ return hook
78
+
79
+
80
+ ##
81
+
82
+ _BASE_DIR: Path = Path()
83
+
84
+
85
+ def load_settings(
86
+ cls: type[_T],
87
+ app_name: str,
88
+ /,
89
+ *,
90
+ filenames: MaybeIterable[str] = "settings.toml",
91
+ start_dir: PathLike | None = None,
92
+ loaders: MaybeIterable[Loader] | None = None,
93
+ processors: MaybeIterable[Processor] = (),
94
+ base_dir: Path = _BASE_DIR,
95
+ ) -> _T:
96
+ if not search(r"^[A-Za-z]+(?:_[A-Za-z]+)*$", app_name):
97
+ raise LoadSettingsError(appname=app_name)
98
+ filenames_use = list(always_iterable(filenames))
99
+ start_dir_use = None if start_dir is None else Path(start_dir)
100
+ files = [find(filename, start_dir=start_dir_use) for filename in filenames_use]
101
+ file_loader = FileLoader(formats={"*.toml": TomlFormat(app_name)}, files=files)
102
+ env_loader = EnvLoader(f"{app_name.upper()}__", nested_delimiter="__")
103
+ loaders_use: list[Loader] = [file_loader, env_loader]
104
+ if loaders is not None:
105
+ loaders_use.extend(always_iterable(loaders))
106
+ return typed_settings.load_settings(
107
+ cls,
108
+ loaders_use,
109
+ processors=list(always_iterable(processors)),
110
+ converter=ExtendedTSConverter(),
111
+ base_dir=base_dir,
112
+ )
113
+
114
+
115
+ @dataclass(kw_only=True, slots=True)
116
+ class LoadSettingsError(Exception):
117
+ appname: str
118
+
119
+ @override
120
+ def __str__(self) -> str:
121
+ return f"Invalid app name; got {self.appname!r}"
122
+
123
+
124
+ __all__ = ["ExtendedTSConverter", "LoadSettingsError", "load_settings"]
@@ -1,99 +0,0 @@
1
- from collections.abc import Callable
2
- from dataclasses import dataclass
3
- from operator import eq
4
- from pathlib import Path
5
- from typing import TypeVar
6
-
7
- from hypothesis import given
8
- from hypothesis.strategies import DataObject, SearchStrategy, data, tuples
9
- from pytest import mark, param
10
- from typed_settings import FileLoader, TomlFormat, load_settings
11
- from whenever import (
12
- Date,
13
- DateDelta,
14
- DateTimeDelta,
15
- PlainDateTime,
16
- Time,
17
- TimeDelta,
18
- ZonedDateTime,
19
- )
20
-
21
- from utilities.hypothesis import (
22
- date_deltas,
23
- date_time_deltas,
24
- dates,
25
- plain_datetimes,
26
- temp_paths,
27
- text_ascii,
28
- time_deltas,
29
- times,
30
- zoned_datetimes,
31
- )
32
- from utilities.typed_settings import ExtendedTSConverter
33
-
34
- app_names = text_ascii(min_size=1).map(str.lower)
35
-
36
-
37
- _T = TypeVar("_T")
38
-
39
-
40
- class TestExtendedTSConverter:
41
- @given(data=data(), root=temp_paths(), appname=text_ascii(min_size=1))
42
- @mark.parametrize(
43
- ("test_cls", "strategy", "serialize"),
44
- [
45
- param(Date, dates(), Date.format_common_iso),
46
- param(DateDelta, date_deltas(parsable=True), DateDelta.format_common_iso),
47
- param(
48
- DateTimeDelta,
49
- date_time_deltas(parsable=True),
50
- DateTimeDelta.format_common_iso,
51
- ),
52
- param(PlainDateTime, plain_datetimes(), PlainDateTime.format_common_iso),
53
- param(Time, times(), Time.format_common_iso),
54
- param(TimeDelta, time_deltas(), TimeDelta.format_common_iso),
55
- param(ZonedDateTime, zoned_datetimes(), ZonedDateTime.format_common_iso),
56
- ],
57
- )
58
- def test_main(
59
- self,
60
- *,
61
- data: DataObject,
62
- root: Path,
63
- appname: str,
64
- test_cls: type[_T],
65
- strategy: SearchStrategy[_T],
66
- serialize: Callable[[_T], str],
67
- ) -> None:
68
- default, value = data.draw(tuples(strategy, strategy))
69
- self._run_test(test_cls, default, root, appname, serialize, value, eq)
70
-
71
- def _run_test(
72
- self,
73
- test_cls: type[_T],
74
- default: _T,
75
- root: Path,
76
- appname: str,
77
- serialize: Callable[[_T], str],
78
- value: _T,
79
- equal: Callable[[_T, _T], bool],
80
- /,
81
- ) -> None:
82
- @dataclass(frozen=True, kw_only=True, slots=True)
83
- class Settings:
84
- value: test_cls = default # pyright: ignore[reportInvalidTypeForm]
85
-
86
- settings_default = load_settings(
87
- Settings, loaders=[], converter=ExtendedTSConverter()
88
- )
89
- assert settings_default.value == default
90
- _ = hash(settings_default)
91
- file = Path(root, "file.toml")
92
- with file.open(mode="w") as fh:
93
- _ = fh.write(f'[{appname}]\nvalue = "{serialize(value)}"')
94
- settings_loaded = load_settings(
95
- Settings,
96
- loaders=[FileLoader(formats={"*.toml": TomlFormat(appname)}, files=[file])],
97
- converter=ExtendedTSConverter(),
98
- )
99
- assert equal(settings_loaded.value, value)
@@ -1,61 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, TypeVar, override
4
-
5
- from typed_settings.converters import TSConverter
6
- from whenever import (
7
- Date,
8
- DateDelta,
9
- DateTimeDelta,
10
- PlainDateTime,
11
- Time,
12
- TimeDelta,
13
- ZonedDateTime,
14
- )
15
-
16
- if TYPE_CHECKING:
17
- from collections.abc import Callable
18
-
19
-
20
- _T = TypeVar("_T")
21
-
22
-
23
- class ExtendedTSConverter(TSConverter):
24
- """An extension of the TSConverter for custom types."""
25
-
26
- @override
27
- def __init__(
28
- self,
29
- *,
30
- resolve_paths: bool = True,
31
- strlist_sep: str | Callable[[str], list] | None = ":",
32
- ) -> None:
33
- super().__init__(resolve_paths=resolve_paths, strlist_sep=strlist_sep)
34
- cases: list[tuple[type[Any], Callable[..., Any]]] = [
35
- (Date, Date.parse_common_iso),
36
- (DateDelta, DateDelta.parse_common_iso),
37
- (DateTimeDelta, DateTimeDelta.parse_common_iso),
38
- (PlainDateTime, PlainDateTime.parse_common_iso),
39
- (Time, Time.parse_common_iso),
40
- (TimeDelta, TimeDelta.parse_common_iso),
41
- (ZonedDateTime, ZonedDateTime.parse_common_iso),
42
- ]
43
- extras = {cls: _make_converter(cls, func) for cls, func in cases}
44
- self.scalar_converters |= extras
45
-
46
-
47
- def _make_converter(
48
- cls: type[_T], parser: Callable[[str], _T], /
49
- ) -> Callable[[Any, type[Any]], Any]:
50
- def hook(value: _T | str, _: type[_T] = cls, /) -> Any:
51
- if not isinstance(value, (cls, str)): # pragma: no cover
52
- msg = f"Invalid type {type(value).__name__!r}; expected '{cls.__name__}' or 'str'"
53
- raise TypeError(msg)
54
- if isinstance(value, str):
55
- return parser(value)
56
- return value
57
-
58
- return hook
59
-
60
-
61
- __all__ = ["ExtendedTSConverter"]