dycw-utilities 0.132.2__tar.gz → 0.132.4__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 (218) hide show
  1. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/PKG-INFO +1 -2
  2. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/pyproject.toml +82 -71
  3. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/conftest.py +2 -1
  4. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_click.py +5 -0
  5. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_parse.py +14 -0
  6. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/__init__.py +1 -1
  7. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/click.py +58 -0
  8. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/parse.py +13 -8
  9. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/types.py +8 -0
  10. dycw_utilities-0.132.2/src/tests/test_pyrsistent.py +0 -49
  11. dycw_utilities-0.132.2/src/utilities/pyrsistent.py +0 -89
  12. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/.gitignore +0 -0
  13. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/LICENSE +0 -0
  14. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/README.md +0 -0
  15. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/__init__.py +0 -0
  16. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/__init__.py +0 -0
  17. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_missing/__init__.py +0 -0
  18. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_missing/module.py +0 -0
  19. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/__init__.py +0 -0
  20. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/outer_1.py +0 -0
  21. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/outer_2.py +0 -0
  22. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  23. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  24. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  25. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  26. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_without/__init__.py +0 -0
  27. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_without/module_1.py +0 -0
  28. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/package_without/module_2.py +0 -0
  29. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/standalone.py +0 -0
  30. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/modules/with_imports.py +0 -0
  31. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  32. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  33. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  34. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  35. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  36. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  37. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  38. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  39. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_aiolimiter.py +0 -0
  40. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_altair.py +0 -0
  41. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_asyncio.py +0 -0
  42. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_asyncio_classes/__init__.py +0 -0
  43. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_asyncio_classes/loopers.py +0 -0
  44. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_asyncio_classes/redis.py +0 -0
  45. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_atomicwrites.py +0 -0
  46. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_atools.py +0 -0
  47. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_cachetools.py +0 -0
  48. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_concurrent.py +0 -0
  49. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_contextlib.py +0 -0
  50. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_contextvars.py +0 -0
  51. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_cryptography.py +0 -0
  52. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_cvxpy.py +0 -0
  53. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_dataclasses.py +0 -0
  54. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_enum.py +0 -0
  55. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_errors.py +0 -0
  56. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_eventkit.py +0 -0
  57. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_fastapi.py +0 -0
  58. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_fpdf2.py +0 -0
  59. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_functions.py +0 -0
  60. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_functools.py +0 -0
  61. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_getpass.py +0 -0
  62. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_git.py +0 -0
  63. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_hashlib.py +0 -0
  64. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_http.py +0 -0
  65. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_hypothesis.py +0 -0
  66. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_importlib.py +0 -0
  67. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_inflect.py +0 -0
  68. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_ipython.py +0 -0
  69. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_iterables.py +0 -0
  70. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_jupyter.py +0 -0
  71. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_libcst.py +0 -0
  72. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_lightweight_charts.py +0 -0
  73. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_logging.py +0 -0
  74. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_luigi.py +0 -0
  75. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_math.py +0 -0
  76. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_memory_profiler.py +0 -0
  77. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_modules.py +0 -0
  78. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_more_itertools.py +0 -0
  79. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_numpy.py +0 -0
  80. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_objects/__init__.py +0 -0
  81. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_objects/objects.py +0 -0
  82. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_operator.py +0 -0
  83. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_optuna.py +0 -0
  84. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_orjson.py +0 -0
  85. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_os.py +0 -0
  86. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pathlib.py +0 -0
  87. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_period.py +0 -0
  88. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pickle.py +0 -0
  89. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_platform.py +0 -0
  90. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_polars.py +0 -0
  91. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_polars_ols.py +0 -0
  92. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pottery.py +0 -0
  93. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pqdm.py +0 -0
  94. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_psutil.py +0 -0
  95. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pydantic.py +0 -0
  96. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pyinstrument.py +0 -0
  97. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pytest.py +0 -0
  98. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_pytest_regressions.py +0 -0
  99. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_python_dotenv.py +0 -0
  100. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_random.py +0 -0
  101. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_re.py +0 -0
  102. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_redis.py +0 -0
  103. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_reprlib.py +0 -0
  104. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_scipy.py +0 -0
  105. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_sentinel.py +0 -0
  106. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_shelve.py +0 -0
  107. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_slack_sdk.py +0 -0
  108. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_socket.py +0 -0
  109. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_sqlalchemy.py +0 -0
  110. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_sqlalchemy_polars.py +0 -0
  111. /dycw_utilities-0.132.2/src/tests/test_statsmodel.py → /dycw_utilities-0.132.4/src/tests/test_statsmodels.py +0 -0
  112. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_streamlit.py +0 -0
  113. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_string.py +0 -0
  114. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_tempfile.py +0 -0
  115. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_text.py +0 -0
  116. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_threading.py +0 -0
  117. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_timer.py +0 -0
  118. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_traceback.py +0 -0
  119. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_typed_settings.py +0 -0
  120. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_types.py +0 -0
  121. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_typing.py +0 -0
  122. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_typing_funcs/__init__.py +0 -0
  123. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_typing_funcs/no_future.py +0 -0
  124. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_typing_funcs/with_future.py +0 -0
  125. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_tzdata.py +0 -0
  126. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_tzlocal.py +0 -0
  127. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_uuid.py +0 -0
  128. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_version.py +0 -0
  129. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_warnings.py +0 -0
  130. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_whenever.py +0 -0
  131. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_zipfile.py +0 -0
  132. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/tests/test_zoneinfo.py +0 -0
  133. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/aiolimiter.py +0 -0
  134. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/altair.py +0 -0
  135. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/asyncio.py +0 -0
  136. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/atomicwrites.py +0 -0
  137. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/atools.py +0 -0
  138. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/cachetools.py +0 -0
  139. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/concurrent.py +0 -0
  140. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/contextlib.py +0 -0
  141. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/contextvars.py +0 -0
  142. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/cryptography.py +0 -0
  143. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/cvxpy.py +0 -0
  144. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/dataclasses.py +0 -0
  145. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/enum.py +0 -0
  146. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/errors.py +0 -0
  147. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/eventkit.py +0 -0
  148. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/fastapi.py +0 -0
  149. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/fpdf2.py +0 -0
  150. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/functions.py +0 -0
  151. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/functools.py +0 -0
  152. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/getpass.py +0 -0
  153. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/git.py +0 -0
  154. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/hashlib.py +0 -0
  155. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/http.py +0 -0
  156. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/hypothesis.py +0 -0
  157. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/importlib.py +0 -0
  158. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/inflect.py +0 -0
  159. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/ipython.py +0 -0
  160. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/iterables.py +0 -0
  161. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/jupyter.py +0 -0
  162. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/libcst.py +0 -0
  163. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/lightweight_charts.py +0 -0
  164. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/logging.py +0 -0
  165. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/luigi.py +0 -0
  166. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/math.py +0 -0
  167. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/memory_profiler.py +0 -0
  168. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/modules.py +0 -0
  169. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/more_itertools.py +0 -0
  170. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/numpy.py +0 -0
  171. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/operator.py +0 -0
  172. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/optuna.py +0 -0
  173. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/orjson.py +0 -0
  174. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/os.py +0 -0
  175. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pathlib.py +0 -0
  176. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/period.py +0 -0
  177. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pickle.py +0 -0
  178. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/platform.py +0 -0
  179. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/polars.py +0 -0
  180. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/polars_ols.py +0 -0
  181. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pottery.py +0 -0
  182. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pqdm.py +0 -0
  183. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/psutil.py +0 -0
  184. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/py.typed +0 -0
  185. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pydantic.py +0 -0
  186. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pyinstrument.py +0 -0
  187. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pytest.py +0 -0
  188. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/pytest_regressions.py +0 -0
  189. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/python_dotenv.py +0 -0
  190. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/random.py +0 -0
  191. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/re.py +0 -0
  192. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/redis.py +0 -0
  193. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/reprlib.py +0 -0
  194. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/scipy.py +0 -0
  195. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/sentinel.py +0 -0
  196. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/shelve.py +0 -0
  197. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/slack_sdk.py +0 -0
  198. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/socket.py +0 -0
  199. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/sqlalchemy.py +0 -0
  200. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/sqlalchemy_polars.py +0 -0
  201. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/statsmodels.py +0 -0
  202. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/streamlit.py +0 -0
  203. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/string.py +0 -0
  204. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/tempfile.py +0 -0
  205. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/text.py +0 -0
  206. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/threading.py +0 -0
  207. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/timer.py +0 -0
  208. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/traceback.py +0 -0
  209. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/typed_settings.py +0 -0
  210. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/typing.py +0 -0
  211. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/tzdata.py +0 -0
  212. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/tzlocal.py +0 -0
  213. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/uuid.py +0 -0
  214. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/version.py +0 -0
  215. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/warnings.py +0 -0
  216. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/whenever.py +0 -0
  217. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/src/utilities/zipfile.py +0 -0
  218. {dycw_utilities-0.132.2 → dycw_utilities-0.132.4}/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.2
3
+ Version: 0.132.4
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -17,7 +17,6 @@ Requires-Dist: pytest-asyncio<1.1,>=1.0.0; extra == 'test'
17
17
  Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
18
18
  Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
19
19
  Requires-Dist: pytest-lazy-fixtures<1.2,>=1.1.4; extra == 'test'
20
- Requires-Dist: pytest-randomly<3.17,>=3.16.0; extra == 'test'
21
20
  Requires-Dist: pytest-regressions<2.9,>=2.8.0; extra == 'test'
22
21
  Requires-Dist: pytest-rerunfailures<16,>=15.1; extra == 'test'
23
22
  Requires-Dist: pytest-rng<1.1,>=1.0.0; extra == 'test'
@@ -7,80 +7,88 @@ requires = ["hatchling"]
7
7
 
8
8
  # dependency groups
9
9
  [dependency-groups]
10
+ aiolimiter = ["aiolimiter >= 1.2.1, < 1.3"]
11
+ altair = ["altair >= 5.5.0, < 5.6"]
12
+ altair-test = [
13
+ "polars-lts-cpu",
14
+ "img2pdf",
15
+ "vl-convert-python",
16
+ ]
17
+ atools = ["atools >= 0.14.2, < 0.15"]
18
+ cachetools = ["cachetools >= 5.5.2, < 5.6"]
19
+ click = ["click >= 8.2.1, < 8.3"]
20
+ core = [
21
+ "atomicwrites >= 1.4.1, < 1.5",
22
+ "typing-extensions >= 4.14.0, < 4.15",
23
+ "tzlocal >= 5.3.1, < 5.4",
24
+ "whenever >= 0.8.5, < 0.9",
25
+ ]
26
+ cryptography = ["cryptography >= 45.0.4, < 45.1"]
27
+ cvxpy = ["cvxpy >= 1.6.5, < 1.7"]
28
+ dataclasses-test = ["orjson", "polars-lts-cpu"]
10
29
  dev = [
11
- "aiohttp >= 3.12.12, < 3.13", # for slack
12
- "aiolimiter >= 1.2.1, < 1.3",
13
- "aiosqlite >= 0.21.0, < 0.22",
14
- "altair >= 5.5.0, < 5.6",
15
- "asyncpg >= 0.30.0, < 0.31", # for sqlalchemy async
16
- "atools >= 0.14.2, < 0.15",
17
- "cachetools >= 5.5.2, < 5.6", # blocked by streamlit
18
- "click >= 8.2.1, < 8.3",
19
30
  "coloredlogs >= 15.0.1, < 15.1",
20
- "cryptography >= 45.0.4, < 45.1",
21
- "cvxpy >= 1.6.5, < 1.7",
22
- "eventkit >= 1.0.3, < 1.1",
23
- "fastapi >= 0.115.11, < 0.116",
24
- "fpdf2 >= 2.8.3, < 2.9",
25
- "greenlet >= 3.2.0, < 3.3", # for sqlalchemy async
26
- "httpx >= 0.28.1, < 0.29", # for fastapi
27
- "hypothesis >= 6.135.2, < 6.136",
28
- "img2pdf >= 0.6.0, < 0.7",
29
- "inflect >= 7.5.0, < 7.6",
30
- "lightweight-charts >= 2.1, < 2.2",
31
- "luigi >= 3.6.0, < 3.7",
32
- "memory-profiler >= 0.61.0, < 0.62",
33
- "more-itertools >= 10.7.0, < 10.8",
34
- "nest-asyncio >= 1.6.0, < 1.7", # for sqlalchemy async
35
- "nox >= 2025.2.9, < 2025.3",
36
- "numpy >= 2.3.0, < 2.4",
37
- "libcst >= 1.8.0, < 1.9",
38
- "optuna >= 4.3.0, < 4.4",
39
- "orjson >= 3.10.18, < 3.11",
40
- "pathvalidate >= 3.2.3, < 3.3",
41
- "polars-lts-cpu >= 1.30.0, < 1.31",
42
- "polars-ols >= 0.3.5, < 0.4",
43
- "pottery >= 3.0.1, < 3.1",
44
- "pqdm >= 0.2.0, < 0.3",
45
- "psutil >= 7.0.0, < 7.1",
46
- "psycopg2-binary >= 2.9.10, < 2.10", # for sqlalchemy
47
- "pydantic >= 2.11.4, < 2.12",
48
- "pyinstrument >= 5.0.2, < 5.1",
31
+ "coverage-conditional-plugin >= 0.9.0, < 0.10",
49
32
  "pyright[nodejs] >= 1.1.401, < 1.2",
50
- "pyrsistent >= 0.20.0, < 0.21",
33
+ "pytest-cov >= 6.1.1, < 6.2",
34
+ ]
35
+ eventkit = ["eventkit >= 1.0.3, < 1.1"]
36
+ fastapi = ["fastapi >= 0.115.11, < 0.116"]
37
+ fastapi-test = ["httpx", "uvicorn"]
38
+ fpdf2 = ["fpdf2 >= 2.8.3, < 2.9"]
39
+ hashlib-test = ["orjson"]
40
+ http-test = ["orjson"]
41
+ hypothesis = ["hypothesis >= 6.135.2, < 6.136"]
42
+ hypothesis-test = ["luigi", "pathvalidate", "numpy", "pytest-rerunfailures"]
43
+ inflect = ["inflect >= 7.5.0, < 7.6"]
44
+ jupyter-test = ["pandas", "polars"]
45
+ libcst = ["libcst >= 1.8.0, < 1.9"]
46
+ lightweight-charts = ["lightweight-charts >= 2.1, < 2.2"]
47
+ lightweight-charts-test = ["polars-lts-cpu", "pyarrow"]
48
+ luigi = ["luigi >= 3.6.0, < 3.7"]
49
+ math-test = ["numpy"]
50
+ memory-profiler = ["memory-profiler >= 0.61.0, < 0.62"]
51
+ more-itertools = ["more-itertools >= 10.7.0, < 10.8"]
52
+ numpy = ["numpy >= 2.3.0, < 2.4"]
53
+ operator = ["polars-lts-cpu"]
54
+ optuna = ["optuna >= 4.3.0, < 4.4"]
55
+ orjson = ["orjson >= 3.10.18, < 3.11"]
56
+ orjson-test = ["polars-lts-cpu"]
57
+ polars = ["polars-lts-cpu >= 1.30.0, < 1.31"]
58
+ polars-ols = ["polars-ols >= 0.3.5, < 0.4"]
59
+ polars-ols-test = ["scikit-learn"]
60
+ polars-test = ["numpy", "statsmodels"]
61
+ pottery = ["pottery >= 3.0.1, < 3.1"]
62
+ pottery-test = ["orjson", "pytest-rerunfailures"]
63
+ pqdm = ["pqdm >= 0.2.0, < 0.3"]
64
+ psutil = ["psutil >= 7.0.0, < 7.1"]
65
+ pydantic = ["pydantic >= 2.11.4, < 2.12"]
66
+ pyinstrument = ["pyinstrument >= 5.0.2, < 5.1"]
67
+ pytest = [
51
68
  "pytest >= 8.3.5, < 8.4",
52
- "pytest-regressions >= 2.8.0, < 2.9",
53
- "python-dotenv >= 1.1.0, < 1.2",
54
- "redis >= 6.2.0, < 6.3",
55
- "rich >= 14.0.0, < 14.1",
56
- "scikit-learn >= 1.7.0, < 1.8",
57
- "scipy >= 1.15.3, < 1.16",
58
- "slack-sdk >= 3.35.0, < 3.36",
59
- "sqlalchemy >= 2.0.41, < 2.1",
60
- "statsmodels >= 0.14.4, < 0.15",
61
- "streamlit >= 1.45.0, < 1.46",
62
- "tomlkit >= 0.13.2, < 0.14",
63
- "typed-settings >= 24.6.0, < 24.7",
64
- "tzdata >= 2025.2, < 2025.3",
65
- "uvicorn >= 0.34.1, < 0.35",
66
- "vegafusion >= 2.0.2, < 2.1",
67
- "vegafusion-python-embed >= 1.6.9, < 1.7",
68
- "vl-convert-python >= 1.8.0, < 1.9",
69
- # test
70
- "coverage-conditional-plugin >= 0.9.0, < 0.10",
71
- "dycw-pytest-only >= 2.1.1, < 2.2",
72
69
  "pytest-asyncio >= 1.0.0, < 1.1",
73
- "pytest-cov >= 6.1.1, < 6.2",
74
- "pytest-instafail >= 0.5.0, < 0.6",
75
- "pytest-lazy-fixtures >= 1.1.4, < 1.2",
76
70
  "pytest-randomly >= 3.16.0, < 3.17",
77
- "pytest-rerunfailures >= 15.1, < 16",
78
- "pytest-rng >= 1.0.0, < 1.1",
79
- "pytest-timeout >= 2.4.0, < 2.5",
80
71
  "pytest-xdist >= 3.7.0, < 3.8",
81
- # CI
82
- "aiolimiter>=1.2.1",
83
72
  ]
73
+ pytest-regressions = ["pytest-regressions >= 2.8.0, < 2.9"]
74
+ pytest-regressions-test = ["orjson", "polars-lts-cpu"]
75
+ pytest-test = ["orjson", "pytest-rng", "pytest-rerunfailures"]
76
+ python-dotenv = ["python-dotenv >= 1.1.0, < 1.2"]
77
+ redis = ["redis >= 6.2.0, < 6.3", "orjson"]
78
+ redis-test = ["pytest-rerunfailures"]
79
+ reprlib-test = ["rich"]
80
+ scipy = ["scipy >= 1.15.3, < 1.16"]
81
+ sklearn = ["scikit-learn >= 1.7.0, < 1.8"]
82
+ slack-sdk = ["slack-sdk >= 3.35.0, < 3.36"]
83
+ slack-sdk-test = ["aiohttp"]
84
+ sqlalchemy = ["sqlalchemy >= 2.0.41, < 2.1"]
85
+ sqlalchemy-polars = ["sqlalchemy", "polars-lts-cpu"]
86
+ sqlalchemy-polars-test = ["aiosqlite", "asyncpg", "greenlet"]
87
+ sqlalchemy-test = ["aiosqlite", "asyncpg", "greenlet"]
88
+ statsmodels = ["statsmodels >= 0.14.4, < 0.15"]
89
+ streamlit = ["streamlit >= 1.45.0, < 1.46"]
90
+ typed-settings = ["typed-settings >= 24.6.0, < 24.7"]
91
+ tzdata = ["tzdata >= 2025.2, < 2025.3"]
84
92
 
85
93
  # project
86
94
  [project]
@@ -94,7 +102,7 @@ dependencies = [
94
102
  name = "dycw-utilities"
95
103
  readme = "README.md"
96
104
  requires-python = ">= 3.12"
97
- version = "0.132.2"
105
+ version = "0.132.4"
98
106
 
99
107
  [project.optional-dependencies]
100
108
  logging = [
@@ -108,7 +116,6 @@ test = [
108
116
  "pytest-cov >= 6.1.1, < 6.2",
109
117
  "pytest-instafail >= 0.5.0, < 0.6",
110
118
  "pytest-lazy-fixtures >= 1.1.4, < 1.2",
111
- "pytest-randomly >= 3.16.0, < 3.17",
112
119
  "pytest-regressions >= 2.8.0, < 2.9",
113
120
  "pytest-rerunfailures >= 15.1, < 16",
114
121
  "pytest-rng >= 1.0.0, < 1.1",
@@ -121,7 +128,7 @@ test = [
121
128
  # bump-my-version
122
129
  [tool.bumpversion]
123
130
  allow_dirty = true
124
- current_version = "0.132.2"
131
+ current_version = "0.132.4"
125
132
 
126
133
  [[tool.bumpversion.files]]
127
134
  filename = "src/utilities/__init__.py"
@@ -223,17 +230,17 @@ addopts = [
223
230
  "--durations=10",
224
231
  "--durations-min=10",
225
232
  "--strict-markers",
226
- "--timeout=300",
227
233
  ]
228
234
  asyncio_default_fixture_loop_scope = "function"
229
235
  asyncio_mode = "auto"
230
236
  filterwarnings = [
231
237
  "error",
232
238
  "ignore:.*utcfromtimestamp.* is deprecated and scheduled for removal in a future version:DeprecationWarning", # luigi
239
+ "ignore:Exception ignored in.* <coroutine object .* at .*>:pytest.PytestUnraisableExceptionWarning",
233
240
  "ignore:Implicitly cleaning up <TemporaryDirectory '.*'>:ResourceWarning",
234
241
  "ignore:ResourceTracker called reentrantly for resource cleanup, which is unsupported:UserWarning",
235
242
  "ignore:Task .* without outputs has no custom complete.* method:UserWarning", # luigi
236
- "ignore:The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <Connection(.*)>>:sqlalchemy.exc.SAWarning", # sqlalchemy
243
+ "ignore:The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <Connection(.*)>:RuntimeWarning", # sqlalchemy
237
244
  "ignore:There is no current event loop:DeprecationWarning", # eventkit
238
245
  "ignore:Using fork.* can cause Polars to deadlock in the child process:RuntimeWarning", # polars/pqdm
239
246
  "ignore:coroutine 'AsyncConnection.close' was never awaited:RuntimeWarning",
@@ -328,3 +335,7 @@ ban-relative-imports = "all"
328
335
  [tool.ruff.lint.isort]
329
336
  required-imports = ["from __future__ import annotations"]
330
337
  split-on-trailing-comma = false
338
+
339
+ # uv
340
+ [tool.uv]
341
+ default-groups = "all"
@@ -8,7 +8,6 @@ from typing import TYPE_CHECKING, Any
8
8
 
9
9
  from hypothesis import HealthCheck
10
10
  from pytest import fixture, mark, param
11
- from sqlalchemy import text
12
11
  from whenever import PlainDateTime
13
12
 
14
13
  from utilities.platform import IS_NOT_LINUX, IS_WINDOWS
@@ -64,6 +63,8 @@ def set_log_factory() -> AbstractContextManager[None]:
64
63
 
65
64
  @fixture(params=[param("sqlite"), param("postgresql", marks=SKIPIF_CI)])
66
65
  async def test_engine(*, request: SubRequest, tmp_path: Path) -> Any:
66
+ from sqlalchemy import text
67
+
67
68
  from utilities.sqlalchemy import create_async_engine
68
69
 
69
70
  dialect = request.param
@@ -16,6 +16,7 @@ from hypothesis.strategies import (
16
16
  booleans,
17
17
  data,
18
18
  frozensets,
19
+ ip_addresses,
19
20
  lists,
20
21
  sampled_from,
21
22
  )
@@ -36,6 +37,8 @@ from utilities.click import (
36
37
  FrozenSetChoices,
37
38
  FrozenSetEnums,
38
39
  FrozenSetStrs,
40
+ IPv4Address,
41
+ IPv6Address,
39
42
  ListEnums,
40
43
  ListStrs,
41
44
  Month,
@@ -227,6 +230,8 @@ class TestParameters:
227
230
  _lift_serializer(str, sort=True),
228
231
  False,
229
232
  ),
233
+ param(IPv4Address(), "IPV4 ADDRESS", ip_addresses(v=4), str, True),
234
+ param(IPv6Address(), "IPV6 ADDRESS", ip_addresses(v=6), str, True),
230
235
  param(
231
236
  ListEnums(_ExampleEnum),
232
237
  "LIST[ENUM[_ExampleEnum]]",
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import Iterable
4
+ from ipaddress import IPv4Address, IPv6Address
4
5
  from pathlib import Path
5
6
  from types import NoneType
6
7
  from typing import Final, Literal
@@ -12,6 +13,7 @@ from hypothesis.strategies import (
12
13
  floats,
13
14
  frozensets,
14
15
  integers,
16
+ ip_addresses,
15
17
  lists,
16
18
  none,
17
19
  sampled_from,
@@ -110,6 +112,18 @@ class TestSerializeAndParseObject:
110
112
  result = parse_object(int, serialized)
111
113
  assert result == int_
112
114
 
115
+ @given(address=ip_addresses(v=4))
116
+ def test_ipv4_address(self, *, address: IPv4Address) -> None:
117
+ serialized = serialize_object(address)
118
+ result = parse_object(IPv4Address, serialized)
119
+ assert result == address
120
+
121
+ @given(address=ip_addresses(v=6))
122
+ def test_ipv6_address(self, *, address: IPv6Address) -> None:
123
+ serialized = serialize_object(address)
124
+ result = parse_object(IPv6Address, serialized)
125
+ assert result == address
126
+
113
127
  @given(ints=lists(int64s()))
114
128
  def test_list(self, *, ints: list[int]) -> None:
115
129
  serialized = serialize_object(ints)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.132.2"
3
+ __version__ = "0.132.4"
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import ipaddress
3
4
  import pathlib
4
5
  from typing import TYPE_CHECKING, Generic, TypedDict, TypeVar, assert_never, override
5
6
 
@@ -12,12 +13,15 @@ import utilities.whenever
12
13
  from utilities.enum import EnsureEnumError, ensure_enum
13
14
  from utilities.functions import EnsureStrError, ensure_str, get_class_name
14
15
  from utilities.iterables import is_iterable_not_str
16
+ from utilities.parse import ParseObjectError, parse_object
15
17
  from utilities.text import split_str
16
18
  from utilities.types import (
17
19
  DateDeltaLike,
18
20
  DateLike,
19
21
  DateTimeDeltaLike,
20
22
  EnumLike,
23
+ IPv4AddressLike,
24
+ IPv6AddressLike,
21
25
  MaybeStr,
22
26
  PlainDateTimeLike,
23
27
  TEnum,
@@ -173,6 +177,58 @@ class Enum(ParamType, Generic[TEnum]):
173
177
  return _make_metavar(param, desc)
174
178
 
175
179
 
180
+ class IPv4Address(ParamType):
181
+ """An IPv4 address-valued parameter."""
182
+
183
+ name = "ipv4 address"
184
+
185
+ @override
186
+ def __repr__(self) -> str:
187
+ return self.name.upper()
188
+
189
+ @override
190
+ def convert(
191
+ self, value: IPv4AddressLike, param: Parameter | None, ctx: Context | None
192
+ ) -> ipaddress.IPv4Address:
193
+ """Convert a value into the `IPv4Address` type."""
194
+ match value:
195
+ case ipaddress.IPv4Address():
196
+ return value
197
+ case str():
198
+ try:
199
+ return parse_object(ipaddress.IPv4Address, value)
200
+ except ParseObjectError as error:
201
+ self.fail(str(error), param, ctx)
202
+ case _ as never:
203
+ assert_never(never)
204
+
205
+
206
+ class IPv6Address(ParamType):
207
+ """An IPv6 address-valued parameter."""
208
+
209
+ name = "ipv6 address"
210
+
211
+ @override
212
+ def __repr__(self) -> str:
213
+ return self.name.upper()
214
+
215
+ @override
216
+ def convert(
217
+ self, value: IPv6AddressLike, param: Parameter | None, ctx: Context | None
218
+ ) -> ipaddress.IPv6Address:
219
+ """Convert a value into the `IPv6Address` type."""
220
+ match value:
221
+ case ipaddress.IPv6Address():
222
+ return value
223
+ case str():
224
+ try:
225
+ return parse_object(ipaddress.IPv6Address, value)
226
+ except ParseObjectError as error:
227
+ self.fail(str(error), param, ctx)
228
+ case _ as never:
229
+ assert_never(never)
230
+
231
+
176
232
  class Month(ParamType):
177
233
  """A month-valued parameter."""
178
234
 
@@ -467,6 +523,8 @@ __all__ = [
467
523
  "FrozenSetEnums",
468
524
  "FrozenSetParameter",
469
525
  "FrozenSetStrs",
526
+ "IPv4Address",
527
+ "IPv6Address",
470
528
  "ListEnums",
471
529
  "ListParameter",
472
530
  "ListStrs",
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from contextlib import suppress
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
+ from ipaddress import IPv4Address, IPv6Address
6
7
  from pathlib import Path
7
8
  from re import DOTALL
8
9
  from types import NoneType
@@ -176,14 +177,9 @@ def _parse_object_type(
176
177
  return parse_bool(text)
177
178
  except ParseBoolError:
178
179
  raise _ParseObjectParseError(type_=cls, text=text) from None
179
- if is_subclass_gen(cls, int):
180
+ if is_subclass_gen(cls, int | float | IPv4Address | IPv6Address):
180
181
  try:
181
- return int(text)
182
- except ValueError:
183
- raise _ParseObjectParseError(type_=cls, text=text) from None
184
- if issubclass(cls, float):
185
- try:
186
- return float(text)
182
+ return cls(text)
187
183
  except ValueError:
188
184
  raise _ParseObjectParseError(type_=cls, text=text) from None
189
185
  if issubclass(cls, Enum):
@@ -443,7 +439,16 @@ def serialize_object(
443
439
  with suppress(_SerializeObjectSerializeError):
444
440
  return _serialize_object_extra(obj, extra)
445
441
  if (obj is None) or isinstance(
446
- obj, bool | int | float | str | Path | Sentinel | Version
442
+ obj,
443
+ bool
444
+ | int
445
+ | float
446
+ | str
447
+ | IPv4Address
448
+ | IPv6Address
449
+ | Path
450
+ | Sentinel
451
+ | Version,
447
452
  ):
448
453
  return str(obj)
449
454
  if isinstance(
@@ -4,6 +4,7 @@ import datetime as dt
4
4
  from asyncio import Event
5
5
  from collections.abc import Awaitable, Callable, Coroutine, Hashable, Iterable, Mapping
6
6
  from enum import Enum
7
+ from ipaddress import IPv4Address, IPv6Address
7
8
  from logging import Logger
8
9
  from pathlib import Path
9
10
  from random import Random
@@ -112,6 +113,11 @@ THashable1 = TypeVar("THashable1", bound=Hashable)
112
113
  THashable2 = TypeVar("THashable2", bound=Hashable)
113
114
 
114
115
 
116
+ # ipaddress
117
+ IPv4AddressLike = MaybeStr[IPv4Address]
118
+ IPv6AddressLike = MaybeStr[IPv6Address]
119
+
120
+
115
121
  # iterables
116
122
  type MaybeIterable[_T] = _T | Iterable[_T]
117
123
  type IterableHashable[_THashable: Hashable] = (
@@ -295,6 +301,8 @@ __all__ = [
295
301
  "DateTimeRoundUnit",
296
302
  "EnumLike",
297
303
  "ExcInfo",
304
+ "IPv4AddressLike",
305
+ "IPv6AddressLike",
298
306
  "IterableHashable",
299
307
  "LogLevel",
300
308
  "LoggerOrName",
@@ -1,49 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from types import NoneType
4
-
5
- from pyrsistent import PTypeError
6
- from pytest import raises
7
-
8
- from utilities.pyrsistent import PRecord, field
9
-
10
-
11
- class TestPRecord:
12
- def test_mandatory_field_without_type_checking(self) -> None:
13
- class ARecord(PRecord):
14
- x: int = field()
15
-
16
- r = ARecord(x=3)
17
- assert repr(r) == "ARecord(x=3)"
18
- assert r.x == 3
19
- assert r.set(x=2) == ARecord(x=2)
20
- with raises(
21
- AttributeError, match="'y' is not among the specified fields for ARecord"
22
- ):
23
- _ = r.set(y=2)
24
-
25
- def test_optional_field_without_type_checking(self) -> None:
26
- class ARecord(PRecord):
27
- x: int | None = field(default=None)
28
-
29
- r = ARecord()
30
- assert repr(r) == "ARecord(x=None)"
31
- assert r.x is None
32
-
33
- def test_mandatory_field_with_type_checking(self) -> None:
34
- class ARecord(PRecord):
35
- x: int = field(type=int)
36
-
37
- r = ARecord(x=3)
38
- assert repr(r) == "ARecord(x=3)"
39
- with raises(PTypeError, match="Invalid type for field ARecord.x, was str"):
40
- _ = r.set(x="2")
41
-
42
- def test_optional_field_with_type_checking(self) -> None:
43
- class ARecord(PRecord):
44
- x: int | None = field(type=(int, NoneType), default=None)
45
-
46
- r = ARecord()
47
- assert repr(r) == "ARecord(x=None)"
48
- with raises(PTypeError, match="Invalid type for field ARecord.x, was str"):
49
- _ = r.set(x="2")
@@ -1,89 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any, TypeVar, dataclass_transform, overload
4
-
5
- from pyrsistent import PRecord as _PRecord
6
- from pyrsistent import field as _field
7
- from pyrsistent._field_common import (
8
- PFIELD_NO_FACTORY,
9
- PFIELD_NO_INITIAL,
10
- PFIELD_NO_INVARIANT,
11
- PFIELD_NO_SERIALIZER,
12
- PFIELD_NO_TYPE,
13
- )
14
-
15
- if TYPE_CHECKING:
16
- from collections.abc import Callable
17
-
18
- from utilities.types import TypeLike
19
-
20
-
21
- _T = TypeVar("_T")
22
- _U = TypeVar("_U")
23
-
24
-
25
- @overload
26
- def field(
27
- *,
28
- type: type[_T],
29
- invariant: Callable[[Any], tuple[bool, Any]] = ...,
30
- default: Any = ...,
31
- mandatory: bool = ...,
32
- factory: Callable[[_U], _U] = ...,
33
- serializer: Callable[[Any, Any], Any] = ...,
34
- ) -> _T: ...
35
- @overload
36
- def field(
37
- *,
38
- type: tuple[type[_T]],
39
- invariant: Callable[[Any], tuple[bool, Any]] = ...,
40
- default: Any = ...,
41
- mandatory: bool = ...,
42
- factory: Callable[[_U], _U] = ...,
43
- serializer: Callable[[Any, Any], Any] = ...,
44
- ) -> _T: ...
45
- @overload
46
- def field(
47
- *,
48
- type: tuple[type[_T], type[_U]],
49
- invariant: Callable[[Any], tuple[bool, Any]] = ...,
50
- default: Any = ...,
51
- mandatory: bool = ...,
52
- factory: Callable[[_U], _U] = ...,
53
- serializer: Callable[[Any, Any], Any] = ...,
54
- ) -> _T | _U: ...
55
- @overload
56
- def field(
57
- *,
58
- type: tuple[Any, ...] = ...,
59
- invariant: Callable[[Any], tuple[bool, Any]] = ...,
60
- default: Any = ...,
61
- mandatory: bool = ...,
62
- factory: Callable[[_U], _U] = ...,
63
- serializer: Callable[[Any, Any], Any] = ...,
64
- ) -> Any: ...
65
- def field(
66
- *,
67
- type: TypeLike[_T] = PFIELD_NO_TYPE, # noqa: A002
68
- invariant: Callable[[Any], tuple[bool, Any]] = PFIELD_NO_INVARIANT,
69
- default: Any = PFIELD_NO_INITIAL,
70
- mandatory: bool = False,
71
- factory: Callable[[_U], _U] = PFIELD_NO_FACTORY,
72
- serializer: Callable[[Any, Any], Any] = PFIELD_NO_SERIALIZER,
73
- ) -> Any:
74
- """Field specification factory for :py:class:`PRecord`."""
75
- return _field(
76
- type=type,
77
- invariant=invariant,
78
- initial=default,
79
- mandatory=mandatory,
80
- factory=factory,
81
- serializer=serializer,
82
- )
83
-
84
-
85
- @dataclass_transform(kw_only_default=True, field_specifiers=(field,))
86
- class PRecord(_PRecord): ...
87
-
88
-
89
- __all__ = ["PRecord", "field"]