Return the AST statements to replace the ast.Assert instance. This rewrites the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false.
(self, assert_: ast.Assert)
| 843 | return res, self.explanation_param(self.display(res)) |
| 844 | |
| 845 | def visit_Assert(self, assert_: ast.Assert) -> list[ast.stmt]: |
| 846 | class="st">"""Return the AST statements to replace the ast.Assert instance. |
| 847 | |
| 848 | This rewrites the test of an assertion to provide |
| 849 | intermediate values and replace it with an if statement which |
| 850 | raises an assertion error with a detailed explanation in case |
| 851 | the expression is false. |
| 852 | class="st">""" |
| 853 | if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1: |
| 854 | import warnings |
| 855 | |
| 856 | from _pytest.warning_types import PytestAssertRewriteWarning |
| 857 | |
| 858 | class="cm"># TODO: This assert should not be needed. |
| 859 | assert self.module_path is not None |
| 860 | warnings.warn_explicit( |
| 861 | PytestAssertRewriteWarning( |
| 862 | class="st">"assertion is always true, perhaps remove parentheses?" |
| 863 | ), |
| 864 | category=None, |
| 865 | filename=self.module_path, |
| 866 | lineno=assert_.lineno, |
| 867 | ) |
| 868 | |
| 869 | self.statements: list[ast.stmt] = [] |
| 870 | self.variables: list[str] = [] |
| 871 | self.variable_counter = itertools.count() |
| 872 | |
| 873 | if self.enable_assertion_pass_hook: |
| 874 | self.format_variables: list[str] = [] |
| 875 | |
| 876 | self.stack: list[dict[str, ast.expr]] = [] |
| 877 | self.expl_stmts: list[ast.stmt] = [] |
| 878 | self.push_format_context() |
| 879 | class="cm"># Rewrite assert into a bunch of statements. |
| 880 | top_condition, explanation = self.visit(assert_.test) |
| 881 | |
| 882 | negation = ast.UnaryOp(ast.Not(), top_condition) |
| 883 | |
| 884 | if self.enable_assertion_pass_hook: class="cm"># Experimental pytest_assertion_pass hook |
| 885 | msg = self.pop_format_context(ast.Constant(explanation)) |
| 886 | |
| 887 | class="cm"># Failed |
| 888 | if assert_.msg: |
| 889 | assertmsg = self.helper(class="st">"_format_assertmsg", assert_.msg) |
| 890 | gluestr = class="st">"\n>assert " |
| 891 | else: |
| 892 | assertmsg = ast.Constant(class="st">"") |
| 893 | gluestr = class="st">"assert " |
| 894 | err_explanation = ast.BinOp(ast.Constant(gluestr), ast.Add(), msg) |
| 895 | err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation) |
| 896 | err_name = ast.Name(class="st">"AssertionError", ast.Load()) |
| 897 | fmt = self.helper(class="st">"_format_explanation", err_msg) |
| 898 | exc = ast.Call(err_name, [fmt], []) |
| 899 | raise_ = ast.Raise(exc, None) |
| 900 | statements_fail = [] |
| 901 | statements_fail.extend(self.expl_stmts) |
| 902 | statements_fail.append(raise_) |
nothing calls this directly
no test coverage detected