From dbafea57ddcd88956d2f28963292e1781be8dbfe Mon Sep 17 00:00:00 2001 From: Connor McCarthy Date: Fri, 29 Apr 2022 12:52:58 -0600 Subject: [PATCH] feat(sdk): rename CLI methods to 'create' (#7607) * add deprecated alias group * add deprecated alias group tests * implement deprecated alias group * clean up other alias tests * clean up docstring * fix type annotations / mypy * format with yapf --- sdk/python/kfp/cli/pipeline.py | 11 +++- sdk/python/kfp/cli/run.py | 7 +- .../cli/utils/aliased_plurals_group_test.py | 5 +- .../kfp/cli/utils/deprecated_alias_group.py | 66 +++++++++++++++++++ .../cli/utils/deprecated_alias_group_test.py | 55 ++++++++++++++++ 5 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 sdk/python/kfp/cli/utils/deprecated_alias_group.py create mode 100644 sdk/python/kfp/cli/utils/deprecated_alias_group_test.py diff --git a/sdk/python/kfp/cli/pipeline.py b/sdk/python/kfp/cli/pipeline.py index 2da284304043..05f1aecec426 100644 --- a/sdk/python/kfp/cli/pipeline.py +++ b/sdk/python/kfp/cli/pipeline.py @@ -20,10 +20,15 @@ from kfp import client from kfp.cli.output import OutputFormat from kfp.cli.output import print_output +from kfp.cli.utils import deprecated_alias_group from kfp.cli.utils import parsing -@click.group() +@click.group( + cls=deprecated_alias_group.deprecated_alias_group_factory({ + 'upload': 'create', + 'upload-version': 'create-version' + })) def pipeline(): """Manage pipeline resources.""" pass @@ -41,7 +46,7 @@ def pipeline(): help=parsing.get_param_descr(client.Client.upload_pipeline, 'description')) @click.argument('package-file') @click.pass_context -def upload(ctx: click.Context, +def create(ctx: click.Context, pipeline_name: str, package_file: str, description: str = None): @@ -82,7 +87,7 @@ def upload(ctx: click.Context, ) @click.argument('package-file') @click.pass_context -def upload_version(ctx: click.Context, +def create_version(ctx: click.Context, package_file: str, pipeline_version: str, pipeline_id: Optional[str] = None, diff --git a/sdk/python/kfp/cli/run.py b/sdk/python/kfp/cli/run.py index eed582861f54..9e26ea3dc128 100644 --- a/sdk/python/kfp/cli/run.py +++ b/sdk/python/kfp/cli/run.py @@ -24,10 +24,13 @@ from kfp import client from kfp.cli.output import OutputFormat from kfp.cli.output import print_output +from kfp.cli.utils import deprecated_alias_group from kfp.cli.utils import parsing -@click.group() +@click.group( + cls=deprecated_alias_group.deprecated_alias_group_factory( + {'submit': 'create'})) def run(): """Manage run resources.""" pass @@ -114,7 +117,7 @@ def list(ctx: click.Context, experiment_id: str, page_token: str, max_size: int, type=int) @click.argument('args', nargs=-1) @click.pass_context -def submit(ctx: click.Context, experiment_name: str, run_name: str, +def create(ctx: click.Context, experiment_name: str, run_name: str, package_file: str, pipeline_id: str, pipeline_name: str, watch: bool, timeout: int, version: str, args: List[str]): """Submit a pipeline run.""" diff --git a/sdk/python/kfp/cli/utils/aliased_plurals_group_test.py b/sdk/python/kfp/cli/utils/aliased_plurals_group_test.py index 45cc054580ab..37184d89d190 100644 --- a/sdk/python/kfp/cli/utils/aliased_plurals_group_test.py +++ b/sdk/python/kfp/cli/utils/aliased_plurals_group_test.py @@ -31,8 +31,9 @@ def command(): class TestAliasedPluralsGroup(unittest.TestCase): - def setUp(self): - self.runner = testing.CliRunner() + @classmethod + def setUpClass(cls): + cls.runner = testing.CliRunner() def test_aliases_default_success(self): result = self.runner.invoke(cli, ['command']) diff --git a/sdk/python/kfp/cli/utils/deprecated_alias_group.py b/sdk/python/kfp/cli/utils/deprecated_alias_group.py new file mode 100644 index 000000000000..b4720ab92f71 --- /dev/null +++ b/sdk/python/kfp/cli/utils/deprecated_alias_group.py @@ -0,0 +1,66 @@ +# Copyright 2022 The Kubeflow Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Dict, List, Tuple, Union + +import click + + +def deprecated_alias_group_factory( + deprecated_map: Dict[str, + str]) -> 'DeprecatedAliasGroup': # type: ignore + """Closure that returns a class that implements the deprecated alias group. + + Args: + deprecated_map (Dict[str, str]): Dictionary mapping old deprecated names to new names. + + + Returns: + DeprecatedAliasGroup: A class that implements the deprecated alias group. + """ + + class DeprecatedAliasGroup(click.Group): + + def __init__(self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.deprecated_map = deprecated_map + + def get_command(self, ctx: click.Context, + cmd_name: str) -> click.Command: + # using the correct name + command = click.Group.get_command(self, ctx, cmd_name) + if command is not None: + return command + + # using the deprecated alias + correct_name = self.deprecated_map.get(cmd_name) + if correct_name is not None: + command = click.Group.get_command(self, ctx, correct_name) + click.echo( + f"Warning: '{cmd_name}' is deprecated, use '{correct_name}' instead.", + err=True) + + if command is not None: + return command + + raise click.UsageError(f"Unrecognized command '{cmd_name}'.") + + def resolve_command( + self, ctx: click.Context, args: List[str] + ) -> Tuple[Union[str, None], Union[click.Command, None], List[str]]: + # always return the full command name + _, cmd, args = super().resolve_command(ctx, args) + return cmd.name, cmd, args # type: ignore + + return DeprecatedAliasGroup diff --git a/sdk/python/kfp/cli/utils/deprecated_alias_group_test.py b/sdk/python/kfp/cli/utils/deprecated_alias_group_test.py new file mode 100644 index 000000000000..a25a8785554c --- /dev/null +++ b/sdk/python/kfp/cli/utils/deprecated_alias_group_test.py @@ -0,0 +1,55 @@ +# Copyright 2022 The Kubeflow Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import click +from click import testing +from kfp.cli.utils import deprecated_alias_group + + +@click.group( + cls=deprecated_alias_group.deprecated_alias_group_factory( + {'deprecated': 'new'})) +def cli(): + pass + + +@cli.command() +def new(): + click.echo('Called new command.') + + +class TestAliasedPluralsGroup(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.runner = testing.CliRunner() + + def test_new_call(self): + result = self.runner.invoke(cli, ['new']) + self.assertEqual(result.exit_code, 0) + self.assertEqual(result.output, 'Called new command.\n') + + def test_deprecated_call(self): + result = self.runner.invoke(cli, ['deprecated']) + self.assertEqual(result.exit_code, 0) + self.assertTrue('Called new command.\n' in result.output) + self.assertTrue( + "Warning: 'deprecated' is deprecated, use 'new' instead." in + result.output) + + +if __name__ == '__main__': + unittest.main()