Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions Doc/library/argparse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -637,25 +637,21 @@ are set.

.. versionadded:: 3.14

To highlight inline code in your description or epilog text, you can use
backticks::
To highlight inline code in your description, epilog, or argument ``help``
text, you can use backticks::

>>> parser = argparse.ArgumentParser(
... formatter_class=argparse.RawDescriptionHelpFormatter,
... epilog='''Examples:
... `python -m myapp --verbose`
... `python -m myapp --config settings.json`
... ''')
>>> parser.add_argument('--foo', help='set the `foo` value')

When colors are enabled, the text inside backticks will be displayed in a
distinct color to help examples stand out. When colors are disabled, backticks
are preserved as-is, which is readable in plain text.

.. note::

Backtick markup only applies to description and epilog text. It does not
apply to individual argument ``help`` strings.

.. versionadded:: 3.15


Expand Down
4 changes: 2 additions & 2 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -715,9 +715,9 @@ argparse
default to ``True``. This enables suggestions for mistyped arguments by default.
(Contributed by Jakob Schluse in :gh:`140450`.)

* Added backtick markup support in description and epilog text to highlight
* Added backtick markup support in help text to highlight
inline code when color output is enabled.
(Contributed by Savannah Ostrowski in :gh:`142390`.)
(Contributed by Savannah Ostrowski and Hugo van Kemenade in :gh:`142389`.)


array
Expand Down
6 changes: 4 additions & 2 deletions Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ def _format_args(self, action, default_metavar):
def _expand_help(self, action):
help_string = self._get_help_string(action)
if '%' not in help_string:
return help_string
return self._apply_text_markup(help_string)
params = dict(vars(action), prog=self._prog)
for name in list(params):
value = params[name]
Expand Down Expand Up @@ -726,7 +726,9 @@ def colorize(match):
# bare %s etc. - format with full params dict, no colorization
return spec % params

return _re.sub(fmt_spec, colorize, help_string, flags=_re.VERBOSE)
return self._apply_text_markup(
_re.sub(fmt_spec, colorize, help_string, flags=_re.VERBOSE)
)

def _iter_indented_subactions(self, action):
try:
Expand Down
40 changes: 20 additions & 20 deletions Lib/test/libregrtest/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def _create_parser():
'buildbot workers')
group.add_argument('--timeout', metavar='TIMEOUT',
help='dump the traceback and exit if a test takes '
'more than TIMEOUT seconds; disabled if TIMEOUT '
'more than `TIMEOUT` seconds; disabled if `TIMEOUT` '
'is negative or equals to zero')
group.add_argument('--wait', action='store_true',
help='wait for user input, e.g., allow a debugger '
Expand All @@ -261,11 +261,11 @@ def _create_parser():

group = parser.add_argument_group('Verbosity')
group.add_argument('-v', '--verbose', action='count',
help='run tests in verbose mode with output to stdout')
help='run tests in verbose mode with output to `stdout`')
group.add_argument('-w', '--rerun', action='store_true',
help='re-run failed tests in verbose mode')
group.add_argument('--verbose2', action='store_true', dest='rerun',
help='deprecated alias to --rerun')
help='deprecated alias to `--rerun`')
group.add_argument('-W', '--verbose3', action='store_true',
help='display test output on failure')
group.add_argument('-q', '--quiet', action='store_true',
Expand Down Expand Up @@ -295,22 +295,22 @@ def _create_parser():
more_details)
group.add_argument('-m', '--match', metavar='PAT',
dest='match_tests', action=FilterAction, const=True,
help='match test cases and methods with glob pattern PAT')
help='match test cases and methods with glob pattern `PAT`')
group.add_argument('-i', '--ignore', metavar='PAT',
dest='match_tests', action=FilterAction, const=False,
help='ignore test cases and methods with glob pattern PAT')
help='ignore test cases and methods with glob pattern `PAT`')
group.add_argument('--matchfile', metavar='FILENAME',
dest='match_tests',
action=FromFileFilterAction, const=True,
help='similar to --match but get patterns from a '
help='similar to `--match` but get patterns from a '
'text file, one pattern per line')
group.add_argument('--ignorefile', metavar='FILENAME',
dest='match_tests',
action=FromFileFilterAction, const=False,
help='similar to --matchfile but it receives patterns '
help='similar to `--matchfile` but it receives patterns '
'from text file to ignore')
group.add_argument('-G', '--failfast', action='store_true',
help='fail as soon as a test fails (only with -v or -W)')
help='fail as soon as a test fails (only with `-v` or `-W`)')
group.add_argument('-u', '--use', metavar='RES1,RES2,...',
action='extend', type=resources_list,
help='specify which special resource intensive tests '
Expand All @@ -325,28 +325,28 @@ def _create_parser():

group = parser.add_argument_group('Special runs')
group.add_argument('-L', '--runleaks', action='store_true',
help='run the leaks(1) command just before exit.' +
help='run the `leaks(1)` command just before exit.' +
more_details)
group.add_argument('-R', '--huntrleaks', metavar='RUNCOUNTS',
type=huntrleaks,
help='search for reference leaks (needs debug build, '
'very slow).' + more_details)
group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
dest='use_mp', type=int,
help='run PROCESSES processes at once')
help='run `PROCESSES` processes at once')
group.add_argument('--single-process', action='store_true',
dest='single_process',
help='always run all tests sequentially in '
'a single process, ignore -jN option, '
'a single process, ignore `-jN` option, '
'and failed tests are also rerun sequentially '
'in the same process')
group.add_argument('--parallel-threads', metavar='PARALLEL_THREADS',
type=int,
help='run copies of each test in PARALLEL_THREADS at '
help='run copies of each test in `PARALLEL_THREADS` at '
'once')
group.add_argument('-T', '--coverage', action='store_true',
dest='trace',
help='turn on code coverage tracing using the trace '
help='turn on code coverage tracing using the `trace` '
'module')
group.add_argument('-D', '--coverdir', metavar='DIR',
type=relative_filename,
Expand All @@ -356,18 +356,18 @@ def _create_parser():
help='put coverage files alongside modules')
group.add_argument('-t', '--threshold', metavar='THRESHOLD',
type=int,
help='call gc.set_threshold(THRESHOLD)')
help='call `gc.set_threshold(THRESHOLD)`')
group.add_argument('-n', '--nowindows', action='store_true',
help='suppress error message boxes on Windows')
group.add_argument('-F', '--forever', action='store_true',
help='run the specified tests in a loop, until an '
'error happens; imply --failfast')
'error happens; imply `--failfast`')
group.add_argument('--list-tests', action='store_true',
help="only write the name of tests that will be run, "
"don't execute them")
group.add_argument('--list-cases', action='store_true',
help='only write the name of test cases that will be run'
' , don\'t execute them')
help='only write the name of test cases that will be run, '
'don\'t execute them')
group.add_argument('-P', '--pgo', dest='pgo', action='store_true',
help='enable Profile Guided Optimization (PGO) training')
group.add_argument('--pgo-extended', action='store_true',
Expand All @@ -390,11 +390,11 @@ def _create_parser():
group.add_argument('--tempdir', metavar='PATH',
help='override the working directory for the test run')
group.add_argument('--cleanup', action='store_true',
help='remove old test_python_* directories')
help='remove old `test_python_*` directories')
group.add_argument('--bisect', action='store_true',
help='if some tests fail, run test.bisect_cmd on them')
help='if some tests fail, run `test.bisect_cmd` on them')
group.add_argument('--pythoninfo', action='store_true',
help="run python -m test.pythoninfo before tests")
help="run `python -m test.pythoninfo` before tests")
group.add_argument('--dont-add-python-opts', dest='_add_python_opts',
action='store_false',
help="internal option, don't use it")
Expand Down
31 changes: 31 additions & 0 deletions Lib/test/test_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -7696,6 +7696,37 @@ def test_backtick_markup_special_regex_chars(self):
help_text = parser.format_help()
self.assertIn(f'{prog_extra}grep "foo.*bar" | sort{reset}', help_text)

def test_backtick_markup_in_argument_help(self):
parser = argparse.ArgumentParser(prog="PROG", color=True)
parser.add_argument("--foo", help="set the `foo` value")

prog_extra = self.theme.prog_extra
reset = self.theme.reset

help_text = parser.format_help()
self.assertIn(f"set the {prog_extra}foo{reset} value", help_text)
self.assertNotIn("`", help_text)

def test_backtick_markup_in_argument_help_with_format(self):
parser = argparse.ArgumentParser(prog="PROG", color=True)
parser.add_argument(
"--foo", default="bar", help="set `foo` (default: %(default)s)"
)

prog_extra = self.theme.prog_extra
reset = self.theme.reset

help_text = parser.format_help()
self.assertIn(f"set {prog_extra}foo{reset}", help_text)

def test_backtick_markup_in_argument_help_color_disabled(self):
parser = argparse.ArgumentParser(prog="PROG", color=False)
parser.add_argument("--foo", help="set the `foo` value")

help_text = parser.format_help()
self.assertIn("set the `foo` value", help_text)
self.assertNotIn("\x1b[", help_text)

def test_help_with_format_specifiers(self):
# GH-142950: format specifiers like %x should work with color=True
parser = argparse.ArgumentParser(prog='PROG', color=True)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add backtick markup support in :mod:`argparse` option help text to highlight
inline code when color output is enabled. Patch by Hugo van Kemenade.
Loading