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
from platformio import __version__, exception, maintenance
from platformio.commands import PlatformioCLI
from platformio.cli import PlatformioCLI
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"])
)
@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("--no-ansi", is_flag=True, help="Do not print ANSI control characters")
@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.
# See the License for the specific language governing permissions and
# 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 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.package.exception import NotGlobalLibDir, UnknownPackageError
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.project.exception import NotPlatformIOProjectError
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")

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(
ctx,
project_dir,

View File

@ -20,7 +20,7 @@ from fnmatch import fnmatch
from hashlib import sha1
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 print_processing_header
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.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.system.prune import calculate_unnecessary_system_data
from platformio.commands.upgrade import get_latest_version

View File

@ -21,7 +21,7 @@ import click
import semantic_version
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.package.exception import ManifestException, MissingPackageManifestError
from platformio.package.lockfile import LockFile

View File

@ -28,7 +28,7 @@ from traceback import format_exc
import requests
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.proc import is_ci, is_container
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)
cli = test_cmd
def print_suite_header(test_suite):
click.echo(
"Processing %s in %s environment"

View File

@ -21,7 +21,7 @@ import random
import pytest
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.team import cli as cmd_team

View File

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

View File

@ -21,7 +21,7 @@ import pytest
from platformio import proc
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):