mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
Tools: Export selected target actions
Added option --json to action help, for export selected target actions
This commit is contained in:
24
tools/idf.py
24
tools/idf.py
@ -37,8 +37,8 @@ import python_version_checker # noqa: E402
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from idf_py_actions.errors import FatalError # noqa: E402
|
from idf_py_actions.errors import FatalError # noqa: E402
|
||||||
from idf_py_actions.tools import (PropertyDict, executable_exists, idf_version, merge_action_lists, # noqa: E402
|
from idf_py_actions.tools import (PropertyDict, executable_exists, get_target, idf_version, # noqa: E402
|
||||||
realpath)
|
merge_action_lists, realpath)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# For example, importing click could cause this.
|
# For example, importing click could cause this.
|
||||||
print('Please use idf.py only in an ESP-IDF shell environment.', file=sys.stderr)
|
print('Please use idf.py only in an ESP-IDF shell environment.', file=sys.stderr)
|
||||||
@ -376,6 +376,7 @@ def init_cli(verbose_output: List=None) -> Any:
|
|||||||
chain=True,
|
chain=True,
|
||||||
invoke_without_command=True,
|
invoke_without_command=True,
|
||||||
result_callback=self.execute_tasks,
|
result_callback=self.execute_tasks,
|
||||||
|
no_args_is_help=True,
|
||||||
context_settings={'max_content_width': 140},
|
context_settings={'max_content_width': 140},
|
||||||
help=help,
|
help=help,
|
||||||
)
|
)
|
||||||
@ -530,10 +531,6 @@ def init_cli(verbose_output: List=None) -> Any:
|
|||||||
ctx = click.get_current_context()
|
ctx = click.get_current_context()
|
||||||
global_args = PropertyDict(kwargs)
|
global_args = PropertyDict(kwargs)
|
||||||
|
|
||||||
def _help_and_exit() -> None:
|
|
||||||
print(ctx.get_help())
|
|
||||||
ctx.exit()
|
|
||||||
|
|
||||||
# Show warning if some tasks are present several times in the list
|
# Show warning if some tasks are present several times in the list
|
||||||
dupplicated_tasks = sorted(
|
dupplicated_tasks = sorted(
|
||||||
[item for item, count in Counter(task.name for task in tasks).items() if count > 1])
|
[item for item, count in Counter(task.name for task in tasks).items() if count > 1])
|
||||||
@ -546,10 +543,6 @@ def init_cli(verbose_output: List=None) -> Any:
|
|||||||
'Only first occurrence will be executed.')
|
'Only first occurrence will be executed.')
|
||||||
|
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
# Show help and exit if help is in the list of commands
|
|
||||||
if task.name == 'help':
|
|
||||||
_help_and_exit()
|
|
||||||
|
|
||||||
# Set propagated global options.
|
# Set propagated global options.
|
||||||
# These options may be set on one subcommand, but available in the list of global arguments
|
# These options may be set on one subcommand, but available in the list of global arguments
|
||||||
for key in list(task.action_args):
|
for key in list(task.action_args):
|
||||||
@ -577,10 +570,6 @@ def init_cli(verbose_output: List=None) -> Any:
|
|||||||
for action_callback in ctx.command.global_action_callbacks:
|
for action_callback in ctx.command.global_action_callbacks:
|
||||||
action_callback(ctx, global_args, tasks)
|
action_callback(ctx, global_args, tasks)
|
||||||
|
|
||||||
# Always show help when command is not provided
|
|
||||||
if not tasks:
|
|
||||||
_help_and_exit()
|
|
||||||
|
|
||||||
# Build full list of tasks to and deal with dependencies and order dependencies
|
# Build full list of tasks to and deal with dependencies and order dependencies
|
||||||
tasks_to_run: OrderedDict = OrderedDict()
|
tasks_to_run: OrderedDict = OrderedDict()
|
||||||
while tasks:
|
while tasks:
|
||||||
@ -634,7 +623,9 @@ def init_cli(verbose_output: List=None) -> Any:
|
|||||||
if task.aliases:
|
if task.aliases:
|
||||||
name_with_aliases += ' (aliases: %s)' % ', '.join(task.aliases)
|
name_with_aliases += ' (aliases: %s)' % ', '.join(task.aliases)
|
||||||
|
|
||||||
print('Executing action: %s' % name_with_aliases)
|
# When machine-readable json format for help is printed, don't show info about executing action so the output is deserializable
|
||||||
|
if name_with_aliases != 'help' or not task.action_args.get('json_option', False):
|
||||||
|
print('Executing action: %s' % name_with_aliases)
|
||||||
task(ctx, global_args, task.action_args)
|
task(ctx, global_args, task.action_args)
|
||||||
|
|
||||||
self._print_closing_message(global_args, tasks_to_run.keys())
|
self._print_closing_message(global_args, tasks_to_run.keys())
|
||||||
@ -715,7 +706,8 @@ def init_cli(verbose_output: List=None) -> Any:
|
|||||||
|
|
||||||
cli_help = (
|
cli_help = (
|
||||||
'ESP-IDF CLI build management tool. '
|
'ESP-IDF CLI build management tool. '
|
||||||
'For commands that are not known to idf.py an attempt to execute it as a build system target will be made.')
|
'For commands that are not known to idf.py an attempt to execute it as a build system target will be made. '
|
||||||
|
'Selected target: {}'.format(get_target(project_dir)))
|
||||||
|
|
||||||
return CLI(help=cli_help, verbose_output=verbose_output, all_actions=all_actions)
|
return CLI(help=cli_help, verbose_output=verbose_output, all_actions=all_actions)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import json
|
||||||
import locale
|
import locale
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -193,7 +194,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Any:
|
|||||||
for target in SUPPORTED_TARGETS:
|
for target in SUPPORTED_TARGETS:
|
||||||
print(target)
|
print(target)
|
||||||
|
|
||||||
if 'preview' in ctx.params:
|
if ctx.params.get('preview'):
|
||||||
for target in PREVIEW_TARGETS:
|
for target in PREVIEW_TARGETS:
|
||||||
print(target)
|
print(target)
|
||||||
|
|
||||||
@ -238,6 +239,24 @@ def action_extensions(base_actions: Dict, project_path: str) -> Any:
|
|||||||
language = 'en'
|
language = 'en'
|
||||||
return language
|
return language
|
||||||
|
|
||||||
|
def help_and_exit(action: str, ctx: Context, param: List, json_option: bool, add_options: bool) -> None:
|
||||||
|
if json_option:
|
||||||
|
output_dict = {}
|
||||||
|
output_dict['target'] = get_target(param.project_dir) # type: ignore
|
||||||
|
output_dict['actions'] = []
|
||||||
|
actions = ctx.to_info_dict().get('command').get('commands')
|
||||||
|
for a in actions:
|
||||||
|
action_info = {}
|
||||||
|
action_info['name'] = a
|
||||||
|
action_info['description'] = actions[a].get('help')
|
||||||
|
if add_options:
|
||||||
|
action_info['options'] = actions[a].get('params')
|
||||||
|
output_dict['actions'].append(action_info)
|
||||||
|
print(json.dumps(output_dict, sort_keys=True, indent=4))
|
||||||
|
else:
|
||||||
|
print(ctx.get_help())
|
||||||
|
ctx.exit()
|
||||||
|
|
||||||
root_options = {
|
root_options = {
|
||||||
'global_options': [
|
'global_options': [
|
||||||
{
|
{
|
||||||
@ -286,6 +305,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Any:
|
|||||||
{
|
{
|
||||||
'names': ['--preview'],
|
'names': ['--preview'],
|
||||||
'help': 'Enable IDF features that are still in preview.',
|
'help': 'Enable IDF features that are still in preview.',
|
||||||
|
'is_eager': True,
|
||||||
'is_flag': True,
|
'is_flag': True,
|
||||||
'default': False,
|
'default': False,
|
||||||
},
|
},
|
||||||
@ -530,4 +550,26 @@ def action_extensions(base_actions: Dict, project_path: str) -> Any:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return merge_action_lists(root_options, build_actions, clean_actions)
|
help_action = {
|
||||||
|
'actions': {
|
||||||
|
'help': {
|
||||||
|
'callback': help_and_exit,
|
||||||
|
'help': 'Show help message and exit.',
|
||||||
|
'hidden': True,
|
||||||
|
'options': [
|
||||||
|
{
|
||||||
|
'names': ['--json', 'json_option'],
|
||||||
|
'is_flag': True,
|
||||||
|
'help': 'Print out actions in machine-readable format for selected target.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'names': ['--add-options'],
|
||||||
|
'is_flag': True,
|
||||||
|
'help': 'Add options about actions to machine-readable format.'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return merge_action_lists(root_options, build_actions, clean_actions, help_action)
|
||||||
|
46
tools/test_idf_py/idf_py_help_schema.json
Normal file
46
tools/test_idf_py/idf_py_help_schema.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://github.com/espressif/esp-idf/blob/master/tools/test_idf_py/idf_py_help_schema.json",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"target": {
|
||||||
|
"type": ["string", "null"],
|
||||||
|
"description": "Selected target"
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of supported actions",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/actionInfo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"target",
|
||||||
|
"actions"
|
||||||
|
],
|
||||||
|
"definitions": {
|
||||||
|
"actionInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Information about one action",
|
||||||
|
"properties": {
|
||||||
|
"name" : {
|
||||||
|
"description": "Action name",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description" : {
|
||||||
|
"description": "Description of the action",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"description": "Additional info about action's options",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"description"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,11 +3,14 @@
|
|||||||
# SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from unittest import TestCase, main, mock
|
from unittest import TestCase, main, mock
|
||||||
|
|
||||||
|
import jsonschema
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -227,5 +230,21 @@ class TestDeprecations(TestWithoutExtensions):
|
|||||||
self.assertNotIn('"test_0" is deprecated', output)
|
self.assertNotIn('"test_0" is deprecated', output)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHelpOutput(TestWithoutExtensions):
|
||||||
|
def test_output(self):
|
||||||
|
def action_test(commands, schema):
|
||||||
|
output_file = 'idf_py_help_output.json'
|
||||||
|
with open(output_file, 'w') as outfile:
|
||||||
|
subprocess.run(commands, env=os.environ, stdout=outfile)
|
||||||
|
with open(output_file, 'r') as outfile:
|
||||||
|
help_obj = json.load(outfile)
|
||||||
|
self.assertIsNone(jsonschema.validate(help_obj, schema))
|
||||||
|
|
||||||
|
with open(os.path.join(current_dir, 'idf_py_help_schema.json'), 'r') as schema_file:
|
||||||
|
schema_json = json.load(schema_file)
|
||||||
|
action_test(['idf.py', 'help', '--json'], schema_json)
|
||||||
|
action_test(['idf.py', 'help', '--json', '--add-options'], schema_json)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user