Skip to content

Conversation

@madnoberson
Copy link
Contributor

@madnoberson madnoberson commented Oct 21, 2025

This PR contains the following updates:

Package Type Update Change
cyclopts project.dependencies major ==3.24.* -> ==4.5.*

Release Notes

BrianPugh/cyclopts (cyclopts)

v4.5.1

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.5.0...v4.5.1

v4.5.0

Compare Source

Features

Full Changelog: BrianPugh/cyclopts@v4.4.6...v4.5.0

v4.4.6

Compare Source

What's Changed

Full Changelog: BrianPugh/cyclopts@v4.4.5...v4.4.6

v4.4.5

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.4.4...v4.4.5

v4.4.4

Compare Source

Bug Fixes

Special Thanks to @​AntoninRousset for very clear and organized bug reporting with minimal-working examples!

Full Changelog: BrianPugh/cyclopts@v4.4.3...v4.4.4

v4.4.3

Compare Source

Bug Fixes

  • Place positive short flags after positive options, place negative short flags after negative options. By @​BrianPugh in https://github.com/BrianPugh/cyclopts/pull/721

    Example python code:

    @​app.default
    def foo(dry_run: Annotated[bool, Parameter(alias=["-d"])] = False):
        ...

    Before:

    --dry-run --no-dry-run -d  Enable dry run mode. [default: False]
    

    After:

    --dry-run -d --no-dry-run  Enable dry run mode. [default: False]
    

Full Changelog: BrianPugh/cyclopts@v4.4.2...v4.4.3

v4.4.2

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.4.1...v4.4.2

v4.4.1

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.4.0...v4.4.1

v4.4.0

Compare Source

Features

  • Parameter.parse now accepts regex strings to filter which parameters are parsed. (#​705)
    • e.g. Parameter(parse="^(?!_)") — ignore "private" parameters starting with _
  • Experimental MkDocs documentation generation plugin. (#​621)
  • Various Sphinx plugin improvements.

UI Improvements

  • Command aliases now display with parentheses for clarity. (#​706)
    • greet (g, greet-alias) instead of greet g greet-alias

Bug Fixes

  • Fixed parsing of double-digit negative numbers. (#​708)
  • Fixed lazy-loaded subcommands being eagerly imported when resolving Group objects. (#​710)

Full Changelog: BrianPugh/cyclopts@v4.3.0...v4.4.0

v4.3.0

Compare Source

Features

  • Introduce Paramter.n_tokens to control number of tokens consumed/provided to custom converters. by @​BrianPugh in https://github.com/BrianPugh/cyclopts/pull/695
    • converter functions can now also be directly decorated with @Parameter(...).
    • When decorating a class, Parameter.converter can now be a string indicating a forward-reference to a classmethod in the class.

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.2.5...v4.3.0

v4.2.5

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.2.4...v4.2.5

v4.2.4

Compare Source

Features

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.2.3...v4.2.4

v4.2.3

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.2.2...v4.2.3

v4.2.2

Compare Source

Bug Fixes

Docs

Full Changelog: BrianPugh/cyclopts@v4.2.1...v4.2.2

v4.2.1

Compare Source

Bug Fixes

Full Changelog: BrianPugh/cyclopts@v4.2.0...v4.2.1

v4.2.0

Compare Source

Features

Bug Fixes

Internal

Full Changelog: BrianPugh/cyclopts@v4.1.0...v4.2.0

v4.1.0

Compare Source

Features

  • Support pydantic Secret-types (SecretStr, SecretBytes, etc) by @​BrianPugh in #​620

  • Parameter.count for int counting-flags (e.g., verbosity -vvv). by @​BrianPugh in #​622

    from cyclopts import Parameter
    
    def main(verbose: Annotated[int, Parameter(alias="-v", count=True)] = 0):
        print(f"Verbosity level: {verbose}")  # -vvv → 3
  • Add App.help_epilogue, which prints a message at the bottom of the app's help-page. by @​BrianPugh in #​628

    app = App(help_epilogue="For more info, visit: https://cyclopts.readthedocs.io")
    
    @​app.default
    def main(name: str):
        """Greet someone."""
        print(f"Hello {name}")

╭─ Parameters ───────────────────────────────╮

│ * NAME [required] │

╰────────────────────────────────────────────╯

For more info, visit: https://cyclopts.readthedocs.io


* Add help from dataclass/attrs metadata to the resolution hierarchy. by @&#8203;BrianPugh in <https://github.com/BrianPugh/cyclopts/pull/642>

```python
from dataclasses import dataclass, field

@&#8203;dataclass
class Config:
    port: int = field(default=8080, metadata={"help": "Server port"})
  • Add GNU-style combined short options support by @​BrianPugh in #​639

    from typing import Annotated
    from cyclopts import Parameter
    
    def main(
        verbose: Annotated[bool, Parameter(alias="-v")],
        user: Annotated[str, Parameter(alias="-u")],
    ):
        pass

-v -uroot → verbose=True, user="root"

-vuroot → verbose=True, user="root" (GNU-style combined)

-vu root → verbose=True, user="root"


* More powerful `ArgumentCollection.__getitem__` to support looking up by parameter name by @&#8203;isoschiz in <https://github.com/BrianPugh/cyclopts/pull/635>

```python
arg = argument_collection["param_name"]  # Lookup by parameter name

Bug Fixes

  • Resolve the default version to the nearest explicitly set App.version value instead of root-app version value. by @​BrianPugh in #​632
  • Have MutuallyExclusive group validator accurately report the user-specified option name instead of the first positive name. by @​BrianPugh in #​634
  • Have MissingArgumentError accurately report the user-specified option name instead of the first positive name. by @​BrianPugh in #​638
  • Fix the negative-flag showing up twice for Optional[bool] in the help-page. by @​BrianPugh in #​633
  • Fix incorrect deleting of help/version flag commands when overwriting their respective flag attributes. by @​BrianPugh in #​644
  • Fix unexpected exception when both --help and --version are passed to a subcommand. --help takes precedence. by @​BrianPugh in #​650
  • Allow positional elements of kw-only dataclass. by @​BrianPugh in #​651
  • Fix cyclopts.__version__ not being updated (due to uv migration). by @​BrianPugh in #​657
  • Add parse=False to App.version_print handlers. by @​BrianPugh in #​656
  • Fix kw-only dataclass object instantiation by @​BrianPugh in #​658
  • Misc (mostly internal) type hinting improvements by @​BrianPugh in #​659
  • Fix config command filtering logic. by @​BrianPugh in #​660

Special thanks to @​isoschiz for thorough testing and bug reporting!

Documentation

New Contributors

Full Changelog: BrianPugh/cyclopts@v4.0.0...v4.1.0

v4.0.0

Compare Source

Cyclopts v4 represents a big feature update that makes it a no-compromise CLI python framework.

While Cyclopts v4 has a few breaking changes that generally make applications cleaner/terser/more intuitive, most shouldn't severely impact applications in the wild. This section lists the changes from most impactful to least.

Breaking Features / Breaking Changes / Migration

  • The default help/version formatting has been changed from RestructuredText to Markdown.

    • To keep old behavior, set App(help_format="restructuredtext").
  • Default behavior of App.__call__ and App.run_async return value has changed. By default, these methods do not return and now perform a sys.exit. This ensures that scripts and installed applications have consistent exit code behavior. Previously, a script might have had a different exit code compared to an equivalent installed package. This behavior can be controlled via the new attribute App.result_action.

    • To replicate the old behavior, set result_action="return_value" in your root app.

      app = App(result_action="return_value")
  • New App-inheritance mechanism/priorities. For most users this will have no impact, but pay attention if you use Meta Apps.

    • Previously, meta-apps were treated as mostly independent. They now inherit configurations from their parent App.
    • The execution path through the App tree may now be different from the inheritance path. Meta App parents are higher up the inheritance tree than meta-apps. I.e., app.meta inherits from app.
    • See #​497 for discussion.
  • Dropped Python 3.9 support. Python 3.9 EOL is October 31, 2025.

  • On the help page, the root application name falls back to the script name (instead of the registered @app.default command name).

  • If a dataclass-like parameter is annotated with Parameter(name="*"), and all of its attributes are optional, but the parameter itself is not optional, a ValueError will now be raised. The value in the function signature must have a default value like None. See discussion in #​519.

  • InvalidCommandError has been renamed UnknownCommandError for consistency.

  • Errors are now printed to stderr instead of stdout. Uses the new App.error_console.

    • If you want the old behavior (printing errors to stdout), set error_console to a console writing to stdout:

      from rich.console import Console
      app = App(error_console=Console())
  • All Parameter arguments except name (the only positional parameter) are now keyword-only.

  • If only nameless Groups are assigned to a Parameter, the default Argument/Parameter group is still also applied. This is most convenient when applying a validator without impacting the help page.

Features

Pure "value added" features.

  • Lazy loading - Commands can now be registered using import paths (e.g., "myapp.commands.users:create"), which defers module imports until the command is executed. This dramatically improves CLI startup time for applications with many commands or heavy dependencies.

    from cyclopts import App
    
    app = App(name="myapp")
    user_app = App(name="user")

Module only imported when command is executed

user_app.command("myapp.commands.users:create")
app.command(user_app)


* Shell Completion (supports bash, zsh, fish). Enable with `app.register_install_completion_command()`, then users can install via `myapp --install-completion`.
* Standalone python scripts can have dynamic shell completion via the new `cyclopts run` CLI command.
* Help page customization via `help_formatter` parameter on `App` and `Group`.
* Create fully custom formatters by implementing the `HelpFormatter` protocol.
* Built-in formatters: `DefaultFormatter` (Rich-based with colors/borders) and `PlainFormatter` (accessibility-focused plain text).
* New `cyclopts` CLI tool.
* `cyclopts run` - Execute a python script with dynamic shell-completion.
* `cyclopts generate-docs` - Generates documentation in a variety of formats (markdown, restructuredtext, html).
  * Example: `cyclopts generate-docs myscript.py -o docs.md`
* Sphinx Extension for automatically generating CLI documentation from your Cyclopts App.
* Use the `.. cyclopts:: mypackage.cli:app` directive in your RST files.
* New `App` attributes; many of these were available as `App.__call__` parameters, but now they can also be directly set on `App` and are inherited as expected:
* `print_error` - Whether Cyclopts should print the rich-formatted error when a `CycloptsError` is encountered. True by default.
* `exit_on_error` - If there is an error parsing/coercing the CLI tokens, invoke `sys.exit(1)`. True by default.
* `help_on_error` - If there is an error parsing/coercing the CLI tokens, print out the help-page for the parsed application. False by default.
* `verbose` - Populate `CycloptsError` exception strings with more information intended for developers. False by default.
* flatten subapp's subcommands if named `"*"`. by @&#8203;BrianPugh in https://github.com/BrianPugh/cyclopts/pull/611
* Add support for `enum.Flag` and `enum.IntFlag`.
* Add support for `datetime.date` type by @&#8203;PerchunPak in https://github.com/BrianPugh/cyclopts/pull/601
* Add `cyclopts.config.Dict` config class for in-memory configuration sources. Add new keyword argument `source` to config objects. by @&#8203;BrianPugh in https://github.com/BrianPugh/cyclopts/pull/599
* `App.console` now always resolves to a `console` and respects the app-hierarchy. If a console is explicitly assigned, that console will always be used. This makes it easier to access a `console` object within commands.
* Improved parsing of JSON strings from the CLI. Can now handle `list[CustomClass]` if each element is supplied as a JSON string.
* Optimized "happy execution path" performance.
* If `App.sort_key` or `Group.sort_key` are **generators**, Cyclopts automatically invokes `next` on them immediately.
* This allows for streamlined lexical ordering of commands using `itertools.count`:

  ```python
  from itertools import count
  from cyclopts import App, Group

  counter = count()

  @&#8203;app.command(group=Group("Commands", sort_key=counter))
  def first():
      pass

  @&#8203;app.command(group=Group("Commands", sort_key=counter))
  def second():
      pass
  ```

#### Bug Fixes

* Fixed empty iterables handling within Pydantic models.
* Allow for 0 arguments for iterables (e.g., `list[int]`) when `consume_multiple=True`.
* Fixed incorrect parsing of very large integers.
* Do not parse `help_flags` after `end_of_options_delimiter` by @&#8203;BrianPugh in https://github.com/BrianPugh/cyclopts/pull/609

#### Internal / Developer

* Migrated internal project manager from Poetry to uv.

Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

@madnoberson madnoberson force-pushed the renovate/cyclopts-4.x branch 2 times, most recently from e88dd23 to 124940c Compare October 31, 2025 01:23
@madnoberson madnoberson force-pushed the renovate/cyclopts-4.x branch from 124940c to ba035f4 Compare November 26, 2025 01:25
@madnoberson madnoberson force-pushed the renovate/cyclopts-4.x branch from ba035f4 to a071fe6 Compare December 17, 2025 01:25
@madnoberson madnoberson force-pushed the renovate/cyclopts-4.x branch from a071fe6 to 3583f7c Compare January 17, 2026 01:28
@madnoberson madnoberson force-pushed the renovate/cyclopts-4.x branch from 3583f7c to 8282e91 Compare January 25, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants