Refactor handling of CLI commands

This commit is contained in:
Ivan Kravets
2022-05-31 17:07:56 +03:00
parent 506a08c7cf
commit dcecd5f922
20 changed files with 113 additions and 118 deletions

View File

@ -19,7 +19,7 @@ from traceback import format_exc
import click import click
from platformio import __version__, exception, maintenance from platformio import __version__, exception, maintenance
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.compat import IS_CYGWIN, ensure_python3 from platformio.compat import IS_CYGWIN, ensure_python3
@ -27,7 +27,7 @@ from platformio.compat import IS_CYGWIN, ensure_python3
cls=PlatformioCLI, context_settings=dict(help_option_names=["-h", "--help"]) cls=PlatformioCLI, context_settings=dict(help_option_names=["-h", "--help"])
) )
@click.version_option(__version__, prog_name="PlatformIO Core") @click.version_option(__version__, prog_name="PlatformIO Core")
@click.option("--force", "-f", is_flag=True, help="DEPRECATED") @click.option("--force", "-f", is_flag=True, help="DEPRECATED", hidden=True)
@click.option("--caller", "-c", help="Caller ID (service)") @click.option("--caller", "-c", help="Caller ID (service)")
@click.option("--no-ansi", is_flag=True, help="Do not print ANSI control characters") @click.option("--no-ansi", is_flag=True, help="Do not print ANSI control characters")
@click.pass_context @click.pass_context

96
platformio/cli.py Normal file
View File

@ -0,0 +1,96 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# 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 importlib
from pathlib import Path
import click
class PlatformioCLI(click.MultiCommand):
leftover_args = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._pio_root_path = Path(__file__).parent
self._pio_cmd_aliases = dict(package="pkg")
def _find_pio_commands(self):
def _to_module_path(p):
return (
"platformio." + ".".join(p.relative_to(self._pio_root_path).parts)[:-3]
)
result = {}
for p in self._pio_root_path.rglob("cli.py"):
# skip this module
if p.parent == self._pio_root_path:
continue
cmd_name = p.parent.name
result[self._pio_cmd_aliases.get(cmd_name, cmd_name)] = _to_module_path(p)
# find legacy commands
for p in (self._pio_root_path / "commands").iterdir():
if p.name.startswith("_"):
continue
if (p / "command.py").is_file():
result[p.name] = _to_module_path(p / "command.py")
elif p.name.endswith(".py"):
result[p.name[:-3]] = _to_module_path(p)
return result
@staticmethod
def in_silence():
args = PlatformioCLI.leftover_args
return args and any(
[
args[0] == "debug" and "--interpreter" in " ".join(args),
args[0] == "upgrade",
"--json-output" in args,
"--version" in args,
]
)
def invoke(self, ctx):
PlatformioCLI.leftover_args = ctx.args
if hasattr(ctx, "protected_args"):
PlatformioCLI.leftover_args = ctx.protected_args + ctx.args
return super().invoke(ctx)
def list_commands(self, ctx):
return sorted(list(self._find_pio_commands()))
def get_command(self, ctx, cmd_name):
commands = self._find_pio_commands()
if cmd_name not in commands:
return self._handle_obsolate_command(ctx, cmd_name)
module = importlib.import_module(commands[cmd_name])
return getattr(module, "cli")
@staticmethod
def _handle_obsolate_command(ctx, cmd_name):
# pylint: disable=import-outside-toplevel
if cmd_name == "init":
from platformio.project.commands.init import project_init_cmd
return project_init_cmd
if cmd_name == "package":
from platformio.package.cli import cli
return cli
raise click.UsageError('No such command "%s"' % cmd_name, ctx)

View File

@ -11,76 +11,3 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os
import click
class PlatformioCLI(click.MultiCommand):
leftover_args = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._pio_cmds_dir = os.path.dirname(__file__)
@staticmethod
def in_silence():
args = PlatformioCLI.leftover_args
return args and any(
[
args[0] == "debug" and "--interpreter" in " ".join(args),
args[0] == "upgrade",
"--json-output" in args,
"--version" in args,
]
)
def invoke(self, ctx):
PlatformioCLI.leftover_args = ctx.args
if hasattr(ctx, "protected_args"):
PlatformioCLI.leftover_args = ctx.protected_args + ctx.args
return super().invoke(ctx)
def list_commands(self, ctx):
cmds = []
for cmd_name in os.listdir(self._pio_cmds_dir):
if cmd_name.startswith("__init__"):
continue
if os.path.isfile(os.path.join(self._pio_cmds_dir, cmd_name, "command.py")):
cmds.append(cmd_name)
elif cmd_name.endswith(".py"):
cmds.append(cmd_name[:-3])
cmds.sort()
return cmds
def get_command(self, ctx, cmd_name):
mod = None
try:
mod_path = "platformio.commands." + cmd_name
if os.path.isfile(os.path.join(self._pio_cmds_dir, cmd_name, "command.py")):
mod_path = "platformio.commands.%s.command" % cmd_name
mod = __import__(mod_path, None, None, ["cli"])
except ImportError:
try:
return self._handle_obsolate_command(cmd_name)
except AttributeError:
pass
raise click.UsageError('No such command "%s"' % cmd_name, ctx)
return mod.cli
@staticmethod
def _handle_obsolate_command(name):
# pylint: disable=import-outside-toplevel
if name == "init":
from platformio.project.commands.init import project_init_cmd
return project_init_cmd
if name == "package":
from platformio.commands.pkg import cli
return cli
raise AttributeError()

View File

@ -1,17 +0,0 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# 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.
# pylint: disable=unused-import
from platformio.debug.command import debug_cmd as cli

View File

@ -24,7 +24,7 @@ import click
from tabulate import tabulate from tabulate import tabulate
from platformio import exception, fs, util from platformio import exception, fs, util
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.commands.lib.helpers import get_builtin_libs, save_project_libdeps from platformio.commands.lib.helpers import get_builtin_libs, save_project_libdeps
from platformio.package.exception import NotGlobalLibDir, UnknownPackageError from platformio.package.exception import NotGlobalLibDir, UnknownPackageError
from platformio.package.manager.library import LibraryPackageManager from platformio.package.manager.library import LibraryPackageManager

View File

@ -34,7 +34,7 @@ from platformio.device.commands.monitor import (
from platformio.package.manager.core import inject_contrib_pysite from platformio.package.manager.core import inject_contrib_pysite
from platformio.project.exception import NotPlatformIOProjectError from platformio.project.exception import NotPlatformIOProjectError
from platformio.project.options import ProjectOptions from platformio.project.options import ProjectOptions
from platformio.test.command import test_cmd from platformio.test.cli import test_cmd
@click.group("remote", short_help="Remote Development") @click.group("remote", short_help="Remote Development")

View File

@ -1,17 +0,0 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# 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.
# pylint: disable=unused-import
from platformio.test.command import test_cmd as cli

View File

@ -93,6 +93,9 @@ def debug_cmd(
) )
cli = debug_cmd
def _debug_in_project_dir( def _debug_in_project_dir(
ctx, ctx,
project_dir, project_dir,

View File

@ -20,7 +20,7 @@ from fnmatch import fnmatch
from hashlib import sha1 from hashlib import sha1
from io import BytesIO from io import BytesIO
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.commands.run.command import cli as cmd_run from platformio.commands.run.command import cli as cmd_run
from platformio.commands.run.command import print_processing_header from platformio.commands.run.command import print_processing_header
from platformio.compat import IS_WINDOWS, is_bytes from platformio.compat import IS_WINDOWS, is_bytes

View File

@ -21,7 +21,7 @@ import semantic_version
from platformio import __version__, app, exception, fs, telemetry from platformio import __version__, app, exception, fs, telemetry
from platformio.cache import cleanup_content_cache from platformio.cache import cleanup_content_cache
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.commands.platform import platform_update as cmd_platform_update from platformio.commands.platform import platform_update as cmd_platform_update
from platformio.commands.system.prune import calculate_unnecessary_system_data from platformio.commands.system.prune import calculate_unnecessary_system_data
from platformio.commands.upgrade import get_latest_version from platformio.commands.upgrade import get_latest_version

View File

@ -21,7 +21,7 @@ import click
import semantic_version import semantic_version
from platformio import fs, util from platformio import fs, util
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.compat import ci_strings_are_equal from platformio.compat import ci_strings_are_equal
from platformio.package.exception import ManifestException, MissingPackageManifestError from platformio.package.exception import ManifestException, MissingPackageManifestError
from platformio.package.lockfile import LockFile from platformio.package.lockfile import LockFile

View File

@ -28,7 +28,7 @@ from traceback import format_exc
import requests import requests
from platformio import __version__, app, exception, util from platformio import __version__, app, exception, util
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.compat import hashlib_encode_data, string_types from platformio.compat import hashlib_encode_data, string_types
from platformio.proc import is_ci, is_container from platformio.proc import is_ci, is_container
from platformio.project.helpers import is_platformio_project from platformio.project.helpers import is_platformio_project

View File

@ -175,6 +175,9 @@ def test_cmd( # pylint: disable=too-many-arguments,too-many-locals,redefined-bu
raise exception.ReturnErrorCode(1) raise exception.ReturnErrorCode(1)
cli = test_cmd
def print_suite_header(test_suite): def print_suite_header(test_suite):
click.echo( click.echo(
"Processing %s in %s environment" "Processing %s in %s environment"

View File

@ -21,7 +21,7 @@ import random
import pytest import pytest
import requests import requests
from platformio.commands.account import cli as cmd_account from platformio.account.cli import cli as cmd_account
from platformio.commands.org import cli as cmd_org from platformio.commands.org import cli as cmd_org
from platformio.commands.team import cli as cmd_team from platformio.commands.team import cli as cmd_team

View File

@ -17,7 +17,7 @@
import json import json
import re import re
from platformio.commands import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.commands.lib.command import cli as cmd_lib from platformio.commands.lib.command import cli as cmd_lib
from platformio.package.exception import UnknownPackageError from platformio.package.exception import UnknownPackageError
from platformio.util import strip_ansi_codes from platformio.util import strip_ansi_codes

View File

@ -21,7 +21,7 @@ import pytest
from platformio import proc from platformio import proc
from platformio.fs import load_json from platformio.fs import load_json
from platformio.test.command import test_cmd as pio_test_cmd from platformio.test.cli import test_cmd as pio_test_cmd
def test_calculator_example(tmp_path: Path): def test_calculator_example(tmp_path: Path):