2023-01-19 06:30:17 +08:00
|
|
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
2018-10-08 04:52:23 +08:00
|
|
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
2018-02-11 18:41:41 +08:00
|
|
|
#
|
2018-10-08 04:52:23 +08:00
|
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
import abc
|
2018-02-11 18:41:41 +08:00
|
|
|
import argparse
|
2022-11-15 17:07:54 +08:00
|
|
|
import io
|
2021-07-09 06:12:30 +08:00
|
|
|
import re
|
2018-02-11 18:41:41 +08:00
|
|
|
import sys
|
2023-07-05 04:43:02 +08:00
|
|
|
from argparse import ArgumentParser
|
|
|
|
from typing import IO, Optional, Sequence, Tuple
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
class Command:
|
2020-01-06 15:35:23 +08:00
|
|
|
"""Parsed representation of a command from argparse.
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
This is a single command from an argparse parser. ``ArgparseWriter`` creates these and returns
|
|
|
|
them from ``parse()``, and it passes one of these to each call to ``format()`` so that we can
|
|
|
|
take an action for a single command.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
prog: str,
|
|
|
|
description: Optional[str],
|
|
|
|
usage: str,
|
|
|
|
positionals: Sequence[Tuple[str, str]],
|
|
|
|
optionals: Sequence[Tuple[Sequence[str], str, str]],
|
|
|
|
subcommands: Sequence[Tuple[ArgumentParser, str]],
|
|
|
|
) -> None:
|
|
|
|
"""Initialize a new Command instance.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
prog: Program name.
|
|
|
|
description: Command description.
|
|
|
|
usage: Command usage.
|
|
|
|
positionals: List of positional arguments.
|
|
|
|
optionals: List of optional arguments.
|
|
|
|
subcommands: List of subcommand parsers.
|
|
|
|
"""
|
2020-01-06 15:35:23 +08:00
|
|
|
self.prog = prog
|
|
|
|
self.description = description
|
|
|
|
self.usage = usage
|
|
|
|
self.positionals = positionals
|
|
|
|
self.optionals = optionals
|
|
|
|
self.subcommands = subcommands
|
|
|
|
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
# NOTE: The only reason we subclass argparse.HelpFormatter is to get access to self._expand_help(),
|
|
|
|
# ArgparseWriter is not intended to be used as a formatter_class.
|
|
|
|
class ArgparseWriter(argparse.HelpFormatter, abc.ABC):
|
|
|
|
"""Analyze an argparse ArgumentParser for easy generation of help."""
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def __init__(self, prog: str, out: IO = sys.stdout, aliases: bool = False) -> None:
|
|
|
|
"""Initialize a new ArgparseWriter instance.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
prog: Program name.
|
|
|
|
out: File object to write to.
|
|
|
|
aliases: Whether or not to include subparsers for aliases.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2023-07-05 04:43:02 +08:00
|
|
|
super().__init__(prog)
|
2018-02-11 18:41:41 +08:00
|
|
|
self.level = 0
|
2020-01-06 15:35:23 +08:00
|
|
|
self.prog = prog
|
2023-07-05 04:43:02 +08:00
|
|
|
self.out = out
|
2020-01-06 15:35:23 +08:00
|
|
|
self.aliases = aliases
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def parse(self, parser: ArgumentParser, prog: str) -> Command:
|
|
|
|
"""Parse the parser object and return the relavent components.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
parser: Command parser.
|
|
|
|
prog: Program name.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Information about the command from the parser.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2018-02-11 18:41:41 +08:00
|
|
|
self.parser = parser
|
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
split_prog = parser.prog.split(" ")
|
2020-01-06 15:35:23 +08:00
|
|
|
split_prog[-1] = prog
|
2022-07-31 06:19:18 +08:00
|
|
|
prog = " ".join(split_prog)
|
2020-01-06 15:35:23 +08:00
|
|
|
description = parser.description
|
|
|
|
|
|
|
|
fmt = parser._get_formatter()
|
|
|
|
actions = parser._actions
|
|
|
|
groups = parser._mutually_exclusive_groups
|
2022-07-31 06:19:18 +08:00
|
|
|
usage = fmt._format_usage(None, actions, groups, "").strip()
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
# Go through actions and split them into optionals, positionals, and subcommands
|
2018-02-11 18:41:41 +08:00
|
|
|
optionals = []
|
|
|
|
positionals = []
|
|
|
|
subcommands = []
|
|
|
|
for action in actions:
|
|
|
|
if action.option_strings:
|
2020-01-06 15:35:23 +08:00
|
|
|
flags = action.option_strings
|
|
|
|
dest_flags = fmt._format_action_invocation(action)
|
2022-07-31 06:19:18 +08:00
|
|
|
help = self._expand_help(action) if action.help else ""
|
|
|
|
help = help.replace("\n", " ")
|
2020-01-06 15:35:23 +08:00
|
|
|
optionals.append((flags, dest_flags, help))
|
2018-02-11 18:41:41 +08:00
|
|
|
elif isinstance(action, argparse._SubParsersAction):
|
|
|
|
for subaction in action._choices_actions:
|
|
|
|
subparser = action._name_parser_map[subaction.dest]
|
2020-01-06 15:35:23 +08:00
|
|
|
subcommands.append((subparser, subaction.dest))
|
|
|
|
|
|
|
|
# Look for aliases of the form 'name (alias, ...)'
|
2023-07-05 04:43:02 +08:00
|
|
|
if self.aliases and isinstance(subaction.metavar, str):
|
2022-07-31 06:19:18 +08:00
|
|
|
match = re.match(r"(.*) \((.*)\)", subaction.metavar)
|
2020-01-06 15:35:23 +08:00
|
|
|
if match:
|
2022-07-31 06:19:18 +08:00
|
|
|
aliases = match.group(2).split(", ")
|
2020-01-06 15:35:23 +08:00
|
|
|
for alias in aliases:
|
|
|
|
subparser = action._name_parser_map[alias]
|
|
|
|
subcommands.append((subparser, alias))
|
2018-02-11 18:41:41 +08:00
|
|
|
else:
|
2020-01-06 15:35:23 +08:00
|
|
|
args = fmt._format_action_invocation(action)
|
2022-07-31 06:19:18 +08:00
|
|
|
help = self._expand_help(action) if action.help else ""
|
|
|
|
help = help.replace("\n", " ")
|
2020-01-06 15:35:23 +08:00
|
|
|
positionals.append((args, help))
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
return Command(prog, description, usage, positionals, optionals, subcommands)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
@abc.abstractmethod
|
|
|
|
def format(self, cmd: Command) -> str:
|
|
|
|
"""Return the string representation of a single node in the parser tree.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Override this in subclasses to define how each subcommand should be displayed.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
cmd: Parsed information about a command or subcommand.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
String representation of this subcommand.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def _write(self, parser: ArgumentParser, prog: str, level: int = 0) -> None:
|
|
|
|
"""Recursively write a parser.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
parser: Command parser.
|
|
|
|
prog: Program name.
|
|
|
|
level: Current level.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
|
|
|
self.level = level
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
cmd = self.parse(parser, prog)
|
|
|
|
self.out.write(self.format(cmd))
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
for subparser, prog in cmd.subcommands:
|
|
|
|
self._write(subparser, prog, level=level + 1)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def write(self, parser: ArgumentParser) -> None:
|
2018-02-11 18:41:41 +08:00
|
|
|
"""Write out details about an ArgumentParser.
|
|
|
|
|
|
|
|
Args:
|
2023-07-05 04:43:02 +08:00
|
|
|
parser: Command parser.
|
2018-02-11 18:41:41 +08:00
|
|
|
"""
|
|
|
|
try:
|
2020-01-06 15:35:23 +08:00
|
|
|
self._write(parser, self.prog)
|
2023-07-05 04:43:02 +08:00
|
|
|
except BrokenPipeError:
|
2020-01-06 15:35:23 +08:00
|
|
|
# Swallow pipe errors
|
2023-07-05 04:43:02 +08:00
|
|
|
pass
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
_rst_levels = ["=", "-", "^", "~", ":", "`"]
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
class ArgparseRstWriter(ArgparseWriter):
|
|
|
|
"""Write argparse output as rst sections."""
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
prog: str,
|
|
|
|
out: IO = sys.stdout,
|
|
|
|
aliases: bool = False,
|
|
|
|
rst_levels: Sequence[str] = _rst_levels,
|
|
|
|
) -> None:
|
|
|
|
"""Initialize a new ArgparseRstWriter instance.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
prog: Program name.
|
|
|
|
out: File object to write to.
|
|
|
|
aliases: Whether or not to include subparsers for aliases.
|
|
|
|
rst_levels: List of characters for rst section headings.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2023-07-05 04:43:02 +08:00
|
|
|
super().__init__(prog, out, aliases)
|
2020-01-06 15:35:23 +08:00
|
|
|
self.rst_levels = rst_levels
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def format(self, cmd: Command) -> str:
|
|
|
|
"""Return the string representation of a single node in the parser tree.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
cmd: Parsed information about a command or subcommand.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
String representation of a node.
|
|
|
|
"""
|
2022-11-15 17:07:54 +08:00
|
|
|
string = io.StringIO()
|
2020-01-06 15:35:23 +08:00
|
|
|
string.write(self.begin_command(cmd.prog))
|
|
|
|
|
|
|
|
if cmd.description:
|
|
|
|
string.write(self.description(cmd.description))
|
|
|
|
|
|
|
|
string.write(self.usage(cmd.usage))
|
|
|
|
|
|
|
|
if cmd.positionals:
|
|
|
|
string.write(self.begin_positionals())
|
|
|
|
for args, help in cmd.positionals:
|
|
|
|
string.write(self.positional(args, help))
|
|
|
|
string.write(self.end_positionals())
|
|
|
|
|
|
|
|
if cmd.optionals:
|
|
|
|
string.write(self.begin_optionals())
|
|
|
|
for flags, dest_flags, help in cmd.optionals:
|
|
|
|
string.write(self.optional(dest_flags, help))
|
|
|
|
string.write(self.end_optionals())
|
|
|
|
|
|
|
|
if cmd.subcommands:
|
|
|
|
string.write(self.begin_subcommands(cmd.subcommands))
|
|
|
|
|
|
|
|
return string.getvalue()
|
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def begin_command(self, prog: str) -> str:
|
|
|
|
"""Text to print before a command.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
prog: Program name.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Text before a command.
|
|
|
|
"""
|
2020-01-06 15:35:23 +08:00
|
|
|
return """
|
|
|
|
----
|
|
|
|
|
|
|
|
.. _{0}:
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
{1}
|
|
|
|
{2}
|
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
""".format(
|
|
|
|
prog.replace(" ", "-"), prog, self.rst_levels[self.level] * len(prog)
|
|
|
|
)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def description(self, description: str) -> str:
|
|
|
|
"""Description of a command.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
description: Command description.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Description of a command.
|
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return description + "\n\n"
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def usage(self, usage: str) -> str:
|
|
|
|
"""Example usage of a command.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
usage: Command usage.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Usage of a command.
|
|
|
|
"""
|
2020-01-06 15:35:23 +08:00
|
|
|
return """\
|
|
|
|
.. code-block:: console
|
|
|
|
|
|
|
|
{0}
|
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
""".format(
|
|
|
|
usage
|
|
|
|
)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def begin_positionals(self) -> str:
|
|
|
|
"""Text to print before positional arguments.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Positional arguments header.
|
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return "\n**Positional arguments**\n\n"
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def positional(self, name: str, help: str) -> str:
|
|
|
|
"""Description of a positional argument.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
name: Argument name.
|
|
|
|
help: Help text.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Positional argument description.
|
|
|
|
"""
|
2020-01-06 15:35:23 +08:00
|
|
|
return """\
|
|
|
|
{0}
|
|
|
|
{1}
|
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
""".format(
|
|
|
|
name, help
|
|
|
|
)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def end_positionals(self) -> str:
|
|
|
|
"""Text to print after positional arguments.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Positional arguments footer.
|
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return ""
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def begin_optionals(self) -> str:
|
|
|
|
"""Text to print before optional arguments.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Optional arguments header.
|
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return "\n**Optional arguments**\n\n"
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def optional(self, opts: str, help: str) -> str:
|
|
|
|
"""Description of an optional argument.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
opts: Optional argument.
|
|
|
|
help: Help text.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Optional argument description.
|
|
|
|
"""
|
2020-01-06 15:35:23 +08:00
|
|
|
return """\
|
|
|
|
``{0}``
|
|
|
|
{1}
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
""".format(
|
|
|
|
opts, help
|
|
|
|
)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def end_optionals(self) -> str:
|
|
|
|
"""Text to print after optional arguments.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Optional arguments footer.
|
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return ""
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def begin_subcommands(self, subcommands: Sequence[Tuple[ArgumentParser, str]]) -> str:
|
|
|
|
"""Table with links to other subcommands.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
subcommands: List of subcommands.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Subcommand linking text.
|
|
|
|
"""
|
2020-01-06 15:35:23 +08:00
|
|
|
string = """
|
|
|
|
**Subcommands**
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
.. hlist::
|
|
|
|
:columns: 4
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
for cmd, _ in subcommands:
|
2022-07-31 06:19:18 +08:00
|
|
|
prog = re.sub(r"^[^ ]* ", "", cmd.prog)
|
|
|
|
string += " * :ref:`{0} <{1}>`\n".format(prog, cmd.prog.replace(" ", "-"))
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
return string + "\n"
|
2018-02-11 18:41:41 +08:00
|
|
|
|
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
class ArgparseCompletionWriter(ArgparseWriter):
|
|
|
|
"""Write argparse output as shell programmable tab completion functions."""
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def format(self, cmd: Command) -> str:
|
|
|
|
"""Return the string representation of a single node in the parser tree.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
cmd: Parsed information about a command or subcommand.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
String representation of this subcommand.
|
2018-02-11 18:41:41 +08:00
|
|
|
"""
|
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
assert cmd.optionals # we should always at least have -h, --help
|
|
|
|
assert not (cmd.positionals and cmd.subcommands) # one or the other
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
# We only care about the arguments/flags, not the help messages
|
2023-07-05 04:43:02 +08:00
|
|
|
positionals: Tuple[str, ...] = ()
|
2020-01-06 15:35:23 +08:00
|
|
|
if cmd.positionals:
|
|
|
|
positionals, _ = zip(*cmd.positionals)
|
|
|
|
optionals, _, _ = zip(*cmd.optionals)
|
2023-07-05 04:43:02 +08:00
|
|
|
subcommands: Tuple[str, ...] = ()
|
2020-01-06 15:35:23 +08:00
|
|
|
if cmd.subcommands:
|
|
|
|
_, subcommands = zip(*cmd.subcommands)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
# Flatten lists of lists
|
|
|
|
optionals = [x for xx in optionals for x in xx]
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
return (
|
|
|
|
self.start_function(cmd.prog)
|
|
|
|
+ self.body(positionals, optionals, subcommands)
|
|
|
|
+ self.end_function(cmd.prog)
|
|
|
|
)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def start_function(self, prog: str) -> str:
|
|
|
|
"""Return the syntax needed to begin a function definition.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
prog: Program name.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2020-01-06 15:35:23 +08:00
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Function definition beginning.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
name = prog.replace("-", "_").replace(" ", "_")
|
|
|
|
return "\n_{0}() {{".format(name)
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def end_function(self, prog: str) -> str:
|
|
|
|
"""Return the syntax needed to end a function definition.
|
2018-02-11 18:41:41 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
prog: Program name
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Function definition ending.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return "}\n"
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def body(
|
|
|
|
self, positionals: Sequence[str], optionals: Sequence[str], subcommands: Sequence[str]
|
|
|
|
) -> str:
|
|
|
|
"""Return the body of the function.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
positionals: List of positional arguments.
|
|
|
|
optionals: List of optional arguments.
|
|
|
|
subcommands: List of subcommand parsers.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Function body.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return ""
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def positionals(self, positionals: Sequence[str]) -> str:
|
|
|
|
"""Return the syntax for reporting positional arguments.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
positionals: List of positional arguments.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Syntax for positional arguments.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return ""
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def optionals(self, optionals: Sequence[str]) -> str:
|
|
|
|
"""Return the syntax for reporting optional flags.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
optionals: List of optional arguments.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Syntax for optional flags.
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return ""
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
def subcommands(self, subcommands: Sequence[str]) -> str:
|
|
|
|
"""Return the syntax for reporting subcommands.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
2023-07-05 04:43:02 +08:00
|
|
|
Args:
|
|
|
|
subcommands: List of subcommand parsers.
|
2020-01-06 15:35:23 +08:00
|
|
|
|
|
|
|
Returns:
|
2023-07-05 04:43:02 +08:00
|
|
|
Syntax for subcommand parsers
|
2020-01-06 15:35:23 +08:00
|
|
|
"""
|
2022-07-31 06:19:18 +08:00
|
|
|
return ""
|