assertpy2 2.27.1__tar.gz → 2.29.0__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 (270) hide show
  1. {assertpy2-2.27.1 → assertpy2-2.29.0}/PKG-INFO +1 -1
  2. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_dangling.py +21 -1
  3. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_builder_check_typing.py +72 -50
  4. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_capable_typing.py +32 -24
  5. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_check_typing.py +32 -22
  6. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_compare.py +292 -74
  7. assertpy2-2.29.0/assertpy2/_engine/_contract.py +579 -0
  8. assertpy2-2.29.0/assertpy2/_engine/_diff.py +916 -0
  9. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_equality.py +126 -30
  10. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_introspection.py +9 -4
  11. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_membership.py +123 -33
  12. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_mixin_base.py +48 -1
  13. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_negated_typing.py +296 -276
  14. assertpy2-2.29.0/assertpy2/_engine/_ordering.py +768 -0
  15. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_path.py +70 -12
  16. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_poll_typing.py +780 -377
  17. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_require.py +51 -1
  18. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_typing.py +77 -48
  19. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_hints.py +16 -15
  20. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_matcher_impls.py +294 -104
  21. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_satisfies.py +61 -31
  22. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/assertpy.py +158 -51
  23. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/async_assertions.py +70 -19
  24. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/base.py +133 -91
  25. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/bytes_mixin.py +14 -12
  26. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/collection.py +43 -31
  27. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/contains.py +98 -63
  28. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/dataframe.py +29 -16
  29. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/date.py +28 -29
  30. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/dict.py +17 -7
  31. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/dynamic.py +21 -9
  32. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/errors.py +16 -0
  33. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/exception.py +77 -8
  34. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/file.py +86 -18
  35. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/helpers.py +112 -46
  36. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/matchers.py +6 -4
  37. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/numeric.py +48 -71
  38. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/pytest_plugin.py +1 -1
  39. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/snapshot.py +23 -8
  40. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/string.py +52 -28
  41. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/warning.py +6 -4
  42. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/concepts/stability.md +17 -7
  43. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/concepts/type-safety.md +31 -9
  44. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/extending/custom-assertions.md +12 -2
  45. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/extending/integrations.md +185 -12
  46. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/getting-started/comparison.md +4 -3
  47. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/getting-started/migration.md +22 -4
  48. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/getting-started/quickstart.md +1 -1
  49. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/guides/assertions.md +70 -6
  50. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/guides/errors.md +17 -4
  51. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/guides/fluent.md +14 -1
  52. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/guides/matchers.md +19 -8
  53. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/guides/testing.md +8 -1
  54. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/index.md +2 -2
  55. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/recipes.md +5 -6
  56. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/core.md +2 -1
  57. assertpy2-2.29.0/docs/reference/dataframes.md +22 -0
  58. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/overview.md +3 -2
  59. {assertpy2-2.27.1 → assertpy2-2.29.0}/pyproject.toml +8 -2
  60. {assertpy2-2.27.1 → assertpy2-2.29.0}/scripts/generate_check_protocols.py +5 -0
  61. {assertpy2-2.27.1 → assertpy2-2.29.0}/scripts/generate_poll_protocols.py +262 -32
  62. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/api_snapshot.json +198 -196
  63. assertpy2-2.29.0/tests/chain_corpus.py +337 -0
  64. assertpy2-2.29.0/tests/chain_model.py +633 -0
  65. assertpy2-2.29.0/tests/chain_surfaces.py +226 -0
  66. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/poll_parity_baseline.py +2 -8
  67. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/poll_parity_cases.py +2 -2
  68. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/pyright_baseline.py +17 -7
  69. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_async.py +90 -0
  70. assertpy2-2.29.0/tests/test_call_awaitables.py +163 -0
  71. assertpy2-2.29.0/tests/test_chain_machine.py +657 -0
  72. assertpy2-2.29.0/tests/test_check.py +324 -0
  73. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_check_protocols.py +6 -3
  74. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_complexity.py +15 -13
  75. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_dangling.py +20 -0
  76. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_dataframe.py +2 -2
  77. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_datetime.py +25 -24
  78. assertpy2-2.29.0/tests/test_deep_nesting.py +437 -0
  79. assertpy2-2.29.0/tests/test_duality.py +1014 -0
  80. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_dynamic.py +10 -0
  81. assertpy2-2.29.0/tests/test_equality_signals.py +1146 -0
  82. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_evaluation_core.py +1055 -14
  83. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_expected_contract.py +33 -2
  84. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_expected_exception.py +381 -1
  85. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_expected_warning.py +34 -0
  86. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_hints.py +65 -8
  87. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_http.py +19 -1
  88. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_in.py +14 -0
  89. assertpy2-2.29.0/tests/test_integer_arguments.py +113 -0
  90. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_match_result.py +53 -0
  91. assertpy2-2.29.0/tests/test_matcher_algebra.py +230 -0
  92. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_matcher_parity.py +14 -1
  93. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_matcher_registry.py +15 -0
  94. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_matchers.py +136 -2
  95. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_not.py +2 -2
  96. assertpy2-2.29.0/tests/test_number_zoo.py +492 -0
  97. assertpy2-2.29.0/tests/test_numbers.py +2140 -0
  98. assertpy2-2.29.0/tests/test_numeric_questions.py +322 -0
  99. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_pin_coverage.py +8 -3
  100. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_poll_protocols.py +157 -18
  101. assertpy2-2.29.0/tests/test_prerequisites.py +376 -0
  102. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_property_based.py +370 -10
  103. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_protocol_parity.py +6 -3
  104. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_public_surface.py +2 -0
  105. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_pytest_plugin.py +27 -2
  106. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_recursive_compare.py +17 -0
  107. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_recursive_compare_config.py +136 -14
  108. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_rich_diff.py +7 -10
  109. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_soft.py +25 -1
  110. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_structural.py +878 -38
  111. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_sync_eventually.py +19 -0
  112. assertpy2-2.29.0/tests/test_type.py +311 -0
  113. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing.py +140 -19
  114. assertpy2-2.29.0/tests/test_typing_chain_corpus.py +38 -0
  115. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_claims.py +1 -0
  116. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_http.py +21 -1
  117. assertpy2-2.29.0/tests/test_unrenderable_values.py +244 -0
  118. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_vacuity_contract.py +226 -3
  119. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/typing_cases.py +60 -4
  120. assertpy2-2.29.0/tests/typing_chain_corpus_baseline.json +454 -0
  121. assertpy2-2.29.0/tests/typing_http.py +81 -0
  122. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/typing_integrations.py +2 -0
  123. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/typing_integrations_baseline.py +3 -1
  124. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/typing_negative_baseline.py +53 -4
  125. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/verdict_golden.txt +2 -2
  126. assertpy2-2.27.1/assertpy2/_engine/_contract.py +0 -166
  127. assertpy2-2.27.1/assertpy2/_engine/_diff.py +0 -712
  128. assertpy2-2.27.1/assertpy2/_engine/_ordering.py +0 -170
  129. assertpy2-2.27.1/docs/reference/dataframes.md +0 -5
  130. assertpy2-2.27.1/tests/test_check.py +0 -118
  131. assertpy2-2.27.1/tests/test_numbers.py +0 -963
  132. assertpy2-2.27.1/tests/test_type.py +0 -133
  133. assertpy2-2.27.1/tests/typing_http.py +0 -75
  134. {assertpy2-2.27.1 → assertpy2-2.29.0}/.gitignore +0 -0
  135. {assertpy2-2.27.1 → assertpy2-2.29.0}/CONTRIBUTING.md +0 -0
  136. {assertpy2-2.27.1 → assertpy2-2.29.0}/LICENSE +0 -0
  137. {assertpy2-2.27.1 → assertpy2-2.29.0}/README.md +0 -0
  138. {assertpy2-2.27.1 → assertpy2-2.29.0}/SECURITY.md +0 -0
  139. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/__init__.py +0 -0
  140. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_clustering.py +0 -0
  141. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/__init__.py +0 -0
  142. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_compat.py +0 -0
  143. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_operations.py +0 -0
  144. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_pairing.py +0 -0
  145. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_size.py +0 -0
  146. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_engine/_text.py +0 -0
  147. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_inline.py +0 -0
  148. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/_snapshot_codec.py +0 -0
  149. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/behave_matchers.py +0 -0
  150. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/extracting.py +0 -0
  151. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/http_mixin.py +0 -0
  152. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/json_mixin.py +0 -0
  153. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/outcome.py +0 -0
  154. {assertpy2-2.27.1 → assertpy2-2.29.0}/assertpy2/py.typed +0 -0
  155. {assertpy2-2.27.1 → assertpy2-2.29.0}/benchmarks/test_perf.py +0 -0
  156. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-equal.png +0 -0
  157. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-equal.svg +0 -0
  158. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-gallery.png +0 -0
  159. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-match.svg +0 -0
  160. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-sequence.svg +0 -0
  161. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-set.svg +0 -0
  162. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/assets/diff-string.svg +0 -0
  163. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/guides/data.md +0 -0
  164. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/logo-dark.svg +0 -0
  165. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/logo.svg +0 -0
  166. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/async.md +0 -0
  167. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/bytes.md +0 -0
  168. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/collections.md +0 -0
  169. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/containment.md +0 -0
  170. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/dates.md +0 -0
  171. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/dicts.md +0 -0
  172. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/dynamic.md +0 -0
  173. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/entry-points.md +0 -0
  174. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/errors.md +0 -0
  175. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/exceptions.md +0 -0
  176. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/extracting.md +0 -0
  177. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/files.md +0 -0
  178. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/http.md +0 -0
  179. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/json.md +0 -0
  180. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/matchers.md +0 -0
  181. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/numbers.md +0 -0
  182. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/snapshots.md +0 -0
  183. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/strings.md +0 -0
  184. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/reference/warnings.md +0 -0
  185. {assertpy2-2.27.1 → assertpy2-2.29.0}/docs/stylesheets/extra.css +0 -0
  186. {assertpy2-2.27.1 → assertpy2-2.29.0}/mkdocs.yml +0 -0
  187. {assertpy2-2.27.1 → assertpy2-2.29.0}/mkdocs_hooks.py +0 -0
  188. {assertpy2-2.27.1 → assertpy2-2.29.0}/scripts/mutation_report.py +0 -0
  189. {assertpy2-2.27.1 → assertpy2-2.29.0}/scripts/regenerate.py +0 -0
  190. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/api_surface.py +0 -0
  191. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/conftest.py +0 -0
  192. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/docs_fixtures.py +0 -0
  193. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/group_compat.py +0 -0
  194. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_api_compatibility.py +0 -0
  195. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_api_vocabulary.py +0 -0
  196. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_architecture_doc.py +0 -0
  197. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_async_predicates.py +0 -0
  198. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_attrs_support.py +0 -0
  199. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_behave_matchers.py +0 -0
  200. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_bool.py +0 -0
  201. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_boundary_cases.py +0 -0
  202. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_bytes.py +0 -0
  203. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_callable.py +0 -0
  204. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_capable_protocol.py +0 -0
  205. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_chaining.py +0 -0
  206. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_class.py +0 -0
  207. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_clustering.py +0 -0
  208. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_collection.py +0 -0
  209. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_core.py +0 -0
  210. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_custom_dict.py +0 -0
  211. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_custom_list.py +0 -0
  212. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_declared_floors.py +0 -0
  213. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_description.py +0 -0
  214. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_dict.py +0 -0
  215. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_dict_compare.py +0 -0
  216. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_docs_examples.py +0 -0
  217. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_docs_typing.py +0 -0
  218. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_equals.py +0 -0
  219. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_errors.py +0 -0
  220. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_exception_context.py +0 -0
  221. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_extensions.py +0 -0
  222. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_extracting.py +0 -0
  223. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_fail.py +0 -0
  224. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_file.py +0 -0
  225. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_grouped_soft.py +0 -0
  226. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_hostile_values.py +0 -0
  227. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_inline_record.py +0 -0
  228. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_inline_snapshot.py +0 -0
  229. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_iterable_cluster.py +0 -0
  230. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_json.py +0 -0
  231. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_list.py +0 -0
  232. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_message_elision.py +0 -0
  233. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_namedtuple.py +0 -0
  234. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_negated_protocols.py +0 -0
  235. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_none.py +0 -0
  236. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_openapi_contract.py +0 -0
  237. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_operation_contract.py +0 -0
  238. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_optional_integration_contracts.py +0 -0
  239. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_overload_order.py +0 -0
  240. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_overloads.py +0 -0
  241. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_pipeline.py +0 -0
  242. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_poll_parity.py +0 -0
  243. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_property_attrs.py +0 -0
  244. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_pyright_baseline.py +0 -0
  245. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_recursive_assertion.py +0 -0
  246. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_recursive_compare_attrs.py +0 -0
  247. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_recursive_compare_pydantic.py +0 -0
  248. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_refusals.py +0 -0
  249. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_regex_groups.py +0 -0
  250. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_requirement.py +0 -0
  251. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_same_as.py +0 -0
  252. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_satisfy.py +0 -0
  253. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_skip_guard.py +0 -0
  254. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_snapshots.py +0 -0
  255. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_soft_fail.py +0 -0
  256. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_string.py +0 -0
  257. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_surface_conformance.py +0 -0
  258. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_traceback.py +0 -0
  259. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_type_expression_failures.py +0 -0
  260. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_completeness.py +0 -0
  261. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_conformance.py +0 -0
  262. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_from_a_wheel.py +0 -0
  263. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_integrations.py +0 -0
  264. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_negative.py +0 -0
  265. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_typing_promises.py +0 -0
  266. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_verdict_corpus.py +0 -0
  267. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/test_warn.py +0 -0
  268. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/typing_harness.py +0 -0
  269. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/typing_promises.py +0 -0
  270. {assertpy2-2.27.1 → assertpy2-2.29.0}/tests/verdict_corpus.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: assertpy2
3
- Version: 2.27.1
3
+ Version: 2.29.0
4
4
  Summary: Fluent, fully typed assertion library for Python: your type checker sees only the assertions that fit the value, and every failure carries a structured diff. Soft assertions, polling, inline snapshots, OpenAPI contracts.
5
5
  Project-URL: Homepage, https://github.com/Solganis/assertpy2
6
6
  Project-URL: Repository, https://github.com/Solganis/assertpy2
@@ -40,7 +40,7 @@ from __future__ import annotations
40
40
  import ast
41
41
  import io
42
42
  import tokenize
43
- from typing import Final, NamedTuple
43
+ from typing import TYPE_CHECKING, Final, NamedTuple
44
44
 
45
45
  from ._engine._operations import (
46
46
  ALSO_ASSERTS,
@@ -52,6 +52,9 @@ from ._engine._operations import (
52
52
  WITHOUT_A_VERDICT,
53
53
  )
54
54
 
55
+ if TYPE_CHECKING:
56
+ import pathlib
57
+
55
58
  __tracebackhide__ = True
56
59
 
57
60
  # the builder factories and only those: everything else either asserts by itself or is not an entry point
@@ -440,6 +443,23 @@ def _silenced(statement: ast.stmt, marked: frozenset[int]) -> bool:
440
443
  return any(line in marked for line in range(statement.lineno, last + 1))
441
444
 
442
445
 
446
+ def read_module(path: pathlib.Path) -> str:
447
+ """A test module's text as the interpreter decodes it, which is what `findings` reads.
448
+
449
+ The encoding a PEP 263 cookie or a BOM declares, found the way `tokenize` finds it, and UTF-8 where
450
+ none is declared. A byte that still does not decode is replaced rather than refused: 3.10 to 3.13
451
+ import a module whose comment is not UTF-8, and reading it strictly aborted a whole run from the
452
+ collection hook. A comment's text is not something the check reads.
453
+ """
454
+ data = path.read_bytes()
455
+ try:
456
+ encoding = tokenize.detect_encoding(io.BytesIO(data).readline)[0]
457
+ except SyntaxError:
458
+ # a first line that is not UTF-8 and names no encoding, which 3.10 to 3.13 import all the same
459
+ encoding = "utf-8"
460
+ return data.decode(encoding, errors="replace")
461
+
462
+
443
463
  def findings(source: str, path: str, extra_entries: frozenset[str] = frozenset()) -> list[Finding]:
444
464
  """Report the offending statements in one module's source.
445
465
 
@@ -272,7 +272,15 @@ if TYPE_CHECKING:
272
272
  *items: _E | Matcher[_E],
273
273
  ) -> AssertionOutcome: ...
274
274
  @overload
275
- def does_not_contain(self: _CheckAnyValue[_CapableT], *items: str | Matcher[str]) -> AssertionOutcome: ...
275
+ def does_not_contain(
276
+ self: _CheckAnyValue[bytes] | _CheckAnyValue[bytearray], *items: object
277
+ ) -> AssertionOutcome: ...
278
+ @overload
279
+ def does_not_contain(
280
+ self: _CheckAnyValue[_FrameT_co] | _CheckAnyValue[_ArrayT_co], *items: object
281
+ ) -> AssertionOutcome: ...
282
+ @overload
283
+ def does_not_contain(self: _CheckAnyValue[_CapableT], *items: object) -> AssertionOutcome: ...
276
284
 
277
285
  @overload
278
286
  def contains_only(self: _CheckAnyValue[str], *items: str | Matcher[str]) -> AssertionOutcome: ...
@@ -709,10 +717,10 @@ if TYPE_CHECKING:
709
717
  | _CheckAnyValue[bytearray]
710
718
  | _CheckAnyValue[_FrameT_co]
711
719
  | _CheckAnyValue[_ArrayT_co],
712
- size: int,
720
+ size: SupportsIndex,
713
721
  ) -> AssertionOutcome: ...
714
722
  @overload
715
- def has_size_greater_than(self: _CheckAnyValue[_CapableT], size: int) -> AssertionOutcome: ...
723
+ def has_size_greater_than(self: _CheckAnyValue[_CapableT], size: SupportsIndex) -> AssertionOutcome: ...
716
724
 
717
725
  @overload
718
726
  def has_size_less_than(
@@ -726,10 +734,10 @@ if TYPE_CHECKING:
726
734
  | _CheckAnyValue[bytearray]
727
735
  | _CheckAnyValue[_FrameT_co]
728
736
  | _CheckAnyValue[_ArrayT_co],
729
- size: int,
737
+ size: SupportsIndex,
730
738
  ) -> AssertionOutcome: ...
731
739
  @overload
732
- def has_size_less_than(self: _CheckAnyValue[_CapableT], size: int) -> AssertionOutcome: ...
740
+ def has_size_less_than(self: _CheckAnyValue[_CapableT], size: SupportsIndex) -> AssertionOutcome: ...
733
741
 
734
742
  @overload
735
743
  def has_size_between(
@@ -743,11 +751,13 @@ if TYPE_CHECKING:
743
751
  | _CheckAnyValue[bytearray]
744
752
  | _CheckAnyValue[_FrameT_co]
745
753
  | _CheckAnyValue[_ArrayT_co],
746
- low: int,
747
- high: int,
754
+ low: SupportsIndex,
755
+ high: SupportsIndex,
748
756
  ) -> AssertionOutcome: ...
749
757
  @overload
750
- def has_size_between(self: _CheckAnyValue[_CapableT], low: int, high: int) -> AssertionOutcome: ...
758
+ def has_size_between(
759
+ self: _CheckAnyValue[_CapableT], low: SupportsIndex, high: SupportsIndex
760
+ ) -> AssertionOutcome: ...
751
761
 
752
762
  @overload
753
763
  def is_empty(
@@ -820,46 +830,16 @@ if TYPE_CHECKING:
820
830
  def is_not_inf(self: _CheckAnyValue[SupportsFloat | SupportsIndex]) -> AssertionOutcome: ...
821
831
 
822
832
  @overload
823
- def is_close_to(
824
- self: _CheckAnyValue[bool] | _CheckAnyValue[int] | _CheckAnyValue[float], other: _Number, tolerance: _Number
825
- ) -> AssertionOutcome: ...
826
- @overload
827
- def is_close_to(
828
- self: _CheckAnyValue[datetime.datetime], other: datetime.datetime, tolerance: datetime.timedelta
829
- ) -> AssertionOutcome: ...
830
- @overload
831
- def is_close_to(
832
- self: _CheckAnyValue[SupportsFloat | SupportsIndex],
833
- other: SupportsFloat | SupportsIndex,
834
- tolerance: SupportsFloat | SupportsIndex,
835
- ) -> AssertionOutcome: ...
836
- @overload
837
- def is_close_to(
838
- self: _CheckAnyValue[SupportsFloat | SupportsIndex], other: _Number, tolerance: _Number
839
- ) -> AssertionOutcome: ...
840
-
841
- @overload
842
- def is_not_close_to(
843
- self: _CheckAnyValue[bool] | _CheckAnyValue[int] | _CheckAnyValue[float], other: _Number, tolerance: _Number
844
- ) -> AssertionOutcome: ...
845
- @overload
846
- def is_not_close_to(
847
- self: _CheckAnyValue[datetime.datetime], other: datetime.datetime, tolerance: datetime.timedelta
848
- ) -> AssertionOutcome: ...
849
- @overload
850
- def is_not_close_to(
851
- self: _CheckAnyValue[SupportsFloat | SupportsIndex],
852
- other: SupportsFloat | SupportsIndex,
853
- tolerance: SupportsFloat | SupportsIndex,
833
+ def is_not_between(
834
+ self: _CheckAnyValue[bool] | _CheckAnyValue[int] | _CheckAnyValue[float], low: _Number, high: _Number
854
835
  ) -> AssertionOutcome: ...
855
836
  @overload
856
- def is_not_close_to(
857
- self: _CheckAnyValue[_CapableT], other: _Number, tolerance: _Number
837
+ def is_not_between(
838
+ self: _CheckAnyValue[datetime.datetime], low: datetime.datetime, high: datetime.datetime
858
839
  ) -> AssertionOutcome: ...
859
-
860
840
  @overload
861
841
  def is_not_between(
862
- self: _CheckAnyValue[bool] | _CheckAnyValue[int] | _CheckAnyValue[float], low: _Number, high: _Number
842
+ self: _CheckAnyValue[datetime.date], low: datetime.date, high: datetime.date
863
843
  ) -> AssertionOutcome: ...
864
844
  @overload
865
845
  def is_not_between(self: _CheckAnyValue[_T], low: Any, high: Any) -> AssertionOutcome: ...
@@ -901,6 +881,44 @@ if TYPE_CHECKING:
901
881
  @overload
902
882
  def is_not_zero(self: _CheckAnyValue[_CapableT]) -> AssertionOutcome: ...
903
883
 
884
+ @overload
885
+ def is_close_to(
886
+ self: _CheckAnyValue[int] | _CheckAnyValue[float], other: _Number, tolerance: _Number
887
+ ) -> AssertionOutcome: ...
888
+ @overload
889
+ def is_close_to(
890
+ self: _CheckAnyValue[datetime.datetime], other: datetime.datetime, tolerance: datetime.timedelta
891
+ ) -> AssertionOutcome: ...
892
+ @overload
893
+ def is_close_to(
894
+ self: _CheckAnyValue[SupportsFloat | SupportsIndex],
895
+ other: SupportsFloat | SupportsIndex,
896
+ tolerance: SupportsFloat | SupportsIndex,
897
+ ) -> AssertionOutcome: ...
898
+ @overload
899
+ def is_close_to(
900
+ self: _CheckAnyValue[SupportsFloat | SupportsIndex], other: _Number, tolerance: _Number
901
+ ) -> AssertionOutcome: ...
902
+
903
+ @overload
904
+ def is_not_close_to(
905
+ self: _CheckAnyValue[int] | _CheckAnyValue[float], other: _Number, tolerance: _Number
906
+ ) -> AssertionOutcome: ...
907
+ @overload
908
+ def is_not_close_to(
909
+ self: _CheckAnyValue[datetime.datetime], other: datetime.datetime, tolerance: datetime.timedelta
910
+ ) -> AssertionOutcome: ...
911
+ @overload
912
+ def is_not_close_to(
913
+ self: _CheckAnyValue[SupportsFloat | SupportsIndex],
914
+ other: SupportsFloat | SupportsIndex,
915
+ tolerance: SupportsFloat | SupportsIndex,
916
+ ) -> AssertionOutcome: ...
917
+ @overload
918
+ def is_not_close_to(
919
+ self: _CheckAnyValue[_CapableT], other: _Number, tolerance: _Number
920
+ ) -> AssertionOutcome: ...
921
+
904
922
  @overload
905
923
  def is_even(self: _CheckAnyValue[int] | _CheckAnyValue[float]) -> AssertionOutcome: ...
906
924
  @overload
@@ -912,9 +930,11 @@ if TYPE_CHECKING:
912
930
  def is_odd(self: _CheckAnyValue[int]) -> AssertionOutcome: ...
913
931
 
914
932
  @overload
915
- def is_divisible_by(self: _CheckAnyValue[int] | _CheckAnyValue[float], divisor: int) -> AssertionOutcome: ...
933
+ def is_divisible_by(
934
+ self: _CheckAnyValue[int] | _CheckAnyValue[float], divisor: SupportsIndex
935
+ ) -> AssertionOutcome: ...
916
936
  @overload
917
- def is_divisible_by(self: _CheckAnyValue[int], divisor: int) -> AssertionOutcome: ...
937
+ def is_divisible_by(self: _CheckAnyValue[int], divisor: SupportsIndex) -> AssertionOutcome: ...
918
938
 
919
939
  @overload
920
940
  def contains_key(self: _CheckAnyValue[dict[_K, _V]], *keys: _K | Matcher[_K]) -> AssertionOutcome: ...
@@ -1090,10 +1110,12 @@ if TYPE_CHECKING:
1090
1110
 
1091
1111
  @overload
1092
1112
  def has_byte_at(
1093
- self: _CheckAnyValue[bytes] | _CheckAnyValue[bytearray], index: int, expected: int
1113
+ self: _CheckAnyValue[bytes] | _CheckAnyValue[bytearray], index: SupportsIndex, expected: SupportsIndex
1094
1114
  ) -> AssertionOutcome: ...
1095
1115
  @overload
1096
- def has_byte_at(self: _CheckAnyValue[bytes | bytearray], index: int, expected: int) -> AssertionOutcome: ...
1116
+ def has_byte_at(
1117
+ self: _CheckAnyValue[bytes | bytearray], index: SupportsIndex, expected: SupportsIndex
1118
+ ) -> AssertionOutcome: ...
1097
1119
 
1098
1120
  @overload
1099
1121
  def is_hex_equal_to(
@@ -1248,11 +1270,11 @@ if TYPE_CHECKING:
1248
1270
 
1249
1271
  def is_type_of(self, some_type: type) -> AssertionOutcome: ...
1250
1272
 
1251
- def is_subclass_of(self, some_class: type) -> AssertionOutcome: ...
1273
+ def is_subclass_of(self, some_class: ClassInfo) -> AssertionOutcome: ...
1252
1274
 
1253
- def is_length(self, length: int) -> AssertionOutcome: ...
1275
+ def is_length(self, length: SupportsIndex) -> AssertionOutcome: ...
1254
1276
 
1255
- def is_length_between(self, low: int, high: int) -> AssertionOutcome: ...
1277
+ def is_length_between(self, low: SupportsIndex, high: SupportsIndex) -> AssertionOutcome: ...
1256
1278
 
1257
1279
  def is_callable(self) -> AssertionOutcome: ...
1258
1280
 
@@ -45,6 +45,7 @@ if TYPE_CHECKING:
45
45
  _ExpectedCompletionAssertion,
46
46
  _ExpectedRaiseAssertion,
47
47
  _ExpectedWarningAssertion,
48
+ _Landed,
48
49
  _ListAssertion,
49
50
  )
50
51
 
@@ -168,11 +169,11 @@ if TYPE_CHECKING:
168
169
  @overload
169
170
  def last(self) -> Self: ...
170
171
  @overload
171
- def element(self: _CapableAssertion[Mapping[_K, _V]], index: int) -> AssertionBuilder[_K]: ...
172
+ def element(self: _CapableAssertion[Mapping[_K, _V]], index: SupportsIndex) -> AssertionBuilder[_K]: ...
172
173
  @overload
173
- def element(self: _ElementSource[_E], index: int) -> AssertionBuilder[_E]: ...
174
+ def element(self: _ElementSource[_E], index: SupportsIndex) -> AssertionBuilder[_E]: ...
174
175
  @overload
175
- def element(self, index: int) -> Self: ...
176
+ def element(self, index: SupportsIndex) -> Self: ...
176
177
  @overload
177
178
  def mapped(self: _ElementSource[_E], func: Callable[[_E], _R]) -> AssertionBuilder[list[_R]]: ...
178
179
  @overload
@@ -205,7 +206,10 @@ if TYPE_CHECKING:
205
206
  trace: bool = ...,
206
207
  ) -> _SyncPoll[Any]: ...
207
208
  # where the callable view lands: flattened, the runtime's `-> Self` kept a caught message typed as the callable
208
- def raises(self: _CapableAssertion[_Callable], ex: type) -> _ExpectedRaiseAssertion[Any]: ...
209
+ @overload
210
+ def raises(self: _CapableAssertion[_Callable], ex: type[_Landed]) -> _ExpectedRaiseAssertion[Any, _Landed]: ...
211
+ @overload
212
+ def raises(self: _CapableAssertion[_Callable], ex: type) -> _ExpectedRaiseAssertion[Any, BaseException]: ...
209
213
  def does_not_raise(self: _CapableAssertion[_Callable], ex: type) -> _ExpectedCompletionAssertion[Any]: ...
210
214
  def warns(
211
215
  self: _CapableAssertion[_Callable], warning: type[Warning] = ...
@@ -243,7 +247,7 @@ if TYPE_CHECKING:
243
247
  def all_satisfy(self, matcher: Matcher[Any] | Callable[..., bool], *, allow_empty: bool = ...) -> Self: ...
244
248
  def any_satisfy(self, matcher: Matcher[Any] | Callable[..., bool]) -> Self: ...
245
249
  def at_json_path(self, path: str) -> AssertionBuilder[Any]: ...
246
- def caused_by(self, ex: type) -> AssertionBuilder[Any]: ...
250
+ def caused_by(self, ex: ClassInfo) -> AssertionBuilder[Any]: ...
247
251
  def conforms_to_openapi(
248
252
  self,
249
253
  spec: dict[str, Any],
@@ -306,15 +310,15 @@ if TYPE_CHECKING:
306
310
  def filtered_on(self, predicate: Matcher[Any] | Callable[[Any], bool]) -> _ListAssertion[Any]: ...
307
311
  def flat_mapped(self, func: Callable[[Any], Iterable[Any]]) -> _ListAssertion[Any]: ...
308
312
  def has_byte_at(
309
- self: _CapableAssertion[bytes | bytearray], index: int, expected: int
313
+ self: _CapableAssertion[bytes | bytearray], index: SupportsIndex, expected: SupportsIndex
310
314
  ) -> _CapableAssertion[_CapableT_co]: ...
311
315
  def has_json_path(self, path: str) -> Self: ...
312
316
  def has_no_none_fields(self, *, allow_empty: bool = ...) -> Self: ...
313
- def has_root_cause(self, ex: type) -> AssertionBuilder[Any]: ...
317
+ def has_root_cause(self, ex: ClassInfo) -> AssertionBuilder[Any]: ...
314
318
  def has_same_size_as(self, other: Sized) -> Self: ...
315
- def has_size_between(self, low: int, high: int) -> Self: ...
316
- def has_size_greater_than(self, size: int) -> Self: ...
317
- def has_size_less_than(self, size: int) -> Self: ...
319
+ def has_size_between(self, low: SupportsIndex, high: SupportsIndex) -> Self: ...
320
+ def has_size_greater_than(self, size: SupportsIndex) -> Self: ...
321
+ def has_size_less_than(self, size: SupportsIndex) -> Self: ...
318
322
  def is_after(
319
323
  self: _CapableAssertion[datetime.datetime], other: datetime.datetime
320
324
  ) -> _CapableAssertion[_CapableT_co]: ...
@@ -343,7 +347,9 @@ if TYPE_CHECKING:
343
347
  ) -> _CapableAssertion[_CapableT_co]: ...
344
348
  def is_digit(self: _CapableAssertion[str]) -> _CapableAssertion[_CapableT_co]: ...
345
349
  def is_directory(self: _CapableAssertion[_PathLike]) -> _CapableAssertion[_CapableT_co]: ...
346
- def is_divisible_by(self: _CapableAssertion[int], divisor: int) -> _CapableAssertion[_CapableT_co]: ...
350
+ def is_divisible_by(
351
+ self: _CapableAssertion[int], divisor: SupportsIndex
352
+ ) -> _CapableAssertion[_CapableT_co]: ...
347
353
  def is_empty(self) -> Self: ...
348
354
  def is_equal_to(self, other: object, **kwargs: object) -> Self: ...
349
355
  def is_equal_to_ignoring_case(self: _CapableAssertion[str], other: str) -> _CapableAssertion[_CapableT_co]: ...
@@ -374,8 +380,8 @@ if TYPE_CHECKING:
374
380
  def is_in(self, *items: object) -> Self: ...
375
381
  def is_inf(self: _CapableAssertion[SupportsFloat | SupportsIndex]) -> _CapableAssertion[_CapableT_co]: ...
376
382
  def is_iterable(self) -> Self: ...
377
- def is_length(self, length: int) -> Self: ...
378
- def is_length_between(self, low: int, high: int) -> Self: ...
383
+ def is_length(self, length: SupportsIndex) -> Self: ...
384
+ def is_length_between(self, low: SupportsIndex, high: SupportsIndex) -> Self: ...
379
385
  def is_less_than(self: _CapableAssertion[_Orderable], other: object) -> _CapableAssertion[_CapableT_co]: ...
380
386
  def is_less_than_or_equal_to(
381
387
  self: _CapableAssertion[_Orderable], other: object
@@ -407,7 +413,7 @@ if TYPE_CHECKING:
407
413
  def is_sorted(
408
414
  self, key: Callable[[Any], Any] = ..., reverse: bool = ..., *, allow_empty: bool = ...
409
415
  ) -> Self: ...
410
- def is_subclass_of(self, some_class: type) -> Self: ...
416
+ def is_subclass_of(self, some_class: ClassInfo) -> Self: ...
411
417
  def is_subset_of(self, *supersets: object, allow_empty: bool = ...) -> Self: ...
412
418
  def is_true(self) -> Self: ...
413
419
  def is_type_of(self, some_type: type) -> Self: ...
@@ -492,7 +498,7 @@ if TYPE_CHECKING:
492
498
  self, matcher: Matcher[Any] | Callable[..., bool], *, allow_empty: bool = ...
493
499
  ) -> _CapableAssertion[_CapableT_co]: ...
494
500
  def any_satisfy(self, matcher: Matcher[Any] | Callable[..., bool]) -> _CapableAssertion[_CapableT_co]: ...
495
- def caused_by(self, ex: type) -> _CapableAssertion[_CapableT_co]: ...
501
+ def caused_by(self, ex: ClassInfo) -> _CapableAssertion[_CapableT_co]: ...
496
502
  def conforms_to_openapi(
497
503
  self,
498
504
  spec: dict[str, Any],
@@ -554,15 +560,15 @@ if TYPE_CHECKING:
554
560
  self: _NegatedCapableAssertion[str], pattern: str, group: int | str = ...
555
561
  ) -> _CapableAssertion[_CapableT_co]: ...
556
562
  def has_byte_at(
557
- self: _NegatedCapableAssertion[bytes | bytearray], index: int, expected: int
563
+ self: _NegatedCapableAssertion[bytes | bytearray], index: SupportsIndex, expected: SupportsIndex
558
564
  ) -> _CapableAssertion[_CapableT_co]: ...
559
565
  def has_json_path(self, path: str) -> _CapableAssertion[_CapableT_co]: ...
560
566
  def has_no_none_fields(self, *, allow_empty: bool = ...) -> _CapableAssertion[_CapableT_co]: ...
561
- def has_root_cause(self, ex: type) -> _CapableAssertion[_CapableT_co]: ...
567
+ def has_root_cause(self, ex: ClassInfo) -> _CapableAssertion[_CapableT_co]: ...
562
568
  def has_same_size_as(self, other: Sized) -> _CapableAssertion[_CapableT_co]: ...
563
- def has_size_between(self, low: int, high: int) -> _CapableAssertion[_CapableT_co]: ...
564
- def has_size_greater_than(self, size: int) -> _CapableAssertion[_CapableT_co]: ...
565
- def has_size_less_than(self, size: int) -> _CapableAssertion[_CapableT_co]: ...
569
+ def has_size_between(self, low: SupportsIndex, high: SupportsIndex) -> _CapableAssertion[_CapableT_co]: ...
570
+ def has_size_greater_than(self, size: SupportsIndex) -> _CapableAssertion[_CapableT_co]: ...
571
+ def has_size_less_than(self, size: SupportsIndex) -> _CapableAssertion[_CapableT_co]: ...
566
572
  def is_after(
567
573
  self: _NegatedCapableAssertion[datetime.datetime], other: datetime.datetime
568
574
  ) -> _CapableAssertion[_CapableT_co]: ...
@@ -593,7 +599,9 @@ if TYPE_CHECKING:
593
599
  ) -> _CapableAssertion[_CapableT_co]: ...
594
600
  def is_digit(self: _NegatedCapableAssertion[str]) -> _CapableAssertion[_CapableT_co]: ...
595
601
  def is_directory(self: _NegatedCapableAssertion[_PathLike]) -> _CapableAssertion[_CapableT_co]: ...
596
- def is_divisible_by(self: _NegatedCapableAssertion[int], divisor: int) -> _CapableAssertion[_CapableT_co]: ...
602
+ def is_divisible_by(
603
+ self: _NegatedCapableAssertion[int], divisor: SupportsIndex
604
+ ) -> _CapableAssertion[_CapableT_co]: ...
597
605
  def is_empty(self) -> _CapableAssertion[_CapableT_co]: ...
598
606
  def is_equal_to(self, other: object, **kwargs: object) -> _CapableAssertion[_CapableT_co]: ...
599
607
  def is_equal_to_ignoring_case(
@@ -630,8 +638,8 @@ if TYPE_CHECKING:
630
638
  self: _NegatedCapableAssertion[SupportsFloat | SupportsIndex],
631
639
  ) -> _CapableAssertion[_CapableT_co]: ...
632
640
  def is_iterable(self) -> _CapableAssertion[_CapableT_co]: ...
633
- def is_length(self, length: int) -> _CapableAssertion[_CapableT_co]: ...
634
- def is_length_between(self, low: int, high: int) -> _CapableAssertion[_CapableT_co]: ...
641
+ def is_length(self, length: SupportsIndex) -> _CapableAssertion[_CapableT_co]: ...
642
+ def is_length_between(self, low: SupportsIndex, high: SupportsIndex) -> _CapableAssertion[_CapableT_co]: ...
635
643
  def is_less_than(
636
644
  self: _NegatedCapableAssertion[_Orderable], other: object
637
645
  ) -> _CapableAssertion[_CapableT_co]: ...
@@ -671,7 +679,7 @@ if TYPE_CHECKING:
671
679
  def is_sorted(
672
680
  self, key: Callable[[Any], Any] = ..., reverse: bool = ..., *, allow_empty: bool = ...
673
681
  ) -> _CapableAssertion[_CapableT_co]: ...
674
- def is_subclass_of(self, some_class: type) -> _CapableAssertion[_CapableT_co]: ...
682
+ def is_subclass_of(self, some_class: ClassInfo) -> _CapableAssertion[_CapableT_co]: ...
675
683
  def is_subset_of(self, *supersets: object, allow_empty: bool = ...) -> _CapableAssertion[_CapableT_co]: ...
676
684
  def is_true(self) -> _CapableAssertion[_CapableT_co]: ...
677
685
  def is_type_of(self, some_type: type) -> _CapableAssertion[_CapableT_co]: ...
@@ -32,6 +32,7 @@ if TYPE_CHECKING:
32
32
  _ArrayT_co,
33
33
  _CapableT,
34
34
  _FrameT_co,
35
+ _Landed,
35
36
  _ObjectAssertion,
36
37
  _Other,
37
38
  _P_co,
@@ -41,6 +42,8 @@ if TYPE_CHECKING:
41
42
  _KeySpecs = Hashable | list[Hashable] | set[Hashable] | frozenset[Hashable]
42
43
 
43
44
  _E = TypeVar("_E")
45
+ # a verdict reads no exception back, so the twin's is covariant where the view's is not
46
+ _Exc_co = TypeVar("_Exc_co", bound=BaseException, covariant=True)
44
47
  _N = TypeVar("_N", int, float)
45
48
  _K = TypeVar("_K")
46
49
  _V = TypeVar("_V")
@@ -60,9 +63,9 @@ if TYPE_CHECKING:
60
63
  """The verdict twin of `_SizedAssertion`."""
61
64
 
62
65
  def has_same_size_as(self, other: Sized) -> AssertionOutcome: ...
63
- def has_size_greater_than(self, size: int) -> AssertionOutcome: ...
64
- def has_size_less_than(self, size: int) -> AssertionOutcome: ...
65
- def has_size_between(self, low: int, high: int) -> AssertionOutcome: ...
66
+ def has_size_greater_than(self, size: SupportsIndex) -> AssertionOutcome: ...
67
+ def has_size_less_than(self, size: SupportsIndex) -> AssertionOutcome: ...
68
+ def has_size_between(self, low: SupportsIndex, high: SupportsIndex) -> AssertionOutcome: ...
66
69
  def is_empty(self) -> AssertionOutcome: ...
67
70
  def is_not_empty(self) -> AssertionOutcome: ...
68
71
  @property
@@ -92,8 +95,6 @@ if TYPE_CHECKING:
92
95
  def is_not_nan(self) -> AssertionOutcome: ...
93
96
  def is_inf(self) -> AssertionOutcome: ...
94
97
  def is_not_inf(self) -> AssertionOutcome: ...
95
- def is_close_to(self, other: _Number, tolerance: _Number) -> AssertionOutcome: ...
96
- def is_not_close_to(self, other: _Number, tolerance: _Number) -> AssertionOutcome: ...
97
98
  def is_not_between(self, low: _Number, high: _Number) -> AssertionOutcome: ...
98
99
  def is_between(self, low: _Number, high: _Number) -> AssertionOutcome: ...
99
100
  def is_greater_than(self, other: _Number) -> AssertionOutcome: ...
@@ -150,12 +151,6 @@ if TYPE_CHECKING:
150
151
  @property
151
152
  def not_(self) -> Self: ...
152
153
 
153
- class _CheckReturningAssertion(Protocol):
154
- """The verdict twin of `_ReturningAssertion`."""
155
-
156
- @property
157
- def not_(self) -> Self: ...
158
-
159
154
  class _CheckZeroAssertion(Protocol):
160
155
  """The verdict twin of `_ZeroAssertion`."""
161
156
 
@@ -188,9 +183,9 @@ if TYPE_CHECKING:
188
183
  def is_type_of(self, some_type: type) -> AssertionOutcome: ...
189
184
  def is_instance_of(self, some_class: ClassInfo) -> AssertionOutcome: ...
190
185
  def is_instance_of_any(self, *some_classes: ClassInfo) -> AssertionOutcome: ...
191
- def is_subclass_of(self, some_class: type) -> AssertionOutcome: ...
192
- def is_length(self, length: int) -> AssertionOutcome: ...
193
- def is_length_between(self, low: int, high: int) -> AssertionOutcome: ...
186
+ def is_subclass_of(self, some_class: ClassInfo) -> AssertionOutcome: ...
187
+ def is_length(self, length: SupportsIndex) -> AssertionOutcome: ...
188
+ def is_length_between(self, low: SupportsIndex, high: SupportsIndex) -> AssertionOutcome: ...
194
189
  def is_callable(self) -> AssertionOutcome: ...
195
190
  def is_not_callable(self) -> AssertionOutcome: ...
196
191
  def is_iterable(self) -> AssertionOutcome: ...
@@ -456,6 +451,8 @@ if TYPE_CHECKING:
456
451
  class _CheckNumericAssertion(_CheckRealNumberAssertion, _CheckZeroAssertion, _CheckCoreAssertion, Protocol[_N]):
457
452
  """The verdict twin of `_NumericAssertion`."""
458
453
 
454
+ def is_close_to(self, other: _Number, tolerance: _Number) -> AssertionOutcome: ...
455
+ def is_not_close_to(self, other: _Number, tolerance: _Number) -> AssertionOutcome: ...
459
456
  @overload
460
457
  def satisfies(self, matcher: Callable[[_N], TypeIs[str]]) -> AssertionOutcome: ...
461
458
  @overload
@@ -492,7 +489,7 @@ if TYPE_CHECKING:
492
489
  def satisfies(self, matcher: Matcher[_N] | Callable[[_N], object]) -> AssertionOutcome: ...
493
490
  def is_even(self) -> AssertionOutcome: ...
494
491
  def is_odd(self) -> AssertionOutcome: ...
495
- def is_divisible_by(self, divisor: int) -> AssertionOutcome: ...
492
+ def is_divisible_by(self, divisor: SupportsIndex) -> AssertionOutcome: ...
496
493
  @property
497
494
  def not_(self) -> Self: ...
498
495
 
@@ -587,6 +584,7 @@ if TYPE_CHECKING:
587
584
  """The verdict twin of `_CollectionShapedAssertion`."""
588
585
 
589
586
  def contains(self, *items: object) -> AssertionOutcome: ...
587
+ def does_not_contain(self, *items: object) -> AssertionOutcome: ...
590
588
  def contains_only(self, *items: object) -> AssertionOutcome: ...
591
589
  @property
592
590
  def not_(self) -> Self: ...
@@ -622,6 +620,7 @@ if TYPE_CHECKING:
622
620
  def is_less_than(self, other: datetime.date) -> AssertionOutcome: ...
623
621
  def is_less_than_or_equal_to(self, other: datetime.date) -> AssertionOutcome: ...
624
622
  def is_between(self, low: datetime.date, high: datetime.date) -> AssertionOutcome: ...
623
+ def is_not_between(self, low: datetime.date, high: datetime.date) -> AssertionOutcome: ...
625
624
  @property
626
625
  def not_(self) -> Self: ...
627
626
 
@@ -633,6 +632,7 @@ if TYPE_CHECKING:
633
632
  def is_less_than(self, other: datetime.datetime) -> AssertionOutcome: ...
634
633
  def is_less_than_or_equal_to(self, other: datetime.datetime) -> AssertionOutcome: ...
635
634
  def is_between(self, low: datetime.datetime, high: datetime.datetime) -> AssertionOutcome: ...
635
+ def is_not_between(self, low: datetime.datetime, high: datetime.datetime) -> AssertionOutcome: ...
636
636
  def is_before(self, other: datetime.datetime) -> AssertionOutcome: ...
637
637
  def is_after(self, other: datetime.datetime) -> AssertionOutcome: ...
638
638
  def is_before_or_equal_to(self, other: datetime.datetime) -> AssertionOutcome: ...
@@ -655,6 +655,7 @@ if TYPE_CHECKING:
655
655
  """The verdict twin of `_BytesAssertion`."""
656
656
 
657
657
  def contains(self, *items: object) -> AssertionOutcome: ...
658
+ def does_not_contain(self, *items: object) -> AssertionOutcome: ...
658
659
  def is_sorted(
659
660
  self, key: Callable[[int], object] = ..., reverse: bool = ..., *, allow_empty: bool = ...
660
661
  ) -> AssertionOutcome: ...
@@ -664,7 +665,7 @@ if TYPE_CHECKING:
664
665
  def is_valid_encoding(self, encoding: str) -> AssertionOutcome: ...
665
666
  def starts_with_bytes(self, prefix: bytes | bytearray) -> AssertionOutcome: ...
666
667
  def contains_bytes(self, sub: bytes | bytearray) -> AssertionOutcome: ...
667
- def has_byte_at(self, index: int, expected: int) -> AssertionOutcome: ...
668
+ def has_byte_at(self, index: SupportsIndex, expected: SupportsIndex) -> AssertionOutcome: ...
668
669
  def is_hex_equal_to(self, expected_hex: str) -> AssertionOutcome: ...
669
670
  def is_greater_than(self, other: bytes | bytearray) -> AssertionOutcome: ...
670
671
  def is_greater_than_or_equal_to(self, other: bytes | bytearray) -> AssertionOutcome: ...
@@ -673,19 +674,28 @@ if TYPE_CHECKING:
673
674
  @property
674
675
  def not_(self) -> Self: ...
675
676
 
676
- class _CheckInvokedAssertion(_CheckTextAssertion, Protocol):
677
+ class _CheckInvokedAssertion(_CheckTextAssertion, Protocol[_Exc_co]):
677
678
  """The verdict twin of `_InvokedAssertion`."""
678
679
 
679
- def caused_by(self, ex: type) -> AssertionOutcome: ...
680
+ @overload
681
+ def caused_by(self, ex: type[_Landed]) -> AssertionOutcome: ...
682
+ @overload
683
+ def caused_by(self, ex: ClassInfo) -> AssertionOutcome: ...
684
+ @overload
685
+ def error_of(self, ex: type[_Landed]) -> AssertionOutcome: ...
686
+ @overload
680
687
  def error_of(self, ex: type) -> AssertionOutcome: ...
681
688
  def does_not_contain_error(self, *ex_types: type) -> AssertionOutcome: ...
682
- def has_root_cause(self, ex: type) -> AssertionOutcome: ...
689
+ @overload
690
+ def has_root_cause(self, ex: type[_Landed]) -> AssertionOutcome: ...
691
+ @overload
692
+ def has_root_cause(self, ex: ClassInfo) -> AssertionOutcome: ...
683
693
  def contains_error(self, *ex_types: type) -> AssertionOutcome: ...
684
694
  def matches_error_tree(self, *expected: type | list[Any]) -> AssertionOutcome: ...
685
695
  @property
686
696
  def not_(self) -> Self: ...
687
697
 
688
- class _CheckWarnedAssertion(_CheckTextAssertion, _CheckReturningAssertion, Protocol):
698
+ class _CheckWarnedAssertion(_CheckTextAssertion, Protocol[_P_co]):
689
699
  """The verdict twin of `_WarnedAssertion`."""
690
700
 
691
701
  @property
@@ -697,13 +707,13 @@ if TYPE_CHECKING:
697
707
  @property
698
708
  def not_(self) -> Self: ...
699
709
 
700
- class _CheckCompletedAssertion(_CheckCallableAssertion[_P_co], _CheckReturningAssertion, Protocol[_P_co]):
710
+ class _CheckCompletedAssertion(_CheckCallableAssertion[_P_co], Protocol[_P_co]):
701
711
  """The verdict twin of `_CompletedAssertion`."""
702
712
 
703
713
  @property
704
714
  def not_(self) -> Self: ...
705
715
 
706
- class _CheckExpectedRaiseAssertion(_CheckCallableAssertion[_P_co], Protocol[_P_co]):
716
+ class _CheckExpectedRaiseAssertion(_CheckCallableAssertion[_P_co], Protocol[_P_co, _Exc_co]):
707
717
  """The verdict twin of `_ExpectedRaiseAssertion`."""
708
718
 
709
719
  def when_called_with(self, *some_args: object, **some_kwargs: object) -> AssertionOutcome: ...