Evaluate a single skipif/xfail condition. If an old-style string condition is given, it is eval()'d, otherwise the condition is bool()'d. If this fails, an appropriately formatted pytest.fail is raised. Returns (result, reason). The reason is only relevant if the result is True.
(item: Item, mark: Mark, condition: object)
| 87 | |
| 88 | |
| 89 | def evaluate_condition(item: Item, mark: Mark, condition: object) -> tuple[bool, str]: |
| 90 | """Evaluate a single skipif/xfail condition. |
| 91 | |
| 92 | If an old-style string condition is given, it is eval()'d, otherwise the |
| 93 | condition is bool()'d. If this fails, an appropriately formatted pytest.fail |
| 94 | is raised. |
| 95 | |
| 96 | Returns (result, reason). The reason is only relevant if the result is True. |
| 97 | """ |
| 98 | # String condition. |
| 99 | if isinstance(condition, str): |
| 100 | globals_ = { |
| 101 | "os": os, |
| 102 | "sys": sys, |
| 103 | "platform": platform, |
| 104 | "config": item.config, |
| 105 | } |
| 106 | for dictionary in reversed( |
| 107 | item.ihook.pytest_markeval_namespace(config=item.config) |
| 108 | ): |
| 109 | if not isinstance(dictionary, Mapping): |
| 110 | raise ValueError( |
| 111 | f"pytest_markeval_namespace() needs to return a dict, got {dictionary!r}" |
| 112 | ) |
| 113 | globals_.update(dictionary) |
| 114 | if hasattr(item, "obj"): |
| 115 | globals_.update(item.obj.__globals__) |
| 116 | try: |
| 117 | filename = f"<{mark.name} condition>" |
| 118 | condition_code = compile(condition, filename, "eval") |
| 119 | result = eval(condition_code, globals_) |
| 120 | except SyntaxError as exc: |
| 121 | msglines = [ |
| 122 | f"Error evaluating {mark.name!r} condition", |
| 123 | " " + condition, |
| 124 | " " + " " * (exc.offset or 0) + "^", |
| 125 | "SyntaxError: invalid syntax", |
| 126 | ] |
| 127 | fail("\n".join(msglines), pytrace=False) |
| 128 | except Exception as exc: |
| 129 | msglines = [ |
| 130 | f"Error evaluating {mark.name!r} condition", |
| 131 | " " + condition, |
| 132 | *traceback.format_exception_only(exc), |
| 133 | ] |
| 134 | fail("\n".join(msglines), pytrace=False) |
| 135 | |
| 136 | # Boolean condition. |
| 137 | else: |
| 138 | try: |
| 139 | result = bool(condition) |
| 140 | except Exception as exc: |
| 141 | msglines = [ |
| 142 | f"Error evaluating {mark.name!r} condition as a boolean", |
| 143 | *traceback.format_exception_only(exc), |
| 144 | ] |
| 145 | fail("\n".join(msglines), pytrace=False) |
| 146 |
no test coverage detected