66
77# SPDX-License-Identifier: BSD-3-Clause
88
9+ from __future__ import annotations
10+
911import shlex
1012from argparse import SUPPRESS , ArgumentParser , BooleanOptionalAction , Namespace
11- from typing import Any , Optional
13+ from typing import Any
1214
1315import pytest
1416
@@ -128,6 +130,31 @@ def test_strip_first_line() -> None:
128130 assert strip_first_line ("foo\n bar\n baz" ) == "bar\n baz"
129131
130132
133+ def remove_pytest_prefix (input_string : str ) -> str :
134+ """
135+ Remove ``-m pytest`` from the start of a space-delimited string.
136+
137+ In Python 3.14, pytest now uses the ``__main__`` module's
138+ ``__file__`` attribute to determine the entry point of the test run.
139+ This causes a command line invocation to include the pytest runner's
140+ arguments, which we then need to remove before comparing to expected
141+ output.
142+
143+ Args:
144+ input_string: The string to remove the prefix from.
145+
146+ Returns:
147+ The string without the prefix.
148+ """
149+ return input_string .removeprefix ("-m pytest" ).strip ()
150+
151+
152+ def test_remove_pytest_prefix () -> None :
153+ """Ensure :func:`remove_pytest_prefix` works as expected."""
154+ assert remove_pytest_prefix ("-m pytest foo bar baz" ) == "foo bar baz"
155+ assert remove_pytest_prefix ("-m pytest" ) == ""
156+
157+
131158@pytest .mark .parametrize ("args" , COMPLETE_ARGS )
132159def test_get_effective_command_line_invocation (
133160 parser : ArgumentParser , args : str
@@ -143,8 +170,8 @@ def test_get_effective_command_line_invocation(
143170 "app-nargs2-val --const --app-const1 --app-const2 -vv --ext ext-val1 "
144171 "ext-val2 ext-val3 --no-bool-opt pos1-val1 pos1-val2 pos2-val"
145172 )
146- result = strip_first_entry (
147- unparser .get_effective_command_line_invocation ()
173+ result = remove_pytest_prefix (
174+ strip_first_entry ( unparser .get_effective_command_line_invocation () )
148175 )
149176 assert result == expected
150177
@@ -293,8 +320,8 @@ def test__arg_is_default_and_help_is_suppressed() -> None:
293320 parser .add_argument ("--suppressed" , default = 10 , help = SUPPRESS )
294321 namespace = parser .parse_args (shlex .split ("" ))
295322 unparser = ReverseArgumentParser (parser , namespace )
296- result = strip_first_entry (
297- unparser .get_effective_command_line_invocation ()
323+ result = remove_pytest_prefix (
324+ strip_first_entry ( unparser .get_effective_command_line_invocation () )
298325 )
299326 assert result == ""
300327
@@ -435,7 +462,7 @@ def test__unparse_store_const_action(
435462 ("args" , "expected" ), [(shlex .split ("--foo" ), " --foo" ), ([], None )]
436463)
437464def test__unparse_store_true_action (
438- args : list [str ], expected : Optional [ str ]
465+ args : list [str ], expected : str | None
439466) -> None :
440467 """Ensure ``store_true`` actions are handled appropriately."""
441468 parser = ArgumentParser ()
@@ -450,7 +477,7 @@ def test__unparse_store_true_action(
450477 ("args" , "expected" ), [(shlex .split ("--foo" ), " --foo" ), ([], None )]
451478)
452479def test__unparse_store_false_action (
453- args : list [str ], expected : Optional [ str ]
480+ args : list [str ], expected : str | None
454481) -> None :
455482 """Ensure ``store_false`` actions are handled appropriately."""
456483 parser = ArgumentParser ()
@@ -496,9 +523,7 @@ def test__unparse_append_action(
496523@pytest .mark .parametrize (
497524 ("args" , "expected" ), [("--foo" , " --foo" ), ("" , None )]
498525)
499- def test__unparse_append_const_action (
500- args : str , expected : Optional [str ]
501- ) -> None :
526+ def test__unparse_append_const_action (args : str , expected : str | None ) -> None :
502527 """Ensure ``append_const`` actions are handled appropriately."""
503528 parser = ArgumentParser ()
504529 action = parser .add_argument (
@@ -570,8 +595,8 @@ def test__unparse_sub_parsers_action(
570595 namespace = parser .parse_args (shlex .split (args ))
571596 unparser = ReverseArgumentParser (parser , namespace )
572597 unparser ._unparse_args ()
573- result = strip_first_entry (
574- unparser .get_effective_command_line_invocation ()
598+ result = remove_pytest_prefix (
599+ strip_first_entry ( unparser .get_effective_command_line_invocation () )
575600 )
576601 assert result == expected
577602 result = strip_first_line (unparser .get_pretty_command_line_invocation ())
@@ -612,8 +637,8 @@ def test__unparse_sub_parsers_action_nested() -> None:
612637 namespace = parser .parse_args (shlex .split (args ))
613638 unparser = ReverseArgumentParser (parser , namespace )
614639 unparser ._unparse_args ()
615- result = strip_first_entry (
616- unparser .get_effective_command_line_invocation ()
640+ result = remove_pytest_prefix (
641+ strip_first_entry ( unparser .get_effective_command_line_invocation () )
617642 )
618643 assert result == args
619644 result = strip_first_line (unparser .get_pretty_command_line_invocation ())
@@ -646,9 +671,9 @@ def test__unparse_extend_action() -> None:
646671 ],
647672)
648673def test__unparse_boolean_optional_action (
649- default : Optional [ bool ] , # noqa: FBT001
674+ default : bool | None , # noqa: FBT001
650675 args : str ,
651- expected : Optional [ str ] ,
676+ expected : str | None ,
652677) -> None :
653678 """Ensure ``BooleanOptionalAction`` actions are handled appropriately."""
654679 parser = ArgumentParser ()
0 commit comments