Parser
The Parser handles argv parsing without dispatch. Command
inherits from Parser and adds dispatch, middleware, and help handling. Use Parser
directly when you need full control of program flow, or when integrating face
parsing into an existing application.
Parser
- class face.Parser(name, doc=None, flags=None, posargs=None, post_posargs=None, flagfile=True, group=None)[source]
The Parser lies at the center of face, primarily providing a configurable validation logic on top of the conventional grammar for CLI argument parsing.
- Parameters:
name (str) – A name used to identify this command. Important when the command is embedded as a subcommand of another command.
doc (str) – An optional summary description of the command, used to generate help and usage information.
flags (list) – A list of Flag instances. Optional, as flags can be added with
add().posargs (bool) – Defaults to disabled, pass
Trueto enable the Parser to accept positional arguments. Pass a callable to parse the positional arguments using that function/type. Pass aPosArgSpecfor full customizability.post_posargs (bool) – Same as posargs, but refers to the list of arguments following the
--conventional marker. Seegitandtoxfor examples of commands using this style of positional argument.flagfile (bool) – Defaults to enabled, pass
Falseto disable flagfile support. Pass aFlaginstance to use a custom flag instead of--flagfile. Read more about Flagfiles below.
Once initialized, parsing is performed by calling
Parser.parse()withsys.argvor any other list of strings.- add(*a, **kw)[source]
Add a flag or subparser.
Unless the first argument is a Parser or Flag object, the arguments are the same as the Flag constructor, and will be used to create a new Flag instance to be added.
May raise ValueError if arguments are not recognized as Parser, Flag, or Flag parameters. ValueError may also be raised on duplicate definitions and other conflicts.
- parse(argv)[source]
This method takes a list of strings and converts them into a validated
CommandParseResultaccording to the flags, subparsers, and other options configured.- Parameters:
argv (list) – A required list of strings. Pass
Noneto usesys.argv.
This method may raise ArgumentParseError (or one of its subtypes) if the list of strings fails to parse.
Note
The argv parameter does not automatically default to using
sys.argvbecause it’s best practice for implementing codebases to perform that sort of defaulting in theirmain(), which should accept anargv=Noneparameter. This simple step ensures that the Python CLI application has some sort of programmatic interface that doesn’t require subprocessing. See here for an example.
Basic usage: create a Parser, add flags, call parse(), and
inspect the CommandParseResult:
from face import Parser, Flag, ERROR
p = Parser('mytool', posargs=True)
p.add('--output', doc='output file path')
p.add('--verbose', parse_as=True, char='-v')
p.add('--count', parse_as=int, missing=1)
result = p.parse(['mytool', '--verbose', '--count', '5', 'input.txt'])
print(result.flags)
# OrderedDict([('output', None), ('verbose', True), ('count', 5), ...])
print(result.posargs)
# ('input.txt',)
The add() method accepts either a Flag instance
or the same arguments as the Flag constructor:
# These are equivalent:
p.add(Flag('--output', doc='output file'))
p.add('--output', doc='output file')
Parser also supports subcommands. Add a sub-Parser to create a command hierarchy:
p = Parser('git')
sub = Parser('clone')
sub.add('--depth', parse_as=int)
p.add(sub)
result = p.parse(['git', 'clone', '--depth', '1'])
print(result.subcmds) # ('clone',)
print(result.flags) # OrderedDict([('depth', 1), ...])
Flag
- class face.Flag(name, parse_as=<class 'str'>, missing=None, multi='error', char=None, doc=None, display=None)[source]
The Flag object represents all there is to know about a resource that can be parsed from argv and consumed by a Command function. It also references a FlagDisplay, used by HelpHandlers to control formatting of the flag during –help output
- Parameters:
name (str) – A string name for the flag, starting with a letter, and consisting of only ASCII letters, numbers, ‘-’, and ‘_’.
parse_as – How to interpret the flag. If parse_as is a callable, it will be called with the argument to the flag, the return value of which is stored in the parse result. If parse_as is not a callable, then the flag takes no argument, and the presence of the flag will produce this value in the parse result. Defaults to
str, meaning a default flag will take one string argument.missing – How to interpret the absence of the flag. Can be any value, which will be in the parse result when the flag is not present. Can also be the special value
face.ERROR, which will make the flag required. Defaults toNone.multi (str) – How to handle multiple instances of the same flag. Pass ‘overwrite’ to accept the last flag’s value. Pass ‘extend’ to collect all values into a list. Pass ‘error’ to get the default behavior, which raises a DuplicateFlag exception. multi can also take a callable, which accepts a list of flag values and returns the value to be stored in the
CommandParseResult.char (str) – A single-character short form for the flag. Can be user-friendly for commonly-used flags. Defaults to
None.doc (str) – A summary of the flag’s behavior, used in automatic help generation.
display – Controls how the flag is displayed in automatic help generation. Pass False to hide the flag, pass a string to customize the label, and pass a FlagDisplay instance for full customizability.
Flags are the primary configuration unit for CLI arguments. The --flag-name
form is normalized to flag_name as the key in the parse result and as the
parameter name for dependency injection in Command handlers.
Basic string flag (default parse_as=str):
Flag('--output', doc='output file path')
# --output report.txt => flags['output'] = 'report.txt'
Boolean flag (no argument, presence yields the value):
Flag('--verbose', parse_as=True, char='-v')
# --verbose => flags['verbose'] = True
# (absent) => flags['verbose'] = None
Integer flag with default:
Flag('--count', parse_as=int, missing=1)
# --count 5 => flags['count'] = 5
# (absent) => flags['count'] = 1
Required flag (raises ArgumentParseError if missing):
from face import ERROR
Flag('--name', missing=ERROR)
Multi flag (collect repeated flags into a list):
Flag('--tag', multi='extend')
# --tag a --tag b => flags['tag'] = ['a', 'b']
The multi parameter accepts:
'error'(default): raiseDuplicateFlagon repeat'extend'orTrue: collect all values into a list'override': last value winsA callable: receives list of all values, returns final value
Name normalization: --my-flag becomes my_flag in the result dict
and as a handler parameter name.
FlagDisplay
- class face.FlagDisplay(flag, *, label: str | None = None, post_doc: str | None = None, full_doc: str | None = None, value_name: str | None = None, group: int = 0, hidden: bool = False, sort_key: int = 0)[source]
Provides individual overrides for most of a given flag’s display settings, as used by HelpFormatter instances attached to Parser and Command objects. Pass an instance of this to Flag.set_display() for full control of help output.
FlagDisplay instances are meant to be used 1:1 with Flag instances, as they maintain a reference back to their associated Flag. They are generally automatically created by a Flag constructor, based on the “display” argument.
- Parameters:
flag (Flag) – The Flag instance to which this FlagDisplay applies.
label (str) – The formatted version of the string used to represent the flag in help and error messages. Defaults to None, which allows the label to be autogenerated by the HelpFormatter.
post_doc (str) – An addendum string added to the Flag’s own doc. Defaults to a parenthetical describing whether the flag takes an argument, and whether the argument is required.
full_doc (str) – A string of the whole flag’s doc, overriding the doc + post_doc default.
value_name (str) – For flags which take an argument, the string to use as the placeholder of the flag argument in help and error labels.
hidden (bool) – Pass True to hide this flag in general help and error messages. Defaults to False.
group – An integer or string indicating how this flag should be grouped in help messages, improving readability. Integers are unnamed groups, strings are for named groups. Defaults to 0.
sort_key – Flags are sorted in help output, pass an integer or string to override the sort order.
Controls how a flag appears in help output. Usually created automatically
by the Flag constructor from its display argument. Pass False to
hide a flag, a string to set a custom label, or a FlagDisplay
instance for full control.
PosArgSpec
- class face.PosArgSpec(parse_as=<class 'str'>, min_count=None, max_count=None, display=None, provides=None, *, name: str | None = None, count: int | None = None)[source]
Passed to Command/Parser as posargs and post_posargs parameters to configure the number and type of positional arguments.
- Parameters:
parse_as (callable) – A function to call on each of the passed arguments. Also accepts special argument ERROR, which will raise an exception if positional arguments are passed. Defaults to str.
min_count (int) – A minimimum number of positional arguments. Defaults to 0.
max_count (int) – A maximum number of positional arguments. Also accepts None, meaning no maximum. Defaults to None.
display – Pass a string to customize the name in help output, or False to hide it completely. Also accepts a PosArgDisplay instance, or a dict of the respective arguments.
provides (str) – name of an argument to be passed to a receptive handler function.
name (str) – A shortcut to set display name and provides
count (int) – A shortcut to set min_count and max_count to a single value when an exact number of arguments should be specified.
PosArgSpec instances are stateless and safe to be used multiple times around the application.
- property accepts_args
True if this PosArgSpec is configured to accept one or more arguments.
- parse(posargs)[source]
Parse a list of strings as positional arguments.
- Parameters:
posargs (list) – List of strings, likely parsed by a Parser instance from sys.argv.
Raises an ArgumentArityError if there are too many or too few arguments.
Raises InvalidPositionalArgument if the argument doesn’t match the configured parse_as. See PosArgSpec for more info.
Returns a list of arguments, parsed with parse_as.
PosArgSpec configures positional argument acceptance. It is passed to
Parser or Command via the posargs or
post_posargs constructor parameters.
Shortcut forms in the Parser/Command constructor:
Parser('cmd', posargs=True) # accept any number of string args
Parser('cmd', posargs=False) # no positional args (default)
Parser('cmd', posargs=int) # parse each arg as int
Parser('cmd', posargs='filename') # sets display name and provides name
Parser('cmd', posargs={'min_count': 1, 'max_count': 3}) # dict of kwargs
Full PosArgSpec with provides:
from face import PosArgSpec
spec = PosArgSpec(parse_as=int, min_count=1, max_count=3, name='number')
p = Parser('sum', posargs=spec)
result = p.parse(['sum', '1', '2', '3'])
print(result.posargs) # (1, 2, 3)
When provides (or name) is set, the parsed positional args are injected
into Command handler functions under that name. With min_count=1 and
max_count=1, the single value is unwrapped (not a tuple).
Disabling positional args explicitly:
PosArgSpec(parse_as=ERROR) # raises if any positional args are passed
PosArgDisplay
- class face.PosArgDisplay(*, name: str | None = None, doc: str = '', post_doc: str | None = None, hidden: bool = False, label: str | None = None)[source]
Provides individual overrides for PosArgSpec display in automated help formatting. Pass to a PosArgSpec constructor, which is in turn passed to a Command/Parser.
- Parameters:
spec (PosArgSpec) – The associated PosArgSpec.
name (str) – The string name of an individual positional argument. Automatically pluralized in the label according to PosArgSpec values. Defaults to ‘arg’.
label (str) – The full display label for positional arguments, bypassing the automatic formatting of the name parameter.
doc (str) – A summary description of the positional arguments.
post_doc (str) – An informational addendum about the arguments, often describes default behavior.
Controls how positional arguments appear in help output. Usually created
automatically by PosArgSpec from its display argument.
ListParam
- class face.ListParam(parse_one_as=<class 'str'>, sep=', ', strip=False)[source]
The ListParam takes an argument as a character-separated list, and produces a Python list of parsed values. Basically, the argument equivalent of CSV (Comma-Separated Values):
--flag a1,b2,c3
By default, this yields a
['a1', 'b2', 'c3']as the value forflag. The format is also similar to CSV in that it supports quoting when values themselves contain the separator:--flag 'a1,"b,2",c3'
- Parameters:
parse_one_as (callable) – Turns a single value’s text into its parsed value.
sep (str) – A single-character string representing the list value separator. Defaults to
,.strip (bool) – Whether or not each value in the list should have whitespace stripped before being passed to parse_one_as. Defaults to False.
Note
Aside from using ListParam, an alternative method for accepting multiple arguments is to use the
multi=Trueon theFlagconstructor. The approach tends to be more verbose and can be confusing because arguments can get spread across the command line.
ListParam lets a single flag accept a comma-separated list:
from face import Flag, ListParam
Flag('--tags', parse_as=ListParam())
# --tags a,b,c => flags['tags'] = ['a', 'b', 'c']
Flag('--ports', parse_as=ListParam(parse_one_as=int))
# --ports 80,443,8080 => flags['ports'] = [80, 443, 8080]
Flag('--items', parse_as=ListParam(sep=';', strip=True))
# --items "one ; two ; three" => flags['items'] = ['one', 'two', 'three']
Values containing the separator can be quoted:
--tags 'a,"b,c",d' yields ['a', 'b,c', 'd'].
ChoicesParam
- class face.ChoicesParam(choices, parse_as=None)[source]
Parses a single value, limited to a set of choices. The actual converter used to parse is inferred from choices by default, but an explicit one can be set parse_as.
Restricts a flag’s value to a fixed set of choices. The parse type is inferred from the first choice by default:
from face import Flag, ChoicesParam
Flag('--color', parse_as=ChoicesParam(['red', 'green', 'blue']))
# --color red => flags['color'] = 'red'
# --color yellow => raises ArgumentParseError
Flag('--level', parse_as=ChoicesParam([1, 2, 3]))
# --level 2 => flags['level'] = 2 (parsed as int)
CommandParseResult
- class face.CommandParseResult(parser, argv=())[source]
The result of
Parser.parse(), instances of this type semantically store all that a command line can contain. Each argument corresponds 1:1 with an attribute.- Parameters:
name (str) – Top-level program name, typically the first argument on the command line, i.e.,
sys.argv[0].subcmds (tuple) – Sequence of subcommand names.
flags (OrderedDict) – Mapping of canonical flag names to matched values.
posargs (tuple) – Sequence of parsed positional arguments.
post_posargs (tuple) – Sequence of parsed post-positional arguments (args following
--)parser (Parser) – The Parser instance that parsed this result. Defaults to None.
argv (tuple) – The sequence of strings parsed by the Parser to yield this result. Defaults to
().
Instances of this class can be injected by accepting the
args_builtin in their Command handler function.
The result object returned by Parser.parse(). Contains all parsed data:
name: the program name (argv[0])subcmds: tuple of matched subcommand namesflags:OrderedDictmapping flag names to valuesposargs: tuple of parsed positional argumentspost_posargs: tuple of post-positional arguments (after--)
When used with Command, the result is also available via the
args_ builtin in handler functions. Individual flags are also injected
by name (e.g., a --output flag becomes the output parameter).
ERROR Sentinel
face.ERROR is a sentinel value used in two places:
Flag('--name', missing=ERROR)makes a flag required. Parsing raisesArgumentParseErrorif the flag is absent.PosArgSpec(parse_as=ERROR)disables positional arguments. Parsing raises if any positional arguments are provided.
Import it directly:
from face import ERROR