dycw-utilities 0.112.0__tar.gz → 0.112.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 (228) hide show
  1. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/PKG-INFO +1 -1
  2. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/pyproject.toml +2 -2
  3. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_dataclasses.py +17 -8
  4. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_parse.py +43 -23
  5. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_sentinel.py +4 -3
  6. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_text.py +8 -8
  7. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_typing.py +154 -101
  8. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/__init__.py +1 -1
  9. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/parse.py +3 -2
  10. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/polars.py +7 -6
  11. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/sentinel.py +1 -1
  12. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/text.py +3 -3
  13. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/typing.py +59 -11
  14. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/.gitignore +0 -0
  15. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/LICENSE +0 -0
  16. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/README.md +0 -0
  17. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/__init__.py +0 -0
  18. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/conftest.py +0 -0
  19. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/__init__.py +0 -0
  20. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_missing/__init__.py +0 -0
  21. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_missing/module.py +0 -0
  22. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/__init__.py +0 -0
  23. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/outer_1.py +0 -0
  24. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/outer_2.py +0 -0
  25. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  26. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  27. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  28. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  29. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_without/__init__.py +0 -0
  30. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_without/module_1.py +0 -0
  31. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/package_without/module_2.py +0 -0
  32. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/standalone.py +0 -0
  33. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/modules/with_imports.py +0 -0
  34. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  35. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  36. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  37. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  38. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  39. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  40. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  41. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  42. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/__init__.py +0 -0
  43. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/test_async_service/__init__.py +0 -0
  44. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/test_async_service/__main__.py +0 -0
  45. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/test_async_service/run.sh +0 -0
  46. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
  47. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
  48. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/scripts/test_queue_processor/run.sh +0 -0
  49. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_altair.py +0 -0
  50. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_astor.py +0 -0
  51. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_asyncio.py +0 -0
  52. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_atomicwrites.py +0 -0
  53. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_atools.py +0 -0
  54. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_cachetools.py +0 -0
  55. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_click.py +0 -0
  56. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_concurrent.py +0 -0
  57. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_contextlib.py +0 -0
  58. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_contextvars.py +0 -0
  59. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_cryptography.py +0 -0
  60. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_cvxpy.py +0 -0
  61. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_datetime.py +0 -0
  62. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_enum.py +0 -0
  63. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_errors.py +0 -0
  64. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_eventkit.py +0 -0
  65. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_fastapi.py +0 -0
  66. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_fpdf2.py +0 -0
  67. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_functions.py +0 -0
  68. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_functools.py +0 -0
  69. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_getpass.py +0 -0
  70. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_git.py +0 -0
  71. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_hashlib.py +0 -0
  72. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_http.py +0 -0
  73. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_hypothesis.py +0 -0
  74. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_ipython.py +0 -0
  75. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_iterables.py +0 -0
  76. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_jupyter.py +0 -0
  77. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_lightweight_charts.py +0 -0
  78. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_logging.py +0 -0
  79. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_loguru.py +0 -0
  80. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_luigi.py +0 -0
  81. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_math.py +0 -0
  82. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_memory_profiler.py +0 -0
  83. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_modules.py +0 -0
  84. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_more_itertools.py +0 -0
  85. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_numpy.py +0 -0
  86. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_operator.py +0 -0
  87. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_optuna.py +0 -0
  88. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_orjson.py +0 -0
  89. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_os.py +0 -0
  90. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pathlib.py +0 -0
  91. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_period.py +0 -0
  92. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pickle.py +0 -0
  93. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_platform.py +0 -0
  94. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_polars.py +0 -0
  95. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_polars_ols.py +0 -0
  96. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pqdm.py +0 -0
  97. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pydantic.py +0 -0
  98. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pyinstrument.py +0 -0
  99. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pyrsistent.py +0 -0
  100. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pytest.py +0 -0
  101. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_pytest_regressions.py +0 -0
  102. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_python_dotenv.py +0 -0
  103. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_random.py +0 -0
  104. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_re.py +0 -0
  105. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_redis.py +0 -0
  106. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_reprlib.py +0 -0
  107. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_rich.py +0 -0
  108. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_scipy.py +0 -0
  109. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_shelve.py +0 -0
  110. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_slack_sdk.py +0 -0
  111. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_socket.py +0 -0
  112. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_sqlalchemy.py +0 -0
  113. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_sqlalchemy_polars.py +0 -0
  114. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_statsmodel.py +0 -0
  115. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_streamlit.py +0 -0
  116. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_sys.py +0 -0
  117. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_tempfile.py +0 -0
  118. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_tenacity.py +0 -0
  119. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_threading.py +0 -0
  120. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_timer.py +0 -0
  121. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback.py +0 -0
  122. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/__init__.py +0 -0
  123. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/chain.py +0 -0
  124. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  125. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  126. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  127. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/many.py +0 -0
  128. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/one.py +0 -0
  129. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/recursive.py +0 -0
  130. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  131. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  132. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/two.py +0 -0
  133. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_traceback_funcs/untraced.py +0 -0
  134. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_types.py +0 -0
  135. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_typing_funcs/__init__.py +0 -0
  136. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_typing_funcs/no_future.py +0 -0
  137. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_typing_funcs/with_future.py +0 -0
  138. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_tzdata.py +0 -0
  139. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_tzlocal.py +0 -0
  140. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_uuid.py +0 -0
  141. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_version.py +0 -0
  142. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_warnings.py +0 -0
  143. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_whenever.py +0 -0
  144. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_zipfile.py +0 -0
  145. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/tests/test_zoneinfo.py +0 -0
  146. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/altair.py +0 -0
  147. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/astor.py +0 -0
  148. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/asyncio.py +0 -0
  149. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/atomicwrites.py +0 -0
  150. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/atools.py +0 -0
  151. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/cachetools.py +0 -0
  152. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/click.py +0 -0
  153. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/concurrent.py +0 -0
  154. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/contextlib.py +0 -0
  155. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/contextvars.py +0 -0
  156. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/cryptography.py +0 -0
  157. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/cvxpy.py +0 -0
  158. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/dataclasses.py +0 -0
  159. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/datetime.py +0 -0
  160. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/enum.py +0 -0
  161. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/errors.py +0 -0
  162. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/eventkit.py +0 -0
  163. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/fastapi.py +0 -0
  164. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/fpdf2.py +0 -0
  165. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/functions.py +0 -0
  166. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/functools.py +0 -0
  167. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/getpass.py +0 -0
  168. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/git.py +0 -0
  169. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/hashlib.py +0 -0
  170. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/http.py +0 -0
  171. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/hypothesis.py +0 -0
  172. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/ipython.py +0 -0
  173. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/iterables.py +0 -0
  174. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/jupyter.py +0 -0
  175. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/lightweight_charts.py +0 -0
  176. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/logging.py +0 -0
  177. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/loguru.py +0 -0
  178. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/luigi.py +0 -0
  179. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/math.py +0 -0
  180. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/memory_profiler.py +0 -0
  181. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/modules.py +0 -0
  182. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/more_itertools.py +0 -0
  183. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/numpy.py +0 -0
  184. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/operator.py +0 -0
  185. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/optuna.py +0 -0
  186. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/orjson.py +0 -0
  187. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/os.py +0 -0
  188. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pathlib.py +0 -0
  189. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/period.py +0 -0
  190. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pickle.py +0 -0
  191. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/platform.py +0 -0
  192. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/polars_ols.py +0 -0
  193. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pqdm.py +0 -0
  194. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/py.typed +0 -0
  195. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pydantic.py +0 -0
  196. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pyinstrument.py +0 -0
  197. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pyrsistent.py +0 -0
  198. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pytest.py +0 -0
  199. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/pytest_regressions.py +0 -0
  200. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/python_dotenv.py +0 -0
  201. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/random.py +0 -0
  202. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/re.py +0 -0
  203. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/redis.py +0 -0
  204. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/reprlib.py +0 -0
  205. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/rich.py +0 -0
  206. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/scipy.py +0 -0
  207. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/shelve.py +0 -0
  208. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/slack_sdk.py +0 -0
  209. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/socket.py +0 -0
  210. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/sqlalchemy.py +0 -0
  211. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/sqlalchemy_polars.py +0 -0
  212. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/statsmodels.py +0 -0
  213. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/streamlit.py +0 -0
  214. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/sys.py +0 -0
  215. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/tempfile.py +0 -0
  216. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/tenacity.py +0 -0
  217. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/threading.py +0 -0
  218. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/timer.py +0 -0
  219. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/traceback.py +0 -0
  220. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/types.py +0 -0
  221. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/tzdata.py +0 -0
  222. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/tzlocal.py +0 -0
  223. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/uuid.py +0 -0
  224. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/version.py +0 -0
  225. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/warnings.py +0 -0
  226. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/whenever.py +0 -0
  227. {dycw_utilities-0.112.0 → dycw_utilities-0.112.2}/src/utilities/zipfile.py +0 -0
  228. {dycw_utilities-0.112.0 → dycw_utilities-0.112.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.112.0
3
+ Version: 0.112.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.112.0"
97
+ version = "0.112.2"
98
98
 
99
99
  [project.optional-dependencies]
100
100
  test = [
@@ -337,7 +337,7 @@ zzz-test-zoneinfo = [
337
337
  # bump-my-version
338
338
  [tool.bumpversion]
339
339
  allow_dirty = true
340
- current_version = "0.112.0"
340
+ current_version = "0.112.2"
341
341
 
342
342
  [[tool.bumpversion.files]]
343
343
  filename = "src/utilities/__init__.py"
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from dataclasses import dataclass, field
4
4
  from pathlib import Path
5
5
  from types import NoneType
6
- from typing import Any, cast, override
6
+ from typing import Any, Literal, cast, override
7
7
 
8
8
  from hypothesis import given
9
9
  from hypothesis.strategies import booleans, integers, lists, sampled_from
@@ -406,7 +406,18 @@ class TestSerializeAndParseDataClass:
406
406
  assert result == obj
407
407
 
408
408
  @given(int_=integers())
409
- def test_extra_type(self, *, int_: int) -> None:
409
+ def test_literal_type(self, *, int_: int) -> None:
410
+ obj = DataClassFutureInt(int_=int_)
411
+ serialized = serialize_dataclass(obj)
412
+ result = parse_dataclass(
413
+ serialized,
414
+ DataClassFutureInt,
415
+ extra_parsers={Literal["lit"]: NotImplementedError},
416
+ )
417
+ assert result == obj
418
+
419
+ @given(int_=integers())
420
+ def test_type_extra(self, *, int_: int) -> None:
410
421
  obj = DataClassFutureNestedOuterFirstOuter(
411
422
  inner=DataClassFutureNestedOuterFirstInner(int_=int_)
412
423
  )
@@ -625,9 +636,8 @@ class TestYieldFields:
625
636
  assert result == expected
626
637
  assert is_optional_type(result.type_)
627
638
  args = get_args(result.type_)
628
- assert args == (TrueOrFalseFutureLit,)
629
- arg = one(args)
630
- assert get_args(arg) == ("true", "false")
639
+ assert args == (TrueOrFalseFutureLit, NoneType)
640
+ assert get_args(args[0]) == ("true", "false")
631
641
 
632
642
  def test_class_future_nested(self) -> None:
633
643
  result = one(
@@ -665,9 +675,8 @@ class TestYieldFields:
665
675
  assert result == expected
666
676
  assert is_optional_type(result.type_)
667
677
  args = get_args(result.type_)
668
- assert args == (TrueOrFalseFutureTypeLit,)
669
- arg = one(args)
670
- assert get_args(arg) == ("true", "false")
678
+ assert args == (TrueOrFalseFutureTypeLit, NoneType)
679
+ assert get_args(args[0]) == ("true", "false")
671
680
 
672
681
  def test_class_orjson_log_record(self) -> None:
673
682
  result = list(yield_fields(OrjsonLogRecord, globalns=globals()))
@@ -15,6 +15,7 @@ from hypothesis.strategies import (
15
15
  frozensets,
16
16
  integers,
17
17
  lists,
18
+ none,
18
19
  sampled_from,
19
20
  sets,
20
21
  times,
@@ -56,6 +57,7 @@ from utilities.parse import (
56
57
  serialize_object,
57
58
  )
58
59
  from utilities.sentinel import Sentinel, sentinel
60
+ from utilities.text import parse_bool
59
61
  from utilities.types import Duration, Number
60
62
  from utilities.version import Version
61
63
 
@@ -97,28 +99,17 @@ class TestSerializeAndParseObject:
97
99
  result = parse_object(TruthEnum, serialized)
98
100
  assert result is truth
99
101
 
100
- @given(int_=integers())
101
- def test_extra_type(self, *, int_: int) -> None:
102
- serialized = serialize_object(int_)
103
- result = parse_object(
104
- DataClassFutureInt,
105
- serialized,
106
- extra={DataClassFutureInt: lambda text: DataClassFutureInt(int_=int(text))},
107
- )
108
- expected = DataClassFutureInt(int_=int_)
109
- assert result == expected
110
-
111
102
  @given(float_=floats())
112
103
  def test_float(self, *, float_: float) -> None:
113
104
  serialized = serialize_object(float_)
114
105
  result = parse_object(float, serialized)
115
106
  assert is_equal(result, float_)
116
107
 
117
- @given(values=frozensets(dates()))
118
- def test_frozenset(self, *, values: frozenset[dt.date]) -> None:
119
- serialized = serialize_object(values)
108
+ @given(dates=frozensets(dates()))
109
+ def test_frozenset(self, *, dates: frozenset[dt.date]) -> None:
110
+ serialized = serialize_object(dates)
120
111
  result = parse_object(frozenset[dt.date], serialized)
121
- assert result == values
112
+ assert result == dates
122
113
 
123
114
  @given(int_=integers())
124
115
  def test_int(self, *, int_: int) -> None:
@@ -126,11 +117,17 @@ class TestSerializeAndParseObject:
126
117
  result = parse_object(int, serialized)
127
118
  assert result == int_
128
119
 
129
- @given(values=lists(dates()))
130
- def test_list(self, *, values: list[dt.date]) -> None:
131
- serialized = serialize_object(values)
120
+ @given(dates=lists(dates()))
121
+ def test_list(self, *, dates: list[dt.date]) -> None:
122
+ serialized = serialize_object(dates)
132
123
  result = parse_object(list[dt.date], serialized)
133
- assert result == values
124
+ assert result == dates
125
+
126
+ @given(bool_=booleans())
127
+ def test_literal_extra(self, *, bool_: bool) -> None:
128
+ text = serialize_object(bool_)
129
+ result = parse_object(bool, text, extra={Literal["lit"]: parse_bool})
130
+ assert result is bool_
134
131
 
135
132
  @given(truth=sampled_from(["true", "false"]))
136
133
  def test_literal(self, *, truth: Literal["true", "false"]) -> None:
@@ -204,11 +201,11 @@ class TestSerializeAndParseObject:
204
201
  result = parse_object(Sentinel, serialized)
205
202
  assert result is sentinel
206
203
 
207
- @given(values=sets(dates()))
208
- def test_set(self, *, values: set[dt.date]) -> None:
209
- serialized = serialize_object(values)
204
+ @given(dates=sets(dates()))
205
+ def test_set(self, *, dates: set[dt.date]) -> None:
206
+ serialized = serialize_object(dates)
210
207
  result = parse_object(set[dt.date], serialized)
211
- assert result == values
208
+ assert result == dates
212
209
 
213
210
  @given(serialized=text_ascii())
214
211
  def test_to_serialized(self, *, serialized: str) -> None:
@@ -233,6 +230,17 @@ class TestSerializeAndParseObject:
233
230
  result = parse_object(tuple[int, int], serialized)
234
231
  assert result == (x, y)
235
232
 
233
+ @given(int_=integers())
234
+ def test_type_extra(self, *, int_: int) -> None:
235
+ serialized = serialize_object(int_)
236
+ result = parse_object(
237
+ DataClassFutureInt,
238
+ serialized,
239
+ extra={DataClassFutureInt: lambda text: DataClassFutureInt(int_=int(text))},
240
+ )
241
+ expected = DataClassFutureInt(int_=int_)
242
+ assert result == expected
243
+
236
244
  @given(truth=sampled_from(["true", "false"]))
237
245
  def test_type_literal(self, *, truth: Literal["true", "false"]) -> None:
238
246
  result = parse_object(TrueOrFalseFutureTypeLit, truth)
@@ -337,6 +345,18 @@ class TestParseObject:
337
345
  ):
338
346
  _ = parse_object(bool, text, extra={int: parser})
339
347
 
348
+ @given(value=text_ascii(min_size=10) | none())
349
+ def test_optional_type_with_union_extra_not_used(
350
+ self, *, value: str | None
351
+ ) -> None:
352
+ text = serialize_object(value)
353
+
354
+ def parser(text: str, /) -> Number:
355
+ return int(text)
356
+
357
+ result = parse_object(str | None, text, extra={Number: parser})
358
+ assert result == value
359
+
340
360
  def test_error_bool(self) -> None:
341
361
  with raises(
342
362
  _ParseObjectParseError,
@@ -26,11 +26,12 @@ class TestParseSentinel:
26
26
  result = parse_sentinel(text_use)
27
27
  assert result is sentinel
28
28
 
29
- def test_error(self) -> None:
29
+ @given(text=sampled_from(["invalid", "ssentinell"]))
30
+ def test_error(self, *, text: str) -> None:
30
31
  with raises(
31
- ParseSentinelError, match="Unable to parse sentinel value; got 'invalid'"
32
+ ParseSentinelError, match="Unable to parse sentinel value; got '.*'"
32
33
  ):
33
- _ = parse_sentinel("invalid")
34
+ _ = parse_sentinel(text)
34
35
 
35
36
 
36
37
  class TestSentinel:
@@ -51,11 +51,10 @@ class TestParseBool:
51
51
  result = parse_bool(text_use)
52
52
  assert result is value
53
53
 
54
- def test_error(self) -> None:
55
- with raises(
56
- ParseBoolError, match="Unable to parse boolean value; got 'invalid'"
57
- ):
58
- _ = parse_bool("invalid")
54
+ @given(text=sampled_from(["invalid", "11", "00", "ttruee", "ffalsee"]))
55
+ def test_error(self, *, text: str) -> None:
56
+ with raises(ParseBoolError, match="Unable to parse boolean value; got '.*'"):
57
+ _ = parse_bool(text)
59
58
 
60
59
 
61
60
  class TestParseNone:
@@ -66,9 +65,10 @@ class TestParseNone:
66
65
  result = parse_none(text_use)
67
66
  assert result is None
68
67
 
69
- def test_error(self) -> None:
70
- with raises(ParseNoneError, match="Unable to parse null value; got 'invalid'"):
71
- _ = parse_none("invalid")
68
+ @given(text=sampled_from(["invalid", "nnonee"]))
69
+ def test_error(self, *, text: str) -> None:
70
+ with raises(ParseNoneError, match="Unable to parse null value; got '.*'"):
71
+ _ = parse_none(text)
72
72
 
73
73
 
74
74
  class TestReprEncode:
@@ -22,8 +22,10 @@ from hypothesis.strategies import (
22
22
  just,
23
23
  none,
24
24
  sampled_from,
25
+ sets,
26
+ tuples,
25
27
  )
26
- from pytest import mark, param, raises
28
+ from pytest import raises
27
29
 
28
30
  from tests.test_typing_funcs.no_future import (
29
31
  DataClassNoFutureNestedInnerFirstInner,
@@ -54,6 +56,7 @@ from tests.test_typing_funcs.with_future import (
54
56
  from utilities.sentinel import Sentinel
55
57
  from utilities.types import Duration, LogLevel, Number, Parallelism, Seed
56
58
  from utilities.typing import (
59
+ IsSubclassGenError,
57
60
  _GetTypeClassesTupleError,
58
61
  _GetTypeClassesTypeError,
59
62
  _GetUnionTypeClassesInternalTypeError,
@@ -85,32 +88,40 @@ if TYPE_CHECKING:
85
88
 
86
89
 
87
90
  class TestContainsSelf:
88
- @mark.parametrize("obj", [param(Self), param(Self | None)])
91
+ @given(obj=sampled_from([Self, Self | None]))
89
92
  def test_main(self, *, obj: Any) -> None:
90
93
  assert contains_self(obj)
91
94
 
92
95
 
93
96
  class TestGetArgs:
94
- @mark.parametrize(
95
- ("obj", "expected"),
96
- [
97
- param(dict[int, int], (int, int)),
98
- param(frozenset[int], (int,)),
99
- param(int | None, (int,)),
100
- param(int | str, (int, str)),
101
- param(list[int], (int,)),
102
- param(Literal["a", "b", "c"], ("a", "b", "c")),
103
- param(Mapping[int, int], (int, int)),
104
- param(Sequence[int], (int,)),
105
- param(set[int], (int,)),
106
- param(LogLevel, ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")),
107
- param(Parallelism, ("processes", "threads")),
108
- ],
97
+ @given(
98
+ case=sampled_from([
99
+ (dict[int, int], (int, int)),
100
+ (frozenset[int], (int,)),
101
+ (int | None, (int, NoneType)),
102
+ (int | str, (int, str)),
103
+ (list[int], (int,)),
104
+ (Literal["a", "b", "c"], ("a", "b", "c")),
105
+ (Mapping[int, int], (int, int)),
106
+ (Sequence[int], (int,)),
107
+ (set[int], (int,)),
108
+ (LogLevel, ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")),
109
+ (Parallelism, ("processes", "threads")),
110
+ ])
109
111
  )
110
- def test_main(self, *, obj: Any, expected: tuple[Any, ...]) -> None:
112
+ def test_main(self, *, case: tuple[Any, tuple[Any, ...]]) -> None:
113
+ obj, expected = case
111
114
  result = get_args(obj)
112
115
  assert result == expected
113
116
 
117
+ @given(case=sampled_from([(int | None, (int,)), (int | str | None, (int, str))]))
118
+ def test_optional_drop_none(
119
+ self, *, case: tuple[Any, tuple[type[Any], ...]]
120
+ ) -> None:
121
+ obj, expected = case
122
+ result = get_args(obj, optional_drop_none=True)
123
+ assert result == expected
124
+
114
125
 
115
126
  type _PlusOrMinusOneLit = Literal[1, -1]
116
127
  type _TruthLit = Literal["true", "false"]
@@ -417,73 +428,71 @@ class TestGetUnionTypeClasses:
417
428
 
418
429
 
419
430
  class TestIsAnnotationOfType:
420
- @mark.parametrize(
421
- ("func", "obj", "expected"),
422
- [
423
- param(is_dict_type, Mapping[int, int], False),
424
- param(is_dict_type, Sequence[int], False),
425
- param(is_dict_type, dict[int, int], True),
426
- param(is_dict_type, frozenset[int], False),
427
- param(is_dict_type, list[int], False),
428
- param(is_dict_type, set[int], False),
429
- param(is_dict_type, tuple[int, int], False),
430
- param(is_frozenset_type, Mapping[int, int], False),
431
- param(is_frozenset_type, Sequence[int], False),
432
- param(is_frozenset_type, dict[int, int], False),
433
- param(is_frozenset_type, frozenset[int], True),
434
- param(is_frozenset_type, list[int], False),
435
- param(is_frozenset_type, set[int], False),
436
- param(is_frozenset_type, tuple[int, int], False),
437
- param(is_list_type, Mapping[int, int], False),
438
- param(is_list_type, Sequence[int], False),
439
- param(is_list_type, dict[int, int], False),
440
- param(is_list_type, frozenset[int], False),
441
- param(is_list_type, list[int], True),
442
- param(is_list_type, set[int], False),
443
- param(is_list_type, tuple[int, int], False),
444
- param(is_literal_type, Literal["a", "b", "c"], True),
445
- param(is_literal_type, list[int], False),
446
- param(is_mapping_type, Mapping[int, int], True),
447
- param(is_mapping_type, Sequence[int], False),
448
- param(is_mapping_type, dict[int, int], False),
449
- param(is_mapping_type, frozenset[int], False),
450
- param(is_mapping_type, list[int], False),
451
- param(is_mapping_type, set[int], False),
452
- param(is_mapping_type, tuple[int, int], False),
453
- param(is_optional_type, Literal["a", "b", "c"] | None, True),
454
- param(is_optional_type, Literal["a", "b", "c"], False),
455
- param(is_optional_type, int | None, True),
456
- param(is_optional_type, int | str, False),
457
- param(is_optional_type, list[int] | None, True),
458
- param(is_optional_type, list[int], False),
459
- param(is_sequence_type, Mapping[int, int], False),
460
- param(is_sequence_type, Sequence[int], True),
461
- param(is_sequence_type, dict[int, int], False),
462
- param(is_sequence_type, frozenset[int], False),
463
- param(is_sequence_type, list[int], False),
464
- param(is_sequence_type, set[int], False),
465
- param(is_sequence_type, tuple[int, int], False),
466
- param(is_set_type, Mapping[int, int], False),
467
- param(is_set_type, Sequence[int], False),
468
- param(is_set_type, dict[int, int], False),
469
- param(is_set_type, frozenset[int], False),
470
- param(is_set_type, list[int], False),
471
- param(is_set_type, set[int], True),
472
- param(is_set_type, tuple[int, int], False),
473
- param(is_tuple_type, Mapping[int, int], False),
474
- param(is_tuple_type, Sequence[int], False),
475
- param(is_tuple_type, dict[int, int], False),
476
- param(is_tuple_type, frozenset[int], False),
477
- param(is_tuple_type, list[int], False),
478
- param(is_tuple_type, set[int], False),
479
- param(is_tuple_type, tuple[int, int], True),
480
- param(is_union_type, int | str, True),
481
- param(is_union_type, list[int], False),
482
- ],
431
+ @given(
432
+ case=sampled_from([
433
+ (is_dict_type, Mapping[int, int], False),
434
+ (is_dict_type, Sequence[int], False),
435
+ (is_dict_type, dict[int, int], True),
436
+ (is_dict_type, frozenset[int], False),
437
+ (is_dict_type, list[int], False),
438
+ (is_dict_type, set[int], False),
439
+ (is_dict_type, tuple[int, int], False),
440
+ (is_frozenset_type, Mapping[int, int], False),
441
+ (is_frozenset_type, Sequence[int], False),
442
+ (is_frozenset_type, dict[int, int], False),
443
+ (is_frozenset_type, frozenset[int], True),
444
+ (is_frozenset_type, list[int], False),
445
+ (is_frozenset_type, set[int], False),
446
+ (is_frozenset_type, tuple[int, int], False),
447
+ (is_list_type, Mapping[int, int], False),
448
+ (is_list_type, Sequence[int], False),
449
+ (is_list_type, dict[int, int], False),
450
+ (is_list_type, frozenset[int], False),
451
+ (is_list_type, list[int], True),
452
+ (is_list_type, set[int], False),
453
+ (is_list_type, tuple[int, int], False),
454
+ (is_literal_type, Literal["a", "b", "c"], True),
455
+ (is_literal_type, list[int], False),
456
+ (is_mapping_type, Mapping[int, int], True),
457
+ (is_mapping_type, Sequence[int], False),
458
+ (is_mapping_type, dict[int, int], False),
459
+ (is_mapping_type, frozenset[int], False),
460
+ (is_mapping_type, list[int], False),
461
+ (is_mapping_type, set[int], False),
462
+ (is_mapping_type, tuple[int, int], False),
463
+ (is_optional_type, Literal["a", "b", "c"] | None, True),
464
+ (is_optional_type, Literal["a", "b", "c"], False),
465
+ (is_optional_type, int | None, True),
466
+ (is_optional_type, int | str, False),
467
+ (is_optional_type, list[int] | None, True),
468
+ (is_optional_type, list[int], False),
469
+ (is_sequence_type, Mapping[int, int], False),
470
+ (is_sequence_type, Sequence[int], True),
471
+ (is_sequence_type, dict[int, int], False),
472
+ (is_sequence_type, frozenset[int], False),
473
+ (is_sequence_type, list[int], False),
474
+ (is_sequence_type, set[int], False),
475
+ (is_sequence_type, tuple[int, int], False),
476
+ (is_set_type, Mapping[int, int], False),
477
+ (is_set_type, Sequence[int], False),
478
+ (is_set_type, dict[int, int], False),
479
+ (is_set_type, frozenset[int], False),
480
+ (is_set_type, list[int], False),
481
+ (is_set_type, set[int], True),
482
+ (is_set_type, tuple[int, int], False),
483
+ (is_tuple_type, Mapping[int, int], False),
484
+ (is_tuple_type, Sequence[int], False),
485
+ (is_tuple_type, dict[int, int], False),
486
+ (is_tuple_type, frozenset[int], False),
487
+ (is_tuple_type, list[int], False),
488
+ (is_tuple_type, set[int], False),
489
+ (is_tuple_type, tuple[int, int], True),
490
+ (is_union_type, int | str, True),
491
+ (is_union_type, list[int], False),
492
+ ])
483
493
  )
484
- def test_main(
485
- self, *, func: Callable[[Any], bool], obj: Any, expected: bool
486
- ) -> None:
494
+ def test_main(self, *, case: tuple[Callable[[Any], bool], Any, bool]) -> None:
495
+ func, obj, expected = case
487
496
  assert func(obj) is expected
488
497
 
489
498
 
@@ -491,27 +500,52 @@ class TestIsInstanceGen:
491
500
  @given(
492
501
  data=data(),
493
502
  case=sampled_from([
494
- (booleans(), bool, True),
495
- (booleans(), int, False),
496
- (integers(), bool, False),
497
- (integers(), int, True),
498
- (booleans(), (bool, int), True),
499
- (integers(), (bool, int), True),
500
- (dates(), dt.date, True),
501
- (dates(), dt.datetime, False),
502
- (datetimes(), dt.date, False),
503
- (datetimes(), dt.datetime, True),
504
- (booleans(), Number, False),
505
- (integers(), Number, True),
506
- (floats(), Number, True),
503
+ (booleans(), bool, None, True),
504
+ (booleans(), int, None, False),
505
+ (integers(), bool, None, False),
506
+ (integers(), int, None, True),
507
+ (booleans(), (bool, int), None, True),
508
+ (integers(), (bool, int), None, True),
509
+ (dates(), dt.date, None, True),
510
+ (dates(), dt.datetime, None, False),
511
+ (datetimes(), dt.date, None, False),
512
+ (datetimes(), dt.datetime, None, True),
513
+ (booleans(), Number, None, False),
514
+ (integers(), Number, None, True),
515
+ (floats(), Number, None, True),
516
+ (tuples(booleans()), (bool,), None, True),
517
+ (tuples(booleans()), (int,), None, False),
518
+ (tuples(integers()), (bool,), None, False),
519
+ (tuples(integers()), (int,), None, True),
520
+ (tuples(integers()), (int, int), None, False),
521
+ (integers(), int | None, None, True),
522
+ (integers() | none(), int, None, False),
523
+ (integers() | none(), int | None, None, True),
524
+ (sampled_from([1, 2]), Literal[1, 2, 3], 2, True),
525
+ (sampled_from([1, 2, 3]), Literal[1, 2, 3], 3, True),
526
+ (sampled_from([1, 2, 3]), Literal[1, 2], 3, False),
527
+ (booleans(), Literal[1, 2, 3], None, False),
528
+ (sampled_from([1, 2, 3]), bool, 3, False),
529
+ (tuples(booleans()), Literal[1, 2, 3], None, False),
530
+ (sampled_from([1, 2, 3]), (bool,), 3, False),
507
531
  ]),
508
532
  )
509
533
  def test_main(
510
- self, *, data: DataObject, case: tuple[SearchStrategy[Any], Any, bool]
534
+ self,
535
+ *,
536
+ data: DataObject,
537
+ case: tuple[SearchStrategy[Any], Any, int | None, bool],
511
538
  ) -> None:
512
- strategy, type_, expected = case
513
- value = data.draw(strategy)
514
- assert is_instance_gen(value, type_) is expected
539
+ strategy, type_, min_size, expected = case
540
+ match expected:
541
+ case True:
542
+ value = data.draw(strategy)
543
+ assert is_instance_gen(value, type_)
544
+ case False:
545
+ values = data.draw(
546
+ sets(strategy, min_size=100 if min_size is None else min_size)
547
+ )
548
+ assert not all(is_instance_gen(v, type_) for v in values)
515
549
 
516
550
  @given(bool_=booleans())
517
551
  def test_bool_value_vs_custom_int(self, *, bool_: bool) -> None:
@@ -560,6 +594,21 @@ class TestIsSubclassGen:
560
594
  (bool, Number, False),
561
595
  (int, Number, True),
562
596
  (float, Number, True),
597
+ ((bool,), (bool,), True),
598
+ ((bool,), (int,), False),
599
+ ((int,), (bool,), False),
600
+ ((int,), (int,), True),
601
+ ((int,), (int, int), False),
602
+ (int, int | None, True),
603
+ (int | None, int, False),
604
+ (int | None, int | None, True),
605
+ (Literal[1, 2], Literal[1, 2, 3], True),
606
+ (Literal[1, 2, 3], Literal[1, 2, 3], True),
607
+ (Literal[1, 2, 3], Literal[1, 2], False),
608
+ (bool, Literal[1, 2, 3], False),
609
+ (Literal[1, 2, 3], bool, False),
610
+ ((bool,), Literal[1, 2, 3], False),
611
+ (Literal[1, 2, 3], (bool,), False),
563
612
  ])
564
613
  )
565
614
  def test_main(self, *, case: tuple[type[Any], Any, bool]) -> None:
@@ -574,3 +623,7 @@ class TestIsSubclassGen:
574
623
  assert not is_subclass_gen(int, MyInt)
575
624
  assert is_subclass_gen(MyInt, int)
576
625
  assert is_subclass_gen(MyInt, MyInt)
626
+
627
+ def test_error(self) -> None:
628
+ with raises(IsSubclassGenError, match="Argument must be a class; got None"):
629
+ _ = is_subclass_gen(None, NoneType)
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.112.0"
3
+ __version__ = "0.112.2"
@@ -61,7 +61,8 @@ def parse_object(
61
61
  ) -> Any:
62
62
  """Parse text."""
63
63
  if extra is not None:
64
- return _parse_object_extra(type_, text, extra)
64
+ with suppress(_ParseObjectParseError):
65
+ return _parse_object_extra(type_, text, extra)
65
66
  if type_ is None:
66
67
  try:
67
68
  return parse_none(text)
@@ -285,7 +286,7 @@ def _parse_object_extra(cls: Any, text: str, extra: ParseObjectExtra, /) -> Any:
285
286
  parser = one(
286
287
  p for c, p in extra.items() if (cls is c) or is_subclass_gen(cls, c)
287
288
  )
288
- except OneEmptyError:
289
+ except (OneEmptyError, TypeError):
289
290
  raise _ParseObjectParseError(type_=cls, text=text) from None
290
291
  except OneNonUniqueError as error:
291
292
  raise _ParseObjectExtraNonUniqueError(
@@ -941,10 +941,9 @@ def dataclass_to_schema(
941
941
  dtype = struct_dtype(**dtypes)
942
942
  elif field.type_ is dt.datetime:
943
943
  dtype = _dataclass_to_schema_datetime(field)
944
- elif is_union_type(field.type_) and set(get_args(field.type_)) == {
945
- dt.date,
946
- dt.datetime,
947
- }:
944
+ elif is_union_type(field.type_) and set(
945
+ get_args(field.type_, optional_drop_none=True)
946
+ ) == {dt.date, dt.datetime}:
948
947
  if is_instance_gen(field.value, dt.date):
949
948
  dtype = Date
950
949
  else:
@@ -1002,7 +1001,7 @@ def _dataclass_to_schema_one(
1002
1001
  if is_literal_type(obj):
1003
1002
  return pl.Enum(get_args(obj))
1004
1003
  if is_optional_type(obj):
1005
- inner_type = one(get_args(obj))
1004
+ inner_type = one(get_args(obj, optional_drop_none=True))
1006
1005
  return _dataclass_to_schema_one(inner_type, globalns=globalns, localns=localns)
1007
1006
  msg = f"{obj=}"
1008
1007
  raise NotImplementedError(msg)
@@ -1732,7 +1731,9 @@ def _struct_from_dataclass_one(
1732
1731
  ):
1733
1732
  return String
1734
1733
  if is_optional_type(ann):
1735
- return _struct_from_dataclass_one(one(get_args(ann)), time_zone=time_zone)
1734
+ return _struct_from_dataclass_one(
1735
+ one(get_args(ann, optional_drop_none=True)), time_zone=time_zone
1736
+ )
1736
1737
  if is_frozenset_type(ann) or is_list_type(ann) or is_set_type(ann):
1737
1738
  return List(_struct_from_dataclass_one(one(get_args(ann)), time_zone=time_zone))
1738
1739
  raise _StructFromDataClassTypeError(ann=ann)
@@ -40,7 +40,7 @@ sentinel = Sentinel()
40
40
 
41
41
  def parse_sentinel(text: str, /) -> Sentinel:
42
42
  """Parse text into the Sentinel value."""
43
- if text == "" or search("Sentinel", text, flags=IGNORECASE):
43
+ if search("^(|sentinel|<sentinel>)$", text, flags=IGNORECASE):
44
44
  return sentinel
45
45
  raise ParseSentinelError(text=text)
46
46
 
@@ -25,9 +25,9 @@ DEFAULT_SEPARATOR = ","
25
25
 
26
26
  def parse_bool(text: str, /) -> bool:
27
27
  """Parse text into a boolean value."""
28
- if text == "0" or search("false", text, flags=IGNORECASE):
28
+ if search(r"^(0|False)$", text, flags=IGNORECASE):
29
29
  return False
30
- if text == "1" or search("true", text, flags=IGNORECASE):
30
+ if search(r"^(1|True)$", text, flags=IGNORECASE):
31
31
  return True
32
32
  raise ParseBoolError(text=text)
33
33
 
@@ -46,7 +46,7 @@ class ParseBoolError(Exception):
46
46
 
47
47
  def parse_none(text: str, /) -> None:
48
48
  """Parse text into the None value."""
49
- if text == "" or search("None", text, flags=IGNORECASE):
49
+ if search(r"^(|None)$", text, flags=IGNORECASE):
50
50
  return
51
51
  raise ParseNoneError(text=text)
52
52