diff --git a/cyclopts/core.py b/cyclopts/core.py index 93f9e44..5db645a 100644 --- a/cyclopts/core.py +++ b/cyclopts/core.py @@ -1349,6 +1349,18 @@ def default_dispatcher(command, bound, _): except Exception: print(traceback.format_exc()) + def update(self, app: "App"): + """Copy over all commands from another :class:`App`. + + Commands from the meta app will **not** be copied over. + + Parameters + ---------- + app: cyclopts.App + All commands from this application will be copied over. + """ + self._commands.update(app._commands) + def __repr__(self): """Only shows non-default values.""" non_defaults = {} diff --git a/docs/source/api.rst b/docs/source/api.rst index 1712b38..fa059d1 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -5,7 +5,7 @@ API === .. autoclass:: cyclopts.App - :members: default, command, version_print, help_print, interactive_shell, parse_commands, parse_known_args, parse_args, assemble_argument_collection + :members: default, command, version_print, help_print, interactive_shell, parse_commands, parse_known_args, parse_args, assemble_argument_collection, update :special-members: __call__, __getitem__, __iter__ Cyclopts Application. diff --git a/tests/test_app_utils.py b/tests/test_app_utils.py index a975d55..85250ba 100644 --- a/tests/test_app_utils.py +++ b/tests/test_app_utils.py @@ -1,3 +1,6 @@ +from cyclopts import App + + def test_app_iter(app): """Like a dictionary, __iter__ of an App should yield keys (command names).""" @@ -31,3 +34,20 @@ def fizz(): actual = list(app.meta) assert actual == ["--help", "-h", "--version", "fizz", "foo", "bar"] + + +def test_app_update(): + app1 = App() + app2 = App() + + @app1.command + def foo(): + pass + + @app2.command + def bar(): + pass + + app1.update(app2) + + assert list(app1) == ["--help", "-h", "--version", "foo", "bar"]