API
- class cyclopts.App(name: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = None, help: str | None = None, usage: str | None = None, *, default_command=None, default_parameter: ~cyclopts.parameter.Parameter | None = None, config: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = None, version: None | str | ~typing.Callable[[...], str] = <function _default_version>, version_flags: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = ['--version'], show: bool = True, console: Console | None = None, help_flags: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = ['--help', '-h'], help_format: ~typing.Literal['markdown', 'md', 'plaintext', 'restructuredtext', 'rst', 'rich'] | None = None, help_on_error: bool | None = None, version_format: ~typing.Literal['markdown', 'md', 'plaintext', 'restructuredtext', 'rst', 'rich'] | None = None, group: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = None, group_arguments: None | str | ~cyclopts.group.Group = None, group_parameters: None | str | ~cyclopts.group.Group = None, group_commands: None | str | ~cyclopts.group.Group = None, validator: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = None, name_transform: ~typing.Callable[[str], str] | None = None, sort_key=None, end_of_options_delimiter: str | None = None)
Cyclopts Application.
- name: str | Iterable[str] | None = None
Name of application, or subcommand if registering to another application. Name resolution order:
User specified
name
parameter.If a
default
function has been registered, the name of that function.If the module name is
__main__.py
, the name of the encompassing package.The value of
sys.argv[0]
; i.e. the name of the python script.
Multiple names can be provided in the case of a subcommand, but this is relatively unusual.
Example:
from cyclopts import App app = App() app.command(App(name="foo")) @app["foo"].command def bar(): print("Running bar.") app()
$ my-script foo bar Running bar.
- help: str | None = None
Text to display on help screen. If not supplied, fallbacks to parsing the docstring of function registered with
App.default()
.from cyclopts import App app = App(help="This is my help string.") app()
$ my-script --help Usage: scratch.py COMMAND This is my help string. ╭─ Commands ────────────────────────────────────────────────────────────╮ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰───────────────────────────────────────────────────────────────────────╯
- help_flags: str | Iterable[str] = ("--help", "-h")
CLI flags that trigger
help_print()
. Set to an empty list to disable this feature. Defaults to["--help", "-h"]
.
- help_format: Literal['plaintext', 'markdown', 'md', 'restructuredtext', 'rst'] | None = None
The markup language used in function docstring. If
None
, fallback to parentinghelp_format
. If nohelp_format
is defined, falls back to"restructuredtext"
.
- help_on_error: bool | None = None
Prints the help-page before printing an error. If not set, attempts to inherit from parenting
App
, eventually defaulting toFalse
.
- version_format: Literal['plaintext', 'markdown', 'md', 'restructuredtext', 'rst'] | None = None
The markup language used in the version string. If
None
, fallback to parentingversion_format
. If noversion_format
is defined, falls back to resolvedhelp_format
.
- usage: str | None = None
Text to be displayed in lieue of the default
Usage: app COMMAND ...
at the beginning of the help-page. Set to an empty-string""
to disable showing the default usage.
- show: bool = True
Show this command on the help screen. Hidden commands (
show=False
) are still executable.from cyclopts import App app = App() @app.command def foo(): print("Running foo.") @app.command(show=False) def bar(): print("Running bar.") app()
$ my-script foo Running foo. $ my-script bar Running bar. $ my-script --help Usage: scratch.py COMMAND ╭─ Commands ─────────────────────────────────────────────────╮ │ foo │ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰────────────────────────────────────────────────────────────╯
- sort_key: Any = None
Modifies command display order on the help-page.
If
sort_key
, or any of it's contents, areCallable
, then invoke itsort_key(app)
and apply the returned value to (2) ifNone
, (3) otherwise.For all commands with
sort_key==None
(default value), sort them alphabetically. These sorted commands will be displayed aftersort_key != None
list (see 3).For all commands with
sort_key!=None
, sort them by(sort_key, app.name)
. It is the user's responsibility thatsort_key
s are comparable.
Example usage:
from cyclopts import App app = App() @app.command # sort_key not specified; will be sorted AFTER bob/charlie. def alice(): """Alice help description.""" @app.command(sort_key=2) def bob(): """Bob help description.""" @app.command(sort_key=1) def charlie(): """Charlie help description.""" app()
Resulting help-page:
Usage: demo.py COMMAND ╭─ Commands ──────────────────────────────────────────────────╮ │ charlie Charlie help description. │ │ bob Bob help description. │ │ alice Alice help description. │ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰─────────────────────────────────────────────────────────────╯
- version: None | str | Callable = None
Version to be displayed when a
version_flags
is parsed. Defaults to the version of the package instantiatingApp
. If aCallable
, it will be invoked with no arguments when version is queried.
- version_flags: str | Iterable[str] = ("--version",)
Token(s) that trigger
version_print()
. Set to an empty list to disable version feature. Defaults to["--version"]
.
- console: rich.console.Console = None
Default
rich.console.Console
to use when displaying runtime messages. Cyclopts console resolution is as follows:Any explicitly passed in console to methods like
App.__call__()
,App.parse_args()
, etc.The relevant subcommand's
App.console
attribute, if notNone
.The parenting
App.console
(and so on), if notNone
.If all values are
None
, then the defaultConsole
is used.
- default_parameter: Parameter = None
Default
Parameter
configuration. Unspecified values of command-annotatedParameter
will inherit these values. See Default Parameter for more details.
- group: None | str | Group | Iterable[str | Group] = None
The group(s) that
default_command
belongs to.
- group_arguments: Group = Group("Arguments")
The default
Group
that positional-only parameters are assigned to.
- group_parameters: Group = Group("Parameters")
The default
Group
that non-positional-only parameters are assigned to.
- validator: None | Callable | list[Callable] = []
A function (or list of functions) where all the converted CLI-provided variables will be keyword-unpacked, regardless of their positional/keyword-type in the command function signature. The python variable names will be used, which may differ from their CLI names.
Example usage:
def validator(**kwargs): "Raise an exception if something is invalid."
- name_transform: Callable[[str], str] | None = None
A function that converts function names to their CLI command counterparts.
The function must have signature:
def name_transform(s: str) -> str: ...
The returned string should be without a leading
--
. IfNone
(default value), usesdefault_name_transform()
. Subapps inherit from the first non-None
parentname_transform
.
- config: None | Callable | Iterable[Callable] = None
A function or list of functions that are consecutively executed after parsing CLI tokens and environment variables. These function(s) are called before any conversion and validation. Each config function must have signature:
def config(apps: list["App"], commands: Tuple[str, ...], arguments: ArgumentCollection): """Modifies given mapping inplace with some injected values. Parameters ---------- apps: Tuple[App, ...] The application hierarchy that led to the current command function. The current command app is the last element of this tuple. commands: Tuple[str, ...] The CLI strings that led to the current command function. arguments: ArgumentCollection Complete ArgumentCollection for the app. Modify this collection inplace to influence values provided to the function. """
The intended use-case of this feature is to allow users to specify functions that can load defaults from some external configuration. See cyclopts.config for useful builtins and Config Files for examples.
- end_of_options_delimiter: str | None = None
All tokens after this delimiter will be force-interpreted as positional arguments. If no
end_of_options_delimiter
is set, it will default to POSIX-standard"--"
. Set to an empty string to disable.
- version_print(console: Console | None = None) None
Print the application version.
- Parameters:
console (rich.console.Console) -- Console to print version string to. If not provided, follows the resolution order defined in
App.console
.
- __getitem__(key: str) App
Get the subapp from a command string.
All commands get registered to Cyclopts as subapps. The actual function handler is at
app[key].default_command
.Example usage:
from cyclopts import App app = App() app.command(App(name="foo")) @app["foo"].command def bar(): print("Running bar.") app()
- __iter__() Iterator[str]
Iterate over command & meta command names.
Example usage:
from cyclopts import App app = App() @app.command def foo(): pass @app.command def bar(): pass # help and version flags are treated as commands. assert list(app) == ["--help", "-h", "--version", "foo", "bar"]
- parse_commands(tokens: None | str | Iterable[str] = None, *, include_parent_meta=True) tuple[tuple[str, ...], tuple[App, ...], list[str]]
Extract out the command tokens from a command.
You are probably actually looking for
parse_args()
.- Parameters:
tokens (Union[None, str, Iterable[str]]) -- Either a string, or a list of strings to launch a command. Defaults to
sys.argv[1:]
- Returns:
List[str] -- Strings that are interpreted as a valid command chain.
List[App] -- The associated
App
object for each element in the command chain.List[str] -- The remaining non-command tokens.
- command(obj: T, name: None | str | Iterable[str] = None, **kwargs: object) T
- command(obj: None = None, name: None | str | Iterable[str] = None, **kwargs: object) Callable[[T], T]
Decorator to register a function as a CLI command.
Example usage:
from cyclopts import App app = App() @app.command def foo(): print("foo!") @app.command(name="buzz") def bar(): print("bar!") app()
$ my-script foo foo! $ my-script buzz bar!
- Parameters:
obj (Optional[Callable]) -- Function or
App
to be registered as a command.name (Union[None, str, Iterable[str]]) --
Name(s) to register the command to. If not provided, defaults to:
If registering an
App
, then the app's name.If registering a function, then the function's name after applying
name_transform
.
**kwargs -- Any argument that
App
can take.
- default(obj: T, *, validator: Callable[[...], Any] | None = None) T
- default(obj: None = None, *, validator: Callable[[...], Any] | None = None) Callable[[T], T]
Decorator to register a function as the default action handler.
Example usage:
from cyclopts import App app = App() @app.default def main(): print("Hello world!") app()
$ my-script Hello world!
- assemble_argument_collection(*, apps: Sequence[App] | None = None, default_parameter: Parameter | None = None, parse_docstring: bool = False) ArgumentCollection
Assemble the argument collection for this app.
- Parameters:
apps (Optional[Sequence[App]]) -- List of parenting apps that lead to this app. If provided, will resolve
default_parameter
from the apps.default_parameter (Optional[Parameter]) -- Default parameter with highest priority.
parse_docstring (bool) -- Parse the docstring of
default_command
. Set toTrue
if we need help strings, otherwise set toFalse
for performance reasons.
- Returns:
All arguments for this app.
- Return type:
- parse_known_args(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, end_of_options_delimiter: str | None = None) tuple[Callable[[...], Any], BoundArguments, list[str], dict[str, Any]]
Interpret arguments into a registered function,
BoundArguments
, and any remaining unknown tokens.- Parameters:
tokens (Union[None, str, Iterable[str]]) -- Either a string, or a list of strings to launch a command. Defaults to
sys.argv[1:]
console (rich.console.Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in
App.console
.end_of_options_delimiter (Optional[str]) -- All tokens after this delimiter will be force-interpreted as positional arguments. If
None
, fallback toApp.end_of_options_delimiter
. If that is not set, it will default to POSIX-standard"--"
. Set to an empty string to disable.
- Returns:
command (Callable) -- Bare function to execute.
bound (inspect.BoundArguments) -- Bound arguments for
command
.unused_tokens (List[str]) -- Any remaining CLI tokens that didn't get parsed for
command
.ignored (dict[str, Any]) -- A mapping of python-variable-name to annotated type of any parameter with annotation
parse=False
.Annotated
will be resolved. Intended to simplify meta apps.
- parse_args(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, print_error: bool = True, exit_on_error: bool = True, help_on_error: bool | None = None, verbose: bool = False, end_of_options_delimiter: str | None = None) tuple[Callable, BoundArguments, dict[str, Any]]
Interpret arguments into a function and
BoundArguments
.- Raises:
UnusedCliTokensError -- If any tokens remain after parsing.
- Parameters:
tokens (Union[None, str, Iterable[str]]) -- Either a string, or a list of strings to launch a command. Defaults to
sys.argv[1:]
.console (rich.console.Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in
App.console
.print_error (bool) -- Print a rich-formatted error on error. Defaults to
True
.exit_on_error (bool) -- If there is an error parsing the CLI tokens invoke
sys.exit(1)
. Otherwise, continue to raise the exception. Defaults toTrue
.help_on_error (bool) -- Prints the help-page before printing an error, overriding
App.help_on_error
. Defaults toNone
(interpret fromApp
, eventually defaulting toFalse
).verbose (bool) -- Populate exception strings with more information intended for developers. Defaults to
False
.end_of_options_delimiter (Optional[str]) -- All tokens after this delimiter will be force-interpreted as positional arguments. If
None
, fallback toApp.end_of_options_delimiter
. If that is not set, it will default to POSIX-standard"--"
. Set to an empty string to disable.
- Returns:
command (Callable) -- Function associated with command action.
bound (inspect.BoundArguments) -- Parsed and converted
args
andkwargs
to be used when callingcommand
.ignored (dict[str, Any]) -- A mapping of python-variable-name to type-hint of any parameter with annotation
parse=False
.Annotated
will be resolved. Intended to simplify meta apps.
- __call__(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, print_error: bool = True, exit_on_error: bool = True, help_on_error: bool | None = None, verbose: bool = False, end_of_options_delimiter: str | None = None)
Interprets and executes a command.
- Parameters:
tokens (Union[None, str, Iterable[str]]) -- Either a string, or a list of strings to launch a command. Defaults to
sys.argv[1:]
.console (rich.console.Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in
App.console
.print_error (bool) -- Print a rich-formatted error on error. Defaults to
True
.exit_on_error (bool) -- If there is an error parsing the CLI tokens invoke
sys.exit(1)
. Otherwise, continue to raise the exception. Defaults toTrue
.help_on_error (bool) -- Prints the help-page before printing an error, overriding
App.help_on_error
. Defaults toNone
(interpret fromApp
, eventually defaulting toFalse
).verbose (bool) -- Populate exception strings with more information intended for developers. Defaults to
False
.end_of_options_delimiter (Optional[str]) -- All tokens after this delimiter will be force-interpreted as positional arguments. If
None
, fallback toApp.end_of_options_delimiter
. If that is not set, it will default to POSIX-standard"--"
.
- Returns:
return_value -- The value the command function returns.
- Return type:
Any
- help_print(tokens: Annotated[None | str | Iterable[str], Parameter(show=False)] = None, *, console: Annotated[Console | None, Parameter(parse=False)] = None) None
Print the help page.
- Parameters:
tokens (Union[None, str, Iterable[str]]) -- Tokens to interpret for traversing the application command structure. If not provided, defaults to
sys.argv
.console (rich.console.Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in
App.console
.
- interactive_shell(prompt: str = '$ ', quit: None | str | Iterable[str] = None, dispatcher: Dispatcher | None = None, **kwargs) None
Create a blocking, interactive shell.
All registered commands can be executed in the shell.
- Parameters:
prompt (str) -- Shell prompt. Defaults to
"$ "
.quit (Union[str, Iterable[str]]) -- String or list of strings that will cause the shell to exit and this method to return. Defaults to
["q", "quit"]
.dispatcher (Optional[Dispatcher]) --
Optional function that subsequently invokes the command. The
dispatcher
function must have signature:def dispatcher(command: Callable, bound: inspect.BoundArguments) -> Any: return command(*bound.args, **bound.kwargs)
The above is the default dispatcher implementation.
**kwargs -- Get passed along to
parse_args()
.
- update(app: App)
Copy over all commands from another
App
.Commands from the meta app will not be copied over.
- Parameters:
app (cyclopts.App) -- All commands from this application will be copied over.
- class cyclopts.Parameter(name=None, converter: ~typing.Callable[[~typing.Any, ~typing.Sequence[~cyclopts.token.Token]], ~typing.Any] | None = None, validator=(), negative: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = None, group: None | ~typing.Any | ~collections.abc.Iterable[~typing.Any] = None, parse=None, show: bool | None = None, show_default: bool | None = None, show_choices=None, help: str | None = None, show_env_var=None, env_var=None, env_var_split: ~typing.Callable = <function env_var_split>, negative_bool=None, negative_iterable=None, required: bool | None = None, allow_leading_hyphen: bool = False, accepts_keys: bool | None = None, consume_multiple=None, *, name_transform: ~typing.Callable[[str], str] | None = None, json_dict: bool | None = None, json_list: bool | None = None)
Cyclopts configuration for individual function parameters with
Annotated
.Example usage:
from cyclopts import app, Parameter from typing import Annotated app = App() @app.default def main(foo: Annotated[int, Parameter(name="bar")]): print(foo) app()
$ my-script 100 100 $ my-script --bar 100 100
- name: None | str | Iterable[str] = None
Name(s) to expose to the CLI. If not specified, cyclopts will apply
name_transform
to the python parameter name.from cyclopts import App, Parameter from typing import Annotated app = App() @app.default def main(foo: Annotated[int, Parameter(name=("bar", "-b"))]): print(f"{foo=}") app()
$ my-script --help Usage: main COMMAND [ARGS] [OPTIONS] ╭─ Commands ─────────────────────────────────────────────────────╮ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰────────────────────────────────────────────────────────────────╯ ╭─ Parameters ───────────────────────────────────────────────────╮ │ * BAR --bar -b [required] │ ╰────────────────────────────────────────────────────────────────╯ $ my-script --bar 100 foo=100 $ my-script -b 100 foo=100
If specifying name in a nested data structure (e.g. a dataclass), beginning the name with a hyphen
-
will override any hierarchical dot-notation.from cyclopts import App, Parameter from dataclasses import dataclass from typing import Annotated app = App() @dataclass class User: id: int # default behavior email: Annotated[str, Parameter(name="--email")] # overrides pwd: Annotated[str, Parameter(name="password")] # dot-notation with parent @app.command def create(user: User): print(f"Creating {user=}") app()
$ my-script create --help Usage: scratch.py create [ARGS] [OPTIONS] ╭─ Parameters ───────────────────────────────────────────────────╮ │ * USER.ID --user.id [required] │ │ * EMAIL --email [required] │ │ * USER.PASSWORD [required] │ │ --user.password │ ╰────────────────────────────────────────────────────────────────╯
- converter: Callable | None = None
A function that converts tokens into an object. The converter should have signature:
def converter(type_, tokens) -> Any: pass
Where
type_
is the parameter's type hint, andtokens
is either:A
list[cyclopts.Token]
of CLI tokens (most commonly).from cyclopts import App, Parameter from typing import Annotated app = App() def converter(type_, tokens): assert type_ == tuple[int, int] return tuple(2 * int(x.value) for x in tokens) @app.default def main(coordinates: Annotated[tuple[int, int], Parameter(converter=converter)]): print(f"{coordinates=}") app()
$ python my-script.py 7 12 coordinates=(14, 24)
A
dict
ofToken
if keys are specified in the CLI. E.g.$ python my-script.py --foo.key1=val1
would be parsed into:
tokens = { "key1": ["val1"], }
If not provided, defaults to Cyclopts's internal coercion engine. If a pydantic type-hint is provided, Cyclopts will disable it's internal coercion engine (including this converter argument) and leave the coercion to pydantic.
- validator: None | Callable | Iterable[Callable] = None
A function (or list of functions) that validates data returned by the
converter
.def validator(type_, value: Any) -> None: pass # Raise a TypeError, ValueError, or AssertionError here if data is invalid.
- group: None | str | Group | Iterable[str | Group] = None
The group(s) that this parameter belongs to. This can be used to better organize the help-page, and/or to add additional conversion/validation logic (such as ensuring mutually-exclusive arguments).
If
None
, defaults to one of the following groups:Parenting
App.group_arguments
if the parameter isPOSITIONAL_ONLY
. By default, this isGroup("Arguments")
.Parenting
App.group_parameters
otherwise. By default, this isGroup("Parameters")
.
See Groups for examples.
- negative: None | str | Iterable[str] = None
Name(s) for empty iterables or false boolean flags.
For booleans, defaults to
no-{name}
(seenegative_bool
).For iterables, defaults to
empty-{name}
(seenegative_iterable
).
Set to an empty list or string to disable the creation of negative flags.
Example usage:
from cyclopts import App, Parameter from typing import Annotated app = App() @app.default def main(*, verbose: Annotated[bool, Parameter(negative="--quiet")] = False): print(f"{verbose=}") app()
$ my-script --help Usage: main COMMAND [ARGS] [OPTIONS] ╭─ Commands ─────────────────────────────────────────────────────╮ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰────────────────────────────────────────────────────────────────╯ ╭─ Parameters ───────────────────────────────────────────────────╮ │ --verbose --quiet [default: False] │ ╰────────────────────────────────────────────────────────────────╯
- negative_bool: str | None = None
Prefix for negative boolean flags. Defaults to
"no-"
.
- negative_iterable: str | None = None
Prefix for empty iterables (like lists and sets) flags. Defaults to
"empty-"
.
- allow_leading_hyphen: bool = False
Allow parsing non-numeric values that begin with a hyphen
-
. This is disabled (False
) by default, allowing for more helpful error messages for unknown CLI options.
- parse: bool | None = True
Attempt to use this parameter while parsing. Annotated parameter must be keyword-only. This is intended to be used with meta apps for injecting values.
- required: bool | None = None
Indicates that the parameter must be supplied. Defaults to inferring from the function signature; i.e.
False
if the parameter has a default,True
otherwise.
- show: bool | None = None
Show this parameter on the help screen. Defaults to
parse
value (default:True
).
- show_default: bool | None = None
If a variable has a default, display the default on the help page. Defaults to
None
, similar toTrue
, but will not display the default if it'sNone
.
- show_choices: bool | None = True
If a variable has a set of choices, display the choices on the help page.
- help: str | None = None
Help string to be displayed on the help page. If not specified, defaults to the docstring.
- show_env_var: bool | None = True
If a variable has
env_var
set, display the variable name on the help page.
- env_var: None | str | Iterable[str] = None
Fallback to environment variable(s) if CLI value not provided. If multiple environment variables are given, the left-most environment variable with a set value will be used. If no environment variable is set, Cyclopts will fallback to the function-signature default.
- env_var_split: Callable = cyclopts.env_var_split
Function that splits up the read-in
env_var
value. The function must have signature:def env_var_split(type_: type, val: str) -> list[str]: ...
where
type_
is the associated parameter type-hint, andval
is the environment value.
- name_transform: Callable[[str], str] | None = None
A function that converts python parameter names to their CLI command counterparts.
The function must have signature:
def name_transform(s: str) -> str: ...
If
None
(default value), usescyclopts.default_name_transform()
.
- accepts_keys: bool | None = None
If
False
, treat the user-defined class annotation similar to a tuple. Individual class sub-parameters will not be addressable by CLI keywords. The class will consume enough tokens to populate all required positional parameters.Default behavior (
accepts_keys=True
):from cyclopts import App, Parameter from typing import Annotated app = App() class Image: def __init__(self, path, label): self.path = path self.label = label def __repr__(self): return f"Image(path={self.path!r}, label={self.label!r})" @app.default def main(image: Image): print(f"{image=}") app()
$ my-program --help Usage: main COMMAND [ARGS] [OPTIONS] ╭─ Commands ──────────────────────────────────────────────────────────╮ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰─────────────────────────────────────────────────────────────────────╯ ╭─ Parameters ────────────────────────────────────────────────────────╮ │ * IMAGE.PATH --image.path [required] │ │ * IMAGE.LABEL --image.label [required] │ ╰─────────────────────────────────────────────────────────────────────╯ $ my-program foo.jpg nature image=Image(path='foo.jpg', label='nature') $ my-program --image.path foo.jpg --image.label nature image=Image(path='foo.jpg', label='nature')
Behavior when
accepts_keys=False
:# Modify the default command function's signature. @app.default def main(image: Annotated[Image, Parameter(accepts_keys=False)]): print(f"{image=}")
$ my-program --help Usage: main COMMAND [ARGS] [OPTIONS] ╭─ Commands ──────────────────────────────────────────────────────────╮ │ --help -h Display this message and exit. │ │ --version Display application version. │ ╰─────────────────────────────────────────────────────────────────────╯ ╭─ Parameters ────────────────────────────────────────────────────────╮ │ * IMAGE --image [required] │ ╰─────────────────────────────────────────────────────────────────────╯ $ my-program foo.jpg nature image=Image(path='foo.jpg', label='nature') $ my-program --image foo.jpg nature image=Image(path='foo.jpg', label='nature')
- consume_multiple: bool | None = None
When a parameter is specified by keyword, consume multiple elements worth of CLI tokens. Will consume tokens until the stream is exhausted, or an and
allow_leading_hyphen
is False IfFalse
(default behavior), then only a single element worth of CLI tokens will be consumed.from cyclopts import App from pathlib import Path app = App() @app.default def rules(files: list[Path], ext: list[str] = []): pass app()
$ cmd --ext .pdf --ext .html foo.md bar.md
- json_dict: bool | None = None
Allow for the parsing of json-dict-strings as data. If
None
(default behavior), acts likeTrue
, unless the annotated type is union'd withstr
. WhenTrue
, data will be parsed as json if the following conditions are met:The parameter is specified as a keyword option; e.g.
--movie
.The referenced parameter is dataclass-like.
The first character of the token is a
{
.
- json_list: bool | None = None
Allow for the parsing of json-list-strings as data. If
None
(default behavior), acts likeTrue
, unless the annotated type has each element typestr
. WhenTrue
, data will be parsed as json if the following conditions are met:The referenced parameter is iterable (not including
str
).The first character of the token is a
[
.
- classmethod combine(*parameters: Parameter | None) Parameter
Returns a new Parameter with combined values of all provided
parameters
.- Parameters:
*parameters (Optional[Parameter]) -- Parameters who's attributes override
self
attributes. Ordered from least-to-highest attribute priority.
- class cyclopts.Group(name: str = '', help: str = '', *, show: bool | None = None, sort_key=None, validator=None, default_parameter: Parameter | None = None)
A group of parameters and/or commands in a CLI application.
- name: str = ""
Group name used for the help-page and for group-referenced-by-string. This is a title, so the first character should be capitalized. If a name is not specified, it will not be shown on the help-page.
- help: str = ""
Additional documentation shown on the help-page. This will be displayed inside the group's panel, above the parameters/commands.
- show: bool | None = None
Show this group on the help-page. Defaults to
None
, which will only show the group if aname
is provided.
- sort_key: Any = None
Modifies group-panel display order on the help-page.
If
sort_key
, or any of it's contents, areCallable
, then invoke itsort_key(group)
and apply the returned value to (2) ifNone
, (3) otherwise.For all groups with
sort_key==None
(default value), sort them alphabetically. These sorted groups will be displayed aftersort_key != None
list (see 3).For all groups with
sort_key!=None
, sort them by(sort_key, group.name)
. It is the user's responsibility thatsort_key
s are comparable.
Example usage:
from cyclopts import App, Group app = App() @app.command(group=Group("4", sort_key=5)) def cmd1(): pass @app.command(group=Group("3", sort_key=lambda x: 10)) def cmd2(): pass @app.command(group=Group("2", sort_key=lambda x: None)) def cmd3(): pass @app.command(group=Group("1")) def cmd4(): pass app()
Resulting help-page:
Usage: app COMMAND ╭─ 4 ────────────────────────────────────────────────────────────────╮ │ cmd1 │ ╰────────────────────────────────────────────────────────────────────╯ ╭─ 3 ────────────────────────────────────────────────────────────────╮ │ cmd2 │ ╰────────────────────────────────────────────────────────────────────╯ ╭─ 1 ────────────────────────────────────────────────────────────────╮ │ cmd4 │ ╰────────────────────────────────────────────────────────────────────╯ ╭─ 2 ────────────────────────────────────────────────────────────────╮ │ cmd3 │ ╰────────────────────────────────────────────────────────────────────╯ ╭─ Commands ─────────────────────────────────────────────────────────╮ │ --help,-h Display this message and exit. │ │ --version Display application version. │ ╰────────────────────────────────────────────────────────────────────╯
- default_parameter: Parameter | None = None
Default
Parameter
in the parameter-resolution-stack that goes betweenApp.default_parameter
and the function signature'sAnnotated
Parameter
. The providedParameter
is not allowed to have agroup
value.
- validator: Callable | None = None
A function (or list of functions) that validates an
ArgumentCollection
.Example usage:
def validator(argument_collection: ArgumentCollection): "Raise an exception if something is invalid."
Validators are not invoked for command groups.
- classmethod create_ordered(name='', help='', *, show=None, sort_key=None, validator=None, default_parameter=None)
Create a group with a globally incrementing
sort_key
.Used to create a group that will be displayed after a previously instantiated
Group.create_ordered()
group on the help-page.- Parameters:
name (str) -- Group name used for the help-page and for group-referenced-by-string. This is a title, so the first character should be capitalized. If a name is not specified, it will not be shown on the help-page.
help (str) -- Additional documentation shown on the help-page. This will be displayed inside the group's panel, above the parameters/commands.
show (Optional[bool]) -- Show this group on the help-page. Defaults to
None
, which will only show the group if aname
is provided.sort_key (Any) -- If provided, prepended to the globally incremented counter value (i.e. has priority during sorting).
validator (Union[None, Callable[["ArgumentCollection"], Any], Iterable[Callable[["ArgumentCollection"], Any]]]) -- Group validator to collectively apply.
default_parameter (Optional[cyclopts.Parameter]) -- Default parameter for elements within the group.
- class cyclopts.Token(*, keyword: str | None = None, value: str = '', source: str = '', index: int = 0, keys: tuple[str, ...] = (), implicit_value: ~typing.Any = <UNSET>)
Tracks how a user supplied a value to the application.
- keyword: str | None = None
Unadulterated user-supplied keyword like
--foo
or--foo.bar.baz
;None
when token was pared positionally. Could also be something liketool.project.foo
if from non-cli sources.
- value: str = ""
The parsed token value (unadulterated).
- source: str = ""
Where the token came from; used for error message purposes. Cyclopts uses the string
cli
for cli-parsed tokens.
- index: int = 0
The relative positional index in which the value was provided.
- class cyclopts.field_info.FieldInfo(names: tuple[str, ...] = (), kind: _ParameterKind = _ParameterKind.POSITIONAL_OR_KEYWORD, *, required: bool = False, default: Any, annotation: Any, help: str | None = None)
Extension of
inspect.Parameter
.
- class cyclopts.Argument(*, tokens: list[~cyclopts.token.Token] = NOTHING, field_info: ~cyclopts.field_info.FieldInfo = NOTHING, parameter: ~cyclopts.parameter.Parameter = NOTHING, hint: ~typing.Any = <class 'str'>, index: int | None = None, keys: tuple[str, ...] = (), value: ~typing.Any = <UNSET>)
Encapsulates functionality and additional contextual information for parsing a parameter.
An argument is defined as anything that would have its own entry in the help page.
- tokens: list[Token]
List of
Token
parsed from various sources. Do not directly mutate; seeappend()
.
- hint: Any
The type hint for this argument; may be different from
FieldInfo.annotation
.
- index: int | None
Associated python positional index for argument. If
None
, then cannot be assigned positionally.
- keys: tuple[str, ...]
Python keys that lead to this leaf.
self.parameter.name
andself.keys
can naively disagree! For example, aself.parameter.name="--foo.bar.baz"
could be aliased to "--fizz". The resultingself.keys
would be("bar", "baz")
.This is populated based on type-hints and class-structure, not
Parameter.name
.from cyclopts import App, Parameter from dataclasses import dataclass from typing import Annotated app = App() @dataclass class User: id: int name: Annotated[str, Parameter(name="--fullname")] @app.default def main(user: User): pass for argument in app.assemble_argument_collection(): print(f"name: {argument.name:16} hint: {str(argument.hint):16} keys: {str(argument.keys)}")
$ my-script name: --user.id hint: <class 'int'> keys: ('id',) name: --fullname hint: <class 'str'> keys: ('name',)
- children: ArgumentCollection
Collection of other
Argument
that eventually culminate into the python variable represented byfield_info
.
- property value
Converted value from last
convert()
call.This value may be stale if fields have changed since last
convert()
call.UNSET
ifconvert()
has not yet been called with tokens.
- property show_default: bool
Show the default value on the help page.
- match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[tuple[str, ...], Any]
Match a name search-term, or a positional integer index.
- Raises:
ValueError -- If no match is found.
- Returns:
Tuple[str, ...] -- Leftover keys after matching to this argument. Used if this argument accepts_arbitrary_keywords.
Any -- Implicit value.
None
if no implicit value is applicable.
- property has_tokens: bool
This argument, or a child argument, has at least 1 parsed token.
- property children_recursive: ArgumentCollection
- convert(converter: Callable | None = None)
-
- Parameters:
converter (Optional[Callable]) -- Converter function to use. Overrides
self.parameter.converter
- Returns:
The converted data. Same as
value
.- Return type:
Any
- validate(value)
Validates provided value.
- Parameters:
value -- Value to validate.
- Returns:
The converted data. Same as
value
.- Return type:
Any
- convert_and_validate(converter: Callable | None = None)
Converts and validates
tokens
intovalue
.- Parameters:
converter (Optional[Callable]) -- Converter function to use. Overrides
self.parameter.converter
- Returns:
The converted data. Same as
value
.- Return type:
Any
- token_count(keys: tuple[str, ...] = ())
The number of string tokens this argument consumes.
- Parameters:
keys (tuple[str, ...]) -- The python keys into this argument. If provided, returns the number of string tokens that specific data type within the argument consumes.
- Returns:
int -- Number of string tokens to create 1 element.
consume_all (bool) --
True
if this data type is iterable.
- property negatives
Negative flags from
Parameter.get_negatives()
.
- property name: str
The first provided name this argument goes by.
- property names: tuple[str, ...]
Names the argument goes by (both positive and negative).
- env_var_split(value: str, delimiter: str | None = None) list[str]
Split a given value with
Parameter.env_var_split()
.
- property show: bool
Show this argument on the help page.
If an argument has child arguments, don't show it on the help-page.
- property required: bool
Whether or not this argument requires a user-provided value.
- class cyclopts.ArgumentCollection(*args)
A list-like container for
Argument
.- copy() ArgumentCollection
Returns a shallow copy of the
ArgumentCollection
.
- match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[Argument, tuple[str, ...], Any]
Matches CLI keyword or index to their
Argument
.- Parameters:
term (str | int) --
One of:
str
keyword like"--foo"
or"-f"
or"--foo.bar.baz"
.int
global positional index.
- Raises:
ValueError -- If the provided
term
doesn't match.- Returns:
Argument -- Matched
Argument
.Tuple[str, ...] -- Python keys into Argument. Non-empty iff Argument accepts keys.
Any -- Implicit value (if a flag).
None
otherwise.
- property groups
- filter_by(*, group: Group | None = None, has_tokens: bool | None = None, has_tree_tokens: bool | None = None, keys_prefix: tuple[str, ...] | None = None, kind: _ParameterKind | None = None, parse: bool | None = None, show: bool | None = None, value_set: bool | None = None) ArgumentCollection
Filter the
ArgumentCollection
.All non-
None
filters will be applied.- Parameters:
group (Optional[Group]) -- The
Group
the arguments should be in.has_tokens (Optional[bool]) -- Immediately has tokens (not including children).
has_tree_tokens (Optional[bool]) -- Argument and/or it's children have parsed tokens.
kind (Optional[inspect._ParameterKind]) -- The
kind
of the argument.parse (Optional[bool]) -- If the argument is intended to be parsed or not.
show (Optional[bool]) -- The Argument is intended to be show on the help page.
value_set (Optional[bool]) -- The converted value is set.
- class cyclopts.UNSET
Special sentinel value indicating that no data was provided. Do not instantiate.
- cyclopts.default_name_transform(s: str) str
Converts a python identifier into a CLI token.
Performs the following operations (in order):
Convert the string to all lowercase.
Replace
_
with-
.Strip any leading/trailing
-
(also stripping_
, due to point 2).
Intended to be used with
App.name_transform
andParameter.name_transform
.- Parameters:
s (str) -- Input python identifier string.
- Returns:
Transformed name.
- Return type:
str
- cyclopts.env_var_split(type_: Any, val: str, *, delimiter: str | None = None) list[str]
Type-dependent environment variable value splitting.
Converts a single string into a list of strings. Splits when:
The
type_
is some variant ofIterable[pathlib.Path]
objects. If Windows, split on;
, otherwise split on:
.Otherwise, if the
type_
is anIterable
, split on whitespace. Leading/trailing whitespace of each output element will be stripped.
This function is the default value for
cyclopts.App.env_var_split
.- Parameters:
type (type) -- Type hint that we will eventually coerce into.
val (str) -- String to split.
delimiter (Optional[str]) -- Delimiter to split
val
on. IfNone
, defaults to whitespace.
- Returns:
List of individual string tokens.
- Return type:
list[str]
- cyclopts.edit(initial_text: str = '', *, fallback_editors: Sequence[str] = ('nano', 'vim', 'notepad', 'gedit'), editor_args: Sequence[str] = (), path: str | Path = '', encoding: str = 'utf-8', save: bool = True, required: bool = True) str
Get text input from a user by launching their default text editor.
- Parameters:
initial_text (str) -- Initial text to populate the text file with.
fallback_editors (Sequence[str]) -- If the text editor cannot be determined from the environment variable
EDITOR
, attempt to use these text editors in the order provided.editor_args (Sequence[str]) -- Additional CLI arguments that are passed along to the editor-launch command.
path (Union[str, Path]) -- If specified, the path to the file that should be opened. Text editors typically display this, so a custom path may result in a better user-interface. Defaults to a temporary text file.
encoding (str) -- File encoding to use.
save (bool) -- Require the user to save before exiting the editor. Otherwise raises
EditorDidNotSaveError
.required (bool) -- Require for the saved text to be different from
initial_text
. Otherwise raisesEditorDidNotChangeError
.
- Raises:
EditorError -- Base editor error exception. Explicitly raised if editor subcommand returned a non-zero exit code.
EditorNotFoundError -- A suitable text editor could not be found.
EditorDidNotSaveError -- The user exited the text-editor without saving and
save=True
.EditorDidNotChangeError -- The user did not change the file contents and
required=True
.
- Returns:
The resulting text that was saved by the text editor.
- Return type:
str
- cyclopts.run(callable: Callable[[...], Coroutine[None, None, V]], /) V
- cyclopts.run(callable: Callable[[...], V], /) V
Run the given callable as a CLI command and return its result.
The callable may also be a coroutine function. This function is syntax sugar for very simple use cases, and is roughly equivalent to:
from cyclopts import App app = App() app.default(callable) app()
Example usage:
import cyclopts def main(name: str, age: int): print(f"Hello {name}, you are {age} years old.") cyclopts.run(main)
Validators
Cyclopts has several builtin validators for common CLI inputs.
- class cyclopts.validators.LimitedChoice(min: int = 0, max: int | None = None)
Group validator that limits the number of selections per group.
Commonly used for enforcing mutually-exclusive parameters (default behavior).
- Parameters:
min (int) -- The minimum (inclusive) number of CLI parameters allowed.
max (Optional[int]) -- The maximum (inclusive) number of CLI parameters allowed. Defaults to
1
ifmin==0
,min
otherwise.
- class cyclopts.validators.MutuallyExclusive
Alias for
LimitedChoice
to make intentions more obvious.Only 1 argument in the group can be supplied a value.
- class cyclopts.validators.Number(*, lt: int | float | None = None, lte: int | float | None = None, gt: int | float | None = None, gte: int | float | None = None, modulo: int | float | None = None)
Limit input number to a value range.
Example Usage:
from cyclopts import App, Parameter, validators from typing import Annotated app = App() @app.default def main(age: Annotated[int, Parameter(validator=validators.Number(gte=0, lte=150))]): print(f"You are {age} years old.") app()
$ my-script 100 You are 100 years old. $ my-script -1 ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "-1" for "AGE". Must be >= 0. │ ╰───────────────────────────────────────────────────────────────╯ $ my-script 200 ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "200" for "AGE". Must be <= 150. │ ╰───────────────────────────────────────────────────────────────╯
- lt: int | float | None
Input value must be less than this value.
- lte: int | float | None
Input value must be less than or equal this value.
- gt: int | float | None
Input value must be greater than this value.
- gte: int | float | None
Input value must be greater than or equal this value.
- modulo: int | float | None
Input value must be a multiple of this value.
- class cyclopts.validators.Path(*, exists: bool = False, file_okay: bool = True, dir_okay: bool = True, ext: None | Any | Iterable[Any] = None)
Assertions on properties of
pathlib.Path
.Example Usage:
from cyclopts import App, Parameter, validators from pathlib import Path from typing import Annotated app = App() @app.default def main( # ``src`` must be a file that exists. src: Annotated[Path, Parameter(validator=validators.Path(exists=True, dir_okay=False))], # ``dst`` must be a path that does **not** exist. dst: Annotated[Path, Parameter(validator=validators.Path(dir_okay=False, file_okay=False))], ): "Copies src->dst." dst.write_bytes(src.read_bytes()) app()
$ my-script foo.bin bar.bin # if foo.bin does not exist ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "foo.bin" for "SRC". "foo.bin" does not exist. │ ╰───────────────────────────────────────────────────────────────╯ $ my-script foo.bin bar.bin # if bar.bin exists ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "bar.bin" for "DST". "bar.bin" already exists. │ ╰───────────────────────────────────────────────────────────────╯
- exists: bool
If
True
, specified path must exist. Defaults toFalse
.
- file_okay: bool
If path exists, check it's type:
If
True
, specified path may be an existing file.If
False
, then existing files are not allowed.
Defaults to
True
.
- dir_okay: bool
If path exists, check it's type:
If
True
, specified path may be an existing directory.If
False
, then existing directories are not allowed.
Defaults to
True
.
- ext: str | Sequence[str]
Supplied path must have this extension (case insensitive). May or may not include the ".".
Types
Cyclopts has builtin pre-defined annotated-types for common conversion and validation configurations. All definitions in this section are simply predefined annotations for convenience:
Annotated[..., Parameter(...)]
Due to Cyclopts's advanced Parameter
resolution engine, these annotations can themselves be annotated to further configure behavior. E.g:
Annotated[PositiveInt, Parameter(...)]
Path
Path
annotated types for checking existence, type, and performing path-resolution.
All of these types will also work on sequence of paths (e.g. tuple[Path, Path]
or list[Path]
).
- cyclopts.types.ExistingPath
A
Path
file or directory that must exist.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=True, ext=()),))]
- cyclopts.types.ResolvedPath
A
Path
file or directory.resolve()
is invoked prior to returning the path.
- cyclopts.types.ResolvedExistingPath
A
Path
file or directory that must exist.resolve()
is invoked prior to returning the path.
- cyclopts.types.Directory
A
Path
that must be a directory (or not exist).alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=True, ext=()),))]
- cyclopts.types.ExistingDirectory
A
Path
directory that must exist.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=False, dir_okay=True, ext=()),))]
- cyclopts.types.ResolvedDirectory
A
Path
directory.resolve()
is invoked prior to returning the path.
- cyclopts.types.ResolvedExistingDirectory
A
Path
directory that must exist.resolve()
is invoked prior to returning the path.
- cyclopts.types.File
A
File
that must be a file (or not exist).alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=()),))]
- cyclopts.types.ExistingFile
A
Path
file that must exist.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=()),))]
- cyclopts.types.ResolvedFile
A
Path
file.resolve()
is invoked prior to returning the path.
- cyclopts.types.ResolvedExistingFile
A
Path
file that must exist.resolve()
is invoked prior to returning the path.
- cyclopts.types.BinPath
A
Path
that must have extensionbin
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('bin',)),))]
- cyclopts.types.ExistingBinPath
A
Path
that must exist and have extensionbin
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('bin',)),))]
- cyclopts.types.CsvPath
A
Path
that must have extensioncsv
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('csv',)),))]
- cyclopts.types.ExistingCsvPath
A
Path
that must exist and have extensioncsv
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('csv',)),))]
- cyclopts.types.TxtPath
A
Path
that must have extensiontxt
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('txt',)),))]
- cyclopts.types.ExistingTxtPath
A
Path
that must exist and have extensiontxt
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('txt',)),))]
- cyclopts.types.ImagePath
A
Path
that must have extension in {png
,jpg
,jpeg
}.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('png', 'jpg', 'jpeg')),))]
- cyclopts.types.ExistingImagePath
A
Path
that must exist and have extension in {png
,jpg
,jpeg
}.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('png', 'jpg', 'jpeg')),))]
- cyclopts.types.Mp4Path
A
Path
that must have extensionmp4
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('mp4',)),))]
- cyclopts.types.ExistingMp4Path
A
Path
that must exist and have extensionmp4
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('mp4',)),))]
- cyclopts.types.JsonPath
A
Path
that must have extensionjson
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('json',)),))]
- cyclopts.types.ExistingJsonPath
A
Path
that must exist and have extensionjson
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('json',)),))]
- cyclopts.types.TomlPath
A
Path
that must have extensiontoml
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('toml',)),))]
- cyclopts.types.ExistingTomlPath
A
Path
that must exist and have extensiontoml
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('toml',)),))]
- cyclopts.types.YamlPath
A
Path
that must have extensionyaml
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('yaml',)),))]
- cyclopts.types.ExistingYamlPath
A
Path
that must exist and have extensionyaml
.alias of
Annotated
[Path
, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('yaml',)),))]
Number
Annotated types for checking common int/float value constraints.
All of these types will also work on sequence of numbers (e.g. tuple[int, int]
or list[float]
).
- cyclopts.types.PositiveFloat
A float that must be
>0
.alias of
Annotated
[float
, Parameter(validator=(Number(lt=None, lte=None, gt=0, gte=None, modulo=None),))]
- cyclopts.types.NonNegativeFloat
A float that must be
>=0
.alias of
Annotated
[float
, Parameter(validator=(Number(lt=None, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.NegativeFloat
A float that must be
<0
.alias of
Annotated
[float
, Parameter(validator=(Number(lt=0, lte=None, gt=None, gte=None, modulo=None),))]
- cyclopts.types.NonPositiveFloat
A float that must be
<=0
.alias of
Annotated
[float
, Parameter(validator=(Number(lt=None, lte=0, gt=None, gte=None, modulo=None),))]
- cyclopts.types.PositiveInt
An int that must be
>0
.alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=None, gt=0, gte=None, modulo=None),))]
- cyclopts.types.NonNegativeInt
An int that must be
>=0
.alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.NegativeInt
An int that must be
<0
.alias of
Annotated
[int
, Parameter(validator=(Number(lt=0, lte=None, gt=None, gte=None, modulo=None),))]
- cyclopts.types.NonPositiveInt
An int that must be
<=0
.alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=0, gt=None, gte=None, modulo=None),))]
- cyclopts.types.UInt8
An unsigned 8-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=255, gt=None, gte=0, modulo=None),))]
- cyclopts.types.Int8
A signed 8-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=127, gt=None, gte=-128, modulo=None),))]
- cyclopts.types.UInt16
An unsigned 16-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),))]
- cyclopts.types.Int16
A signed 16-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=32767, gt=None, gte=-32768, modulo=None),))]
- cyclopts.types.UInt32
An unsigned 32-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=4294967296, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.Int32
A signed 32-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=2147483648, lte=None, gt=None, gte=-2147483648, modulo=None),))]
- cyclopts.types.UInt64
An unsigned 64-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=18446744073709551616, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.Int64
A signed 64-bit integer.
alias of
Annotated
[int
, Parameter(validator=(Number(lt=9223372036854775808, lte=None, gt=None, gte=-9223372036854775808, modulo=None),))]
Json
Annotated types for parsing a json-string from the CLI.
- cyclopts.types.Json
Parse a json-string from the CLI.
Note: Since Cyclopts v3.6.0, all dataclass-like classes now natively attempt to parse json-strings, so practical use-case of this annotation is limited.
Usage example:
from cyclopts import App, types app = App() @app.default def main(json: types.Json): print(json) app()
$ my-script '{"foo": 1, "bar": 2}' {'foo': 1, 'bar': 2}
Web
Annotated types for common web-related values.
- cyclopts.types.Email
An email address string with simple validation.
- cyclopts.types.Port
An
int
limited to range[0, 65535]
.alias of
Annotated
[int
, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),))]
- cyclopts.types.URL
A
str
URL string with some simple validation.
.. autodata:: cyclopts.types.URL
Config
Cyclopts has builtin configuration classes to be used with App.config
for loading user-defined defaults in many common scenarios.
All Cyclopts builtins index into the configuration file with the following rules:
Apply
root_keys
(if provided) to enter the project's configuration namespace.Apply the command name(s) to enter the current command's configuration namespace.
Apply each key/value pair if CLI arguments have not been provided for that parameter.
- class cyclopts.config.Toml(path, root_keys: None | Any | Iterable[Any] = (), *, must_exist: bool = False, search_parents: bool = False, allow_unknown: bool = False, use_commands_as_keys: bool = True)
Automatically read configuration from Toml file.
- path: str | pathlib.Path
Path to TOML configuration file.
- root_keys: Iterable[str] = None
The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a
pyproject.toml
, it is common to store all of your projects configuration under:[tool.myproject]
So, your Cyclopts
App
should be configured as:app = cyclopts.App(config=cyclopts.config.Toml("pyproject.toml", root_keys=("tool", "myproject")))
- must_exist: bool = False
The configuration file MUST exist. Raises
FileNotFoundError
if it does not exist.
- search_parents: bool = False
If
path
doesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundError
if no configuration file is found.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError
.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
For example, the following CLI invocation:
$ python my-script.py my-command
Would search into
["my-command"]
for values.
- class cyclopts.config.Yaml(path, root_keys: None | Any | Iterable[Any] = (), *, must_exist: bool = False, search_parents: bool = False, allow_unknown: bool = False, use_commands_as_keys: bool = True)
Automatically read configuration from YAML file.
- path: str | pathlib.Path
Path to YAML configuration file.
- root_keys: Iterable[str] = None
The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a common
config.yaml
that is shared with other applications, it is common to store your projects configuration under a key likemyproject:
.Your Cyclopts
App
would be configured as:app = cyclopts.App(config=cyclopts.config.Yaml("config.yaml", root_keys="myproject"))
- must_exist: bool = False
The configuration file MUST exist. Raises
FileNotFoundError
if it does not exist.
- search_parents: bool = False
If
path
doesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundError
if no configuration file is found.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError
.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
For example, the following CLI invocation:
$ python my-script.py my-command
Would search into
["my-command"]
for values.
- class cyclopts.config.Json(path, root_keys: None | Any | Iterable[Any] = (), *, must_exist: bool = False, search_parents: bool = False, allow_unknown: bool = False, use_commands_as_keys: bool = True)
Automatically read configuration from Json file.
- path: str | pathlib.Path
Path to JSON configuration file.
- root_keys: Iterable[str] = None
The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a common
config.json
that is shared with other applications, it is common to store your projects configuration under a key like"myproject":
.Your Cyclopts
App
would be configured as:app = cyclopts.App(config=cyclopts.config.Json("config.json", root_keys="myproject"))
- must_exist: bool = False
The configuration file MUST exist. Raises
FileNotFoundError
if it does not exist.
- search_parents: bool = False
If
path
doesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundError
if no configuration file is found.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError
.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
For example, the following CLI invocation:
$ python my-script.py my-command
Would search into
["my-command"]
for values.
- class cyclopts.config.Env(prefix: str = '', *, command: bool = True)
Automatically derive environment variable names to read configurations from.
For example, consider the following app:
import cyclopts app = cyclopts.App(config=cyclopts.config.Env("MY_SCRIPT_")) @app.command def my_command(foo, bar): print(f"{foo=} {bar=}") app()
If values for
foo
andbar
are not supplied by the command line, the app will check the environment variablesMY_SCRIPT_MY_COMMAND_FOO
andMY_SCRIPT_MY_COMMAND_BAR
, respectively:$ python my_script.py my-command 1 2 foo=1 bar=2 $ export MY_SCRIPT_MY_COMMAND_FOO=100 $ python my_script.py my-command --bar=2 foo=100 bar=2 $ python my_script.py my-command 1 2 foo=1 bar=2
- prefix: str = ""
String to prepend to all autogenerated environment variable names. Typically ends in
_
, and is something likeMY_APP_
.
Exceptions
- exception cyclopts.CycloptsError
Bases:
Exception
Root exception for runtime errors.
As CycloptsErrors bubble up the Cyclopts call-stack, more information is added to it. Finally,
format_cyclopts_error()
formats the message nicely for the user.- msg: str | None
If set, override automatic message generation.
- verbose: bool
More verbose error messages; aimed towards developers debugging their Cyclopts app. Defaults to
False
.
- unused_tokens: list[str] | None
Leftover tokens after parsing is complete.
- target: Callable | None
The python function associated with the command being parsed.
- command_chain: Sequence[str] | None
List of command that lead to
target
.
- console: Console | None
Rich console to display runtime errors.
- exception cyclopts.ValidationError
Bases:
CycloptsError
Validator function raised an exception.
- exception_message: str
Parenting Assertion/Value/Type Error message.
- value: Any
Converted value that failed validation.
- exception cyclopts.UnknownOptionError
Bases:
CycloptsError
Unknown/unregistered option provided by the cli.
A nearest-neighbor parameter suggestion may be printed.
- argument_collection: ArgumentCollection
Argument collection of plausible options.
- exception cyclopts.CoercionError
Bases:
CycloptsError
There was an error performing automatic type coercion.
- target_type: type | None
Intended type to coerce into.
- exception cyclopts.InvalidCommandError
Bases:
CycloptsError
CLI token combination did not yield a valid command.
- msg: str | None
If set, override automatic message generation.
- verbose: bool
More verbose error messages; aimed towards developers debugging their Cyclopts app. Defaults to
False
.
- unused_tokens: list[str] | None
Leftover tokens after parsing is complete.
- target: Callable | None
The python function associated with the command being parsed.
- command_chain: Sequence[str] | None
List of command that lead to
target
.
- app: 'App' | None
The Cyclopts application itself.
- console: 'Console' | None
Rich console to display runtime errors.
- exception cyclopts.UnusedCliTokensError
Bases:
CycloptsError
Not all CLI tokens were used as expected.
- exception cyclopts.MissingArgumentError
Bases:
CycloptsError
A required argument was not provided.
- tokens_so_far: list[str]
If the matched parameter requires multiple tokens, these are the ones we have parsed so far.
- exception cyclopts.RepeatArgumentError
Bases:
CycloptsError
The same parameter has erroneously been specified multiple times.
- exception cyclopts.MixedArgumentError
Bases:
CycloptsError
Cannot supply keywords and non-keywords to the same argument.
- exception cyclopts.CommandCollisionError
Bases:
Exception
A command with the same name has already been registered to the app.
- exception cyclopts.EditorError
Bases:
Exception
Root editor-related error.
Root exception raised by all exceptions in
edit()
.
- exception cyclopts.EditorNotFoundError
Bases:
EditorError
Could not find a valid text editor for :func`.edit`.
- exception cyclopts.EditorDidNotSaveError
Bases:
EditorError
User did not save upon exiting
edit()
.
- exception cyclopts.EditorDidNotChangeError
Bases:
EditorError
User did not edit file contents in
edit()
.