From 62b80c396bc2eb669430acb41b55f9fecb8a4283 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 9 May 2019 00:51:28 +0300 Subject: [PATCH] Added support for the latest Python "Click" package (CLI Builder) // Resolve #349 --- HISTORY.rst | 2 ++ platformio/__main__.py | 38 +------------------------- platformio/commands/__init__.py | 48 +++++++++++++++++++++++++++++++++ platformio/commands/lib.py | 3 ++- platformio/maintenance.py | 20 +++++++------- platformio/managers/core.py | 2 +- platformio/telemetry.py | 9 ++++--- setup.py | 2 +- tests/commands/test_init.py | 2 +- tests/commands/test_lib.py | 3 +++ tests/commands/test_platform.py | 4 +-- 11 files changed, 75 insertions(+), 58 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 6991bb7d..77c93c52 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,6 +14,8 @@ PlatformIO 4.0 * Include external configuration files with `extra_configs `__ option (`issue #1590 `_) * Override default source and include directories for a library via `library.json `__ manifest using ``includeDir`` and ``srcDir`` fields +* Added support for the latest Python "Click" package (CLI Builder) + (`issue #349 `_) PlatformIO 3.0 -------------- diff --git a/platformio/__main__.py b/platformio/__main__.py index 61db78de..9138fe3c 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -14,49 +14,13 @@ import os import sys -from os.path import join from platform import system from traceback import format_exc import click from platformio import __version__, exception, maintenance -from platformio.util import get_source_dir - - -class PlatformioCLI(click.MultiCommand): # pylint: disable=R0904 - - def list_commands(self, ctx): - cmds = [] - for filename in os.listdir(join(get_source_dir(), "commands")): - if filename.startswith("__init__"): - continue - if filename.endswith(".py"): - cmds.append(filename[:-3]) - cmds.sort() - return cmds - - def get_command(self, ctx, cmd_name): - mod = None - try: - mod = __import__("platformio.commands." + cmd_name, None, None, - ["cli"]) - except ImportError: - try: - return self._handle_obsolate_command(cmd_name) - except AttributeError: - raise click.UsageError('No such command "%s"' % cmd_name, ctx) - return mod.cli - - @staticmethod - def _handle_obsolate_command(name): - if name == "platforms": - from platformio.commands import platform - return platform.cli - if name == "serialports": - from platformio.commands import device - return device.cli - raise AttributeError() +from platformio.commands import PlatformioCLI @click.command( diff --git a/platformio/commands/__init__.py b/platformio/commands/__init__.py index b0514903..48dd394e 100644 --- a/platformio/commands/__init__.py +++ b/platformio/commands/__init__.py @@ -11,3 +11,51 @@ # 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 +from os.path import dirname, join + +import click + + +class PlatformioCLI(click.MultiCommand): + + leftover_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(PlatformioCLI, self).invoke(ctx) + + def list_commands(self, ctx): + cmds = [] + for filename in os.listdir(join(dirname(__file__), "commands")): + if filename.startswith("__init__"): + continue + if filename.endswith(".py"): + cmds.append(filename[:-3]) + cmds.sort() + return cmds + + def get_command(self, ctx, cmd_name): + mod = None + try: + mod = __import__("platformio.commands." + cmd_name, None, None, + ["cli"]) + except ImportError: + try: + return self._handle_obsolate_command(cmd_name) + except AttributeError: + raise click.UsageError('No such command "%s"' % cmd_name, ctx) + return mod.cli + + @staticmethod + def _handle_obsolate_command(name): + if name == "platforms": + from platformio.commands import platform + return platform.cli + if name == "serialports": + from platformio.commands import device + return device.cli + raise AttributeError() diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 7caf1271..c52350b1 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -21,6 +21,7 @@ from os.path import isdir, join import click from platformio import exception, util +from platformio.commands import PlatformioCLI from platformio.managers.lib import LibraryManager, get_builtin_libs from platformio.project.helpers import ( get_project_dir, get_projectlibdeps_dir, is_platformio_project) @@ -78,7 +79,7 @@ def cli(ctx, **options): ctx.invoked_subcommand) ctx.obj = LibraryManager(storage_dir) - if "--json-output" not in ctx.args: + if "--json-output" not in PlatformioCLI.leftover_args: click.echo("Library Storage: " + storage_dir) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 47105a5b..8841b7f5 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -22,6 +22,7 @@ import click import semantic_version from platformio import __version__, app, exception, telemetry, util +from platformio.commands import PlatformioCLI from platformio.commands.lib import lib_update as cmd_lib_update from platformio.commands.platform import \ platform_install as cmd_platform_install @@ -40,12 +41,12 @@ def on_platformio_start(ctx, force, caller): set_caller(caller) telemetry.on_command() - if not in_silence(ctx): + if not in_silence(): after_upgrade(ctx) -def on_platformio_end(ctx, result): # pylint: disable=W0613 - if in_silence(ctx): +def on_platformio_end(ctx, result): # pylint: disable=unused-argument + if in_silence(): return try: @@ -64,14 +65,11 @@ def on_platformio_exception(e): telemetry.on_exception(e) -def in_silence(ctx=None): - ctx = ctx or app.get_session_var("command_ctx") - if not ctx: - return True - return ctx.args and any([ - ctx.args[0] == "debug" and "--interpreter" in " ".join(ctx.args), - ctx.args[0] == "upgrade", "--json-output" in ctx.args, - "--version" in ctx.args +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 ]) diff --git a/platformio/managers/core.py b/platformio/managers/core.py index 05822f7a..be9e3a1d 100644 --- a/platformio/managers/core.py +++ b/platformio/managers/core.py @@ -27,7 +27,7 @@ CORE_PACKAGES = { "contrib-piohome": "^2.0.1", "contrib-pysite": "~2.%d%d.190418" % (sys.version_info[0], sys.version_info[1]), - "tool-pioplus": "^2.1.4", + "tool-pioplus": "^2.1.5", "tool-unity": "~1.20403.0", "tool-scons": "~2.20501.7" if util.PY2 else "~3.30005.0" } diff --git a/platformio/telemetry.py b/platformio/telemetry.py index 12e4a034..987d5899 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -27,6 +27,7 @@ import click import requests from platformio import __version__, app, exception, util +from platformio.commands import PlatformioCLI try: import queue @@ -133,10 +134,10 @@ class MeasurementProtocol(TelemetryBase): return _arg return None - if not app.get_session_var("command_ctx"): - return - ctx_args = app.get_session_var("command_ctx").args - args = [str(s).lower() for s in ctx_args if not str(s).startswith("-")] + args = [ + str(arg).lower() for arg in PlatformioCLI.leftover_args + if not str(arg).startswith("-") + ] if not args: return cmd_path = args[:1] diff --git a/setup.py b/setup.py index 667a2842..eb667d72 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ from platformio import (__author__, __description__, __email__, __license__, install_requires = [ "bottle<0.13", - "click>=5,<6", + "click>=5,<8", "colorama", "pyserial>=3,<4,!=3.3", "requests>=2.4.0,<3", diff --git a/tests/commands/test_init.py b/tests/commands/test_init.py index 1d7d699e..4e8eac09 100644 --- a/tests/commands/test_init.py +++ b/tests/commands/test_init.py @@ -57,7 +57,7 @@ def test_init_duplicated_boards(clirunner, validate_cliresult, tmpdir): def test_init_ide_without_board(clirunner, tmpdir): with tmpdir.as_cwd(): result = clirunner.invoke(cmd_init, ["--ide", "atom"]) - assert result.exit_code == -1 + assert result.exit_code != 0 assert isinstance(result.exception, exception.ProjectEnvsNotAvailable) diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index b67cec39..47e5a709 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -16,8 +16,11 @@ import json import re from platformio import exception +from platformio.commands import PlatformioCLI from platformio.commands.lib import cli as cmd_lib +PlatformioCLI.leftover_args = ["--json-output"] # hook for click + def test_search(clirunner, validate_cliresult): result = clirunner.invoke(cmd_lib, ["search", "DHT22"]) diff --git a/tests/commands/test_platform.py b/tests/commands/test_platform.py index d327ef37..72941574 100644 --- a/tests/commands/test_platform.py +++ b/tests/commands/test_platform.py @@ -38,14 +38,14 @@ def test_search_raw_output(clirunner, validate_cliresult): def test_install_unknown_version(clirunner): result = clirunner.invoke(cli_platform.platform_install, ["atmelavr@99.99.99"]) - assert result.exit_code == -1 + assert result.exit_code != 0 assert isinstance(result.exception, exception.UndefinedPackageVersion) def test_install_unknown_from_registry(clirunner): result = clirunner.invoke(cli_platform.platform_install, ["unknown-platform"]) - assert result.exit_code == -1 + assert result.exit_code != 0 assert isinstance(result.exception, exception.UnknownPackage)