diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22caac9b9..71cccd907 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py36-plus] - repo: https://github.com/asottile/pyupgrade - rev: v2.11.0 + rev: v2.12.0 hooks: - id: pyupgrade args: [--py36-plus] diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 1b4760a0c..5f3226296 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -968,7 +968,7 @@ class TerminalRepr: return io.getvalue().strip() def __repr__(self) -> str: - return "<{} instance at {:0x}>".format(self.__class__, id(self)) + return f"<{self.__class__} instance at {id(self):0x}>" def toterminal(self, tw: TerminalWriter) -> None: raise NotImplementedError() diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index fa123d2cb..e7ff5cab2 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -12,7 +12,7 @@ def _try_repr_or_str(obj: object) -> str: except (KeyboardInterrupt, SystemExit): raise except BaseException: - return '{}("{}")'.format(type(obj).__name__, obj) + return f'{type(obj).__name__}("{obj}")' def _format_repr_exception(exc: BaseException, obj: object) -> str: @@ -21,7 +21,7 @@ def _format_repr_exception(exc: BaseException, obj: object) -> str: except (KeyboardInterrupt, SystemExit): raise except BaseException as exc: - exc_info = "unpresentable exception ({})".format(_try_repr_or_str(exc)) + exc_info = f"unpresentable exception ({_try_repr_or_str(exc)})" return "<[{} raised in repr()] {} object at 0x{:x}>".format( exc_info, type(obj).__name__, id(obj) ) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 4236618e8..0c7e76268 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -418,4 +418,4 @@ else: # # This also work for Enums (if you use `is` to compare) and Literals. def assert_never(value: "NoReturn") -> "NoReturn": - assert False, "Unhandled value: {} ({})".format(value, type(value).__name__) + assert False, f"Unhandled value: {value} ({type(value).__name__})" diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 237f5c39e..0fd91c2c9 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -721,7 +721,7 @@ class PytestPluginManager(PluginManager): __import__(importspec) except ImportError as e: raise ImportError( - 'Error importing plugin "{}": {}'.format(modname, str(e.args[0])) + f'Error importing plugin "{modname}": {e.args[0]}' ).with_traceback(e.__traceback__) from e except Skipped as e: diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b0a895a04..9b07a04bc 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -859,7 +859,7 @@ class FixtureLookupError(LookupError): error_msg = "file %s, line %s: source code not available" addline(error_msg % (fspath, lineno + 1)) else: - addline("file {}, line {}".format(fspath, lineno + 1)) + addline(f"file {fspath}, line {lineno + 1}") for i, line in enumerate(lines): line = line.rstrip() addline(" " + line) @@ -908,7 +908,7 @@ class FixtureLookupErrorRepr(TerminalRepr): lines = self.errorstring.split("\n") if lines: tw.line( - "{} {}".format(FormattedExcinfo.fail_marker, lines[0].strip()), + f"{FormattedExcinfo.fail_marker} {lines[0].strip()}", red=True, ) for line in lines[1:]: @@ -922,7 +922,7 @@ class FixtureLookupErrorRepr(TerminalRepr): def fail_fixturefunc(fixturefunc, msg: str) -> "NoReturn": fs, lineno = getfslineno(fixturefunc) - location = "{}:{}".format(fs, lineno + 1) + location = f"{fs}:{lineno + 1}" source = _pytest._code.Source(fixturefunc) fail(msg + ":\n\n" + str(source.indent()) + "\n" + location, pytrace=False) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 2c2a83979..18a8a6592 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -294,7 +294,7 @@ def wrap_session( except exit.Exception as exc: if exc.returncode is not None: session.exitstatus = exc.returncode - sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc)) + sys.stderr.write(f"{type(exc).__name__}: {exc}\n") else: if isinstance(excinfo.value, SystemExit): sys.stderr.write("mainloop: caught unexpected SystemExit!\n") @@ -311,7 +311,7 @@ def wrap_session( except exit.Exception as exc: if exc.returncode is not None: session.exitstatus = exc.returncode - sys.stderr.write("{}: {}\n".format(type(exc).__name__, exc)) + sys.stderr.write(f"{type(exc).__name__}: {exc}\n") config._ensure_unconfigure() return session.exitstatus @@ -718,7 +718,7 @@ class Session(nodes.FSCollector): # If it's a directory argument, recurse and look for any Subpackages. # Let the Package collector deal with subnodes, don't collect here. if argpath.is_dir(): - assert not names, "invalid arg {!r}".format((argpath, names)) + assert not names, f"invalid arg {(argpath, names)!r}" seen_dirs: Set[Path] = set() for direntry in visit(str(argpath), self._recurse): diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 2e7dcf93c..72e2ed4bd 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -103,7 +103,7 @@ class Scanner: else: raise ParseError( pos + 1, - 'unexpected character "{}"'.format(input[pos]), + f'unexpected character "{input[pos]}"', ) yield Token(TokenType.EOF, "", pos) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index d2f21e168..845a97339 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -99,9 +99,7 @@ class ParameterSet( if id is not None: if not isinstance(id, str): - raise TypeError( - "Expected id to be a string, got {}: {!r}".format(type(id), id) - ) + raise TypeError(f"Expected id to be a string, got {type(id)}: {id!r}") id = ascii_escaped(id) return cls(values, marks, id) diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 131873c17..189ed3c5e 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -86,7 +86,7 @@ def create_new_paste(contents: Union[str, bytes]) -> str: return "bad response: %s" % exc_info m = re.search(r'href="/raw/(\w+)"', response) if m: - return "{}/show/{}".format(url, m.group(1)) + return f"{url}/show/{m.group(1)}" else: return "bad response: invalid format ('" + response + "')" diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index a0aa800f7..f641e6491 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -500,9 +500,7 @@ def import_path( spec = importlib.util.spec_from_file_location(module_name, str(path)) if spec is None: - raise ImportError( - "Can't find module {} at location {}".format(module_name, str(path)) - ) + raise ImportError(f"Can't find module {module_name} at location {path}") mod = importlib.util.module_from_spec(spec) sys.modules[module_name] = mod spec.loader.exec_module(mod) # type: ignore[union-attr] diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 5a29c8eae..037f69e0b 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1865,7 +1865,7 @@ class LineMatcher: Match lines consecutively? """ if not isinstance(lines2, collections.abc.Sequence): - raise TypeError("invalid type for lines2: {}".format(type(lines2).__name__)) + raise TypeError(f"invalid type for lines2: {type(lines2).__name__}") lines2 = self._getlines(lines2) lines1 = self.lines[:] extralines = [] diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e6808a99a..5ef5085c7 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1400,7 +1400,7 @@ def idmaker( # Suffix non-unique IDs to make them unique. for index, test_id in enumerate(resolved_ids): if test_id_counts[test_id] > 1: - resolved_ids[index] = "{}{}".format(test_id, test_id_suffixes[test_id]) + resolved_ids[index] = f"{test_id}{test_id_suffixes[test_id]}" test_id_suffixes[test_id] += 1 return resolved_ids @@ -1449,7 +1449,7 @@ def _show_fixtures_per_test(config: Config, session: Session) -> None: tw.line() tw.sep("-", f"fixtures used by {item.name}") # TODO: Fix this type ignore. - tw.sep("-", "({})".format(get_best_relpath(item.function))) # type: ignore[attr-defined] + tw.sep("-", f"({get_best_relpath(item.function)})") # type: ignore[attr-defined] # dict key not used in loop but needed for sorting. for _, fixturedefs in sorted(info.name2fixturedefs.items()): assert fixturedefs is not None diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 1531d2fe3..69f01619a 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -733,9 +733,7 @@ def raises( else: func = args[0] if not callable(func): - raise TypeError( - "{!r} object (type: {}) must be callable".format(func, type(func)) - ) + raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") try: func(*args[1:], **kwargs) except expected_exception as e: diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index d872d9da4..eb59fee29 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -149,9 +149,7 @@ def warns( else: func = args[0] if not callable(func): - raise TypeError( - "{!r} object (type: {}) must be callable".format(func, type(func)) - ) + raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") with WarningsChecker(expected_warning, _ispytest=True): return func(*args[1:], **kwargs) diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index 44a1094c0..9a1dd7517 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -79,7 +79,7 @@ def _show_fixture_action(fixturedef: FixtureDef[object], msg: str) -> None: tw.write(" (fixtures used: {})".format(", ".join(deps))) if hasattr(fixturedef, "cached_param"): - tw.write("[{}]".format(saferepr(fixturedef.cached_param, maxsize=42))) # type: ignore[attr-defined] + tw.write(f"[{saferepr(fixturedef.cached_param, maxsize=42)}]") # type: ignore[attr-defined] tw.flush() diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 252f898bf..01d378abc 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -588,7 +588,7 @@ class TerminalReporter: if self.verbosity <= 0 and self._show_progress_info: if self._show_progress_info == "count": num_tests = self._session.testscollected - progress_length = len(" [{}/{}]".format(str(num_tests), str(num_tests))) + progress_length = len(f" [{num_tests}/{num_tests}]") else: progress_length = len(" [100%]") @@ -610,7 +610,7 @@ class TerminalReporter: if self._show_progress_info == "count": if collected: progress = self._progress_nodeids_reported - counter_format = "{{:{}d}}".format(len(str(collected))) + counter_format = f"{{:{len(str(collected))}d}}" format_string = f" [{counter_format}/{{}}]" return format_string.format(len(progress), collected) return f" [ {collected} / {collected} ]" @@ -704,7 +704,7 @@ class TerminalReporter: pypy_version_info = getattr(sys, "pypy_version_info", None) if pypy_version_info: verinfo = ".".join(map(str, pypy_version_info[:3])) - msg += "[pypy-{}-{}]".format(verinfo, pypy_version_info[3]) + msg += f"[pypy-{verinfo}-{pypy_version_info[3]}]" msg += ", pytest-{}, py-{}, pluggy-{}".format( _pytest._version.version, py.__version__, pluggy.__version__ ) @@ -1066,7 +1066,7 @@ class TerminalReporter: msg = ", ".join(line_parts) main_markup = {main_color: True} - duration = " in {}".format(format_session_duration(session_duration)) + duration = f" in {format_session_duration(session_duration)}" duration_with_markup = self._tw.markup(duration, **main_markup) if display_sep: fullwidth += len(duration_with_markup) - len(duration) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 452849f2b..cc3f160d2 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -188,7 +188,7 @@ class TestGeneralUsage: result.stderr.fnmatch_lines( [ f"ERROR: not found: {p2}", - "(no name {!r} in any of [[][]])".format(str(p2)), + f"(no name {str(p2)!r} in any of [[][]])", "", ] ) diff --git a/testing/python/raises.py b/testing/python/raises.py index a3991adae..2d62e9109 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -144,7 +144,7 @@ class TestRaises: try: pytest.raises(ValueError, int, "0") except pytest.fail.Exception as e: - assert e.msg == "DID NOT RAISE {}".format(repr(ValueError)) + assert e.msg == f"DID NOT RAISE {repr(ValueError)}" else: assert False, "Expected pytest.raises.Exception" @@ -152,7 +152,7 @@ class TestRaises: with pytest.raises(ValueError): pass except pytest.fail.Exception as e: - assert e.msg == "DID NOT RAISE {}".format(repr(ValueError)) + assert e.msg == f"DID NOT RAISE {repr(ValueError)}" else: assert False, "Expected pytest.raises.Exception" diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 8c9c227b2..d3c69f1ab 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -772,7 +772,7 @@ class TestStackLevel: # with stacklevel=2 the warning should originate from the above created test file result.stdout.fnmatch_lines_random( [ - "*{testfile}:3*".format(testfile=str(testfile)), + f"*{testfile}:3*", "*Unknown pytest.mark.unknown*", ] )