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
nameparameter.If a
defaultfunction 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_formatis 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_formatis 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 != Nonelist (see 3).For all commands with
sort_key!=None, sort them by(sort_key, app.name). It is the user's responsibility thatsort_keys 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_flagsis 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.Consoleto 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.consoleattribute, if notNone.The parenting
App.console(and so on), if notNone.If all values are
None, then the defaultConsoleis used.
- default_parameter: Parameter = None
Default
Parameterconfiguration. Unspecified values of command-annotatedParameterwill inherit these values. See Default Parameter for more details.
- group: None | str | Group | Iterable[str | Group] = None
The group(s) that
default_commandbelongs to.
- group_arguments: Group = Group("Arguments")
The default
Groupthat positional-only parameters are assigned to.
- group_parameters: Group = Group("Parameters")
The default
Groupthat 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-Noneparentname_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_delimiteris 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
Appobject 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
Appto 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
Appcan 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_parameterfrom the apps.default_parameter (Optional[Parameter]) -- Default parameter with highest priority.
parse_docstring (bool) -- Parse the docstring of
default_command. Set toTrueif we need help strings, otherwise set toFalsefor 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.Annotatedwill 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
argsandkwargsto be used when callingcommand.ignored (dict[str, Any]) -- A mapping of python-variable-name to type-hint of any parameter with annotation
parse=False.Annotatedwill 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
dispatcherfunction 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_transformto 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, andtokensis 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
dictofTokenif 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_argumentsif the parameter isPOSITIONAL_ONLY. By default, this isGroup("Arguments").Parenting
App.group_parametersotherwise. 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.
Falseif the parameter has a default,Trueotherwise.
- show: bool | None = None
Show this parameter on the help screen. Defaults to
parsevalue (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_varset, 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_varvalue. The function must have signature:def env_var_split(type_: type, val: str) -> list[str]: ...
where
type_is the associated parameter type-hint, andvalis 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_hyphenis 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
selfattributes. 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 anameis 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 != Nonelist (see 3).For all groups with
sort_key!=None, sort them by(sort_key, group.name). It is the user's responsibility thatsort_keys 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
Parameterin the parameter-resolution-stack that goes betweenApp.default_parameterand the function signature'sAnnotatedParameter. The providedParameteris not allowed to have agroupvalue.
- 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 anameis 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
--fooor--foo.bar.baz;Nonewhen token was pared positionally. Could also be something liketool.project.fooif 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
clifor 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
Tokenparsed 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.nameandself.keyscan naively disagree! For example, aself.parameter.name="--foo.bar.baz"could be aliased to "--fizz". The resultingself.keyswould 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
Argumentthat 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.UNSETifconvert()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.
Noneif 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
tokensintovalue.- 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) --
Trueif 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:
strkeyword like"--foo"or"-f"or"--foo.bar.baz".intglobal positional index.
- Raises:
ValueError -- If the provided
termdoesn't match.- Returns:
Argument -- Matched
Argument.Tuple[str, ...] -- Python keys into Argument. Non-empty iff Argument accepts keys.
Any -- Implicit value (if a flag).
Noneotherwise.
- 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-
Nonefilters will be applied.- Parameters:
group (Optional[Group]) -- The
Groupthe 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
kindof 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_transformandParameter.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
valon. 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
1ifmin==0,minotherwise.
- class cyclopts.validators.MutuallyExclusive
Alias for
LimitedChoiceto 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
Pathfile 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
Pathfile or directory.resolve()is invoked prior to returning the path.
- cyclopts.types.ResolvedExistingPath
A
Pathfile or directory that must exist.resolve()is invoked prior to returning the path.
- cyclopts.types.Directory
A
Paththat 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
Pathdirectory that must exist.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=False, dir_okay=True, ext=()),))]
- cyclopts.types.ResolvedDirectory
A
Pathdirectory.resolve()is invoked prior to returning the path.
- cyclopts.types.ResolvedExistingDirectory
A
Pathdirectory that must exist.resolve()is invoked prior to returning the path.
- cyclopts.types.File
A
Filethat 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
Pathfile that must exist.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=()),))]
- cyclopts.types.ResolvedFile
A
Pathfile.resolve()is invoked prior to returning the path.
- cyclopts.types.ResolvedExistingFile
A
Pathfile that must exist.resolve()is invoked prior to returning the path.
- cyclopts.types.BinPath
A
Paththat must have extensionbin.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('bin',)),))]
- cyclopts.types.ExistingBinPath
A
Paththat 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
Paththat must have extensioncsv.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('csv',)),))]
- cyclopts.types.ExistingCsvPath
A
Paththat 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
Paththat must have extensiontxt.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('txt',)),))]
- cyclopts.types.ExistingTxtPath
A
Paththat 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
Paththat 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
Paththat 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
Paththat must have extensionmp4.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('mp4',)),))]
- cyclopts.types.ExistingMp4Path
A
Paththat 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
Paththat must have extensionjson.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('json',)),))]
- cyclopts.types.ExistingJsonPath
A
Paththat 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
Paththat must have extensiontoml.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('toml',)),))]
- cyclopts.types.ExistingTomlPath
A
Paththat 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
Paththat must have extensionyaml.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('yaml',)),))]
- cyclopts.types.ExistingYamlPath
A
Paththat 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
intlimited 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
strURL 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
Appshould 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
FileNotFoundErrorif it does not exist.
- search_parents: bool = False
If
pathdoesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundErrorif 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.yamlthat is shared with other applications, it is common to store your projects configuration under a key likemyproject:.Your Cyclopts
Appwould 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
FileNotFoundErrorif it does not exist.
- search_parents: bool = False
If
pathdoesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundErrorif 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.jsonthat is shared with other applications, it is common to store your projects configuration under a key like"myproject":.Your Cyclopts
Appwould 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
FileNotFoundErrorif it does not exist.
- search_parents: bool = False
If
pathdoesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundErrorif 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
fooandbarare not supplied by the command line, the app will check the environment variablesMY_SCRIPT_MY_COMMAND_FOOandMY_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:
ExceptionRoot 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:
CycloptsErrorValidator function raised an exception.
- exception_message: str
Parenting Assertion/Value/Type Error message.
- value: Any
Converted value that failed validation.
- exception cyclopts.UnknownOptionError
Bases:
CycloptsErrorUnknown/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:
CycloptsErrorThere was an error performing automatic type coercion.
- target_type: type | None
Intended type to coerce into.
- exception cyclopts.InvalidCommandError
Bases:
CycloptsErrorCLI 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:
CycloptsErrorNot all CLI tokens were used as expected.
- exception cyclopts.MissingArgumentError
Bases:
CycloptsErrorA 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:
CycloptsErrorThe same parameter has erroneously been specified multiple times.
- exception cyclopts.MixedArgumentError
Bases:
CycloptsErrorCannot supply keywords and non-keywords to the same argument.
- exception cyclopts.CommandCollisionError
Bases:
ExceptionA command with the same name has already been registered to the app.
- exception cyclopts.EditorError
Bases:
ExceptionRoot editor-related error.
Root exception raised by all exceptions in
edit().
- exception cyclopts.EditorNotFoundError
Bases:
EditorErrorCould not find a valid text editor for :func`.edit`.
- exception cyclopts.EditorDidNotSaveError
Bases:
EditorErrorUser did not save upon exiting
edit().
- exception cyclopts.EditorDidNotChangeError
Bases:
EditorErrorUser did not edit file contents in
edit().