Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions awscli/clidocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
from botocore.model import StringShape
from botocore.utils import is_json_value_header

from awscli import SCALAR_TYPES, __version__ as AWS_CLI_VERSION
from awscli import SCALAR_TYPES
from awscli import __version__ as AWS_CLI_VERSION
from awscli.argprocess import ParamShorthandDocGen
from awscli.bcdoc.docevents import DOC_EVENTS
from awscli.topictags import TopicTagDB
Expand Down Expand Up @@ -133,6 +134,17 @@ def doc_description(self, help_command, **kwargs):
doc.include_doc_string(help_command.description)
doc.style.new_paragraph()

def _add_agent_toolkit_note(self, help_command):
namespace = help_command.event_class.split('.', 1)[0]
if namespace == 'agent-toolkit':
return
doc = help_command.doc
doc.style.new_paragraph()
doc.writeln(
'See also: Official AWS skills may be available, '
'"aws agent-toolkit help".'
)

def doc_synopsis_start(self, help_command, **kwargs):
self._documented_arg_groups = []
doc = help_command.doc
Expand Down Expand Up @@ -461,6 +473,7 @@ def doc_description(self, help_command, **kwargs):
doc.style.h2('Description')
# TODO: need a documentation attribute.
doc.include_doc_string(service_model.documentation)
self._add_agent_toolkit_note(help_command)

def doc_subitems_start(self, help_command, **kwargs):
doc = help_command.doc
Expand All @@ -484,7 +497,9 @@ def doc_meta_description(self, help_command, **kwargs):
doc = help_command.doc
reference = help_command.event_class.replace('.', ' ')
doc.writeln(".. meta::")
doc.writeln(f" :description: Learn about the AWS CLI {AWS_CLI_VERSION} {reference} commands.")
doc.writeln(
f" :description: Learn about the AWS CLI {AWS_CLI_VERSION} {reference} commands."
)
doc.writeln("")


Expand All @@ -498,6 +513,7 @@ def doc_description(self, help_command, **kwargs):
doc.include_doc_string(operation_model.documentation)
self._add_webapi_crosslink(help_command)
self._add_note_for_document_types_if_used(help_command)
self._add_agent_toolkit_note(help_command)

def _add_webapi_crosslink(self, help_command):
doc = help_command.doc
Expand Down Expand Up @@ -698,9 +714,12 @@ def doc_meta_description(self, help_command, **kwargs):
doc = help_command.doc
reference = help_command.event_class.replace('.', ' ')
doc.writeln(".. meta::")
doc.writeln(f" :description: Use the AWS CLI {AWS_CLI_VERSION} to run the {reference} command.")
doc.writeln(
f" :description: Use the AWS CLI {AWS_CLI_VERSION} to run the {reference} command."
)
doc.writeln("")


class TopicListerDocumentEventHandler(CLIDocumentEventHandler):
DESCRIPTION = (
'This is the AWS CLI Topic Guide. It gives access to a set '
Expand Down
1 change: 1 addition & 0 deletions awscli/customizations/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ def doc_description(self, help_command, **kwargs):
self.doc.style.h2('Description')
self.doc.write(help_command.description)
self.doc.style.new_paragraph()
self._add_agent_toolkit_note(help_command)

def doc_synopsis_start(self, help_command, **kwargs):
if not help_command.synopsis:
Expand Down
2 changes: 1 addition & 1 deletion awscli/data/cli.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"description": "The AWS Command Line Interface is a unified tool to manage your AWS services.",
"synopsis": "aws [options] <command> <subcommand> [parameters]",
"help_usage": "Use *aws command help* for information on a specific command. Use *aws help topics* to view a list of available help topics. The synopsis for each command shows its parameters and their usage. Optional parameters are shown in square brackets.",
"help_usage": "Use *aws command help* for information on a specific command. Use *aws help topics* to view a list of available help topics. The synopsis for each command shows its parameters and their usage. Optional parameters are shown in square brackets. Use *aws agent-toolkit help* to browse and install official AWS skills, which provide steering instructions for coding agents.",
"options": {
"debug": {
"action": "store_true",
Expand Down
42 changes: 40 additions & 2 deletions tests/functional/docs/test_help_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def runner_url():
file_creator = FileCreator()
return runner(
file_creator.create_file(
'config', '[default]\n' 'cli_help_output = url\n'
'config', '[default]\ncli_help_output = url\n'
)
)

Expand All @@ -87,7 +87,7 @@ def runner_browser():
file_creator = FileCreator()
return runner(
file_creator.create_file(
'config', '[default]\n' 'cli_help_output = browser\n'
'config', '[default]\ncli_help_output = browser\n'
)
)

Expand Down Expand Up @@ -526,6 +526,44 @@ def test_operation_help_command_has_note(self):
)


class TestAgentToolkitNote(BaseAWSHelpOutputTest):
NOTE = 'See also: Official AWS skills may be available, "aws agent-toolkit help".'

def test_note_in_provider_help(self):
self.driver.main(['help'])
self.assert_contains(
'Use *aws agent-toolkit help* to browse and install'
)

def test_note_in_service_help(self):
self.driver.main(['ec2', 'help'])
self.assert_contains(self.NOTE)

def test_note_in_operation_help(self):
self.driver.main(['ec2', 'describe-instances', 'help'])
self.assert_contains(self.NOTE)

def test_note_in_custom_service_help(self):
self.driver.main(['s3', 'help'])
self.assert_contains(self.NOTE)

def test_note_in_custom_operation_help(self):
self.driver.main(['s3', 'ls', 'help'])
self.assert_contains(self.NOTE)

def test_note_not_in_agent_toolkit_service_help(self):
self.driver.main(['agent-toolkit', 'help'])
self.assert_not_contains(self.NOTE)

def test_note_not_in_agent_toolkit_modeled_operation_help(self):
self.driver.main(['agent-toolkit', 'list-available-skills', 'help'])
self.assert_not_contains(self.NOTE)

def test_note_not_in_agent_toolkit_custom_operation_help(self):
self.driver.main(['agent-toolkit', 'add-skill', 'help'])
self.assert_not_contains(self.NOTE)


class TestAliases(BaseAWSHelpOutputTest):
def setUp(self):
super().setUp()
Expand Down
83 changes: 74 additions & 9 deletions tests/unit/test_clidocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ def test_breadcrumbs_html(self):
doc_handler = CLIDocumentEventHandler(help_cmd)
doc_handler.doc_breadcrumbs(help_cmd)
self.assertEqual(
help_cmd.doc.getvalue().decode('utf-8'), '[ :ref:`aws <cli:aws>` ]\n\n'
help_cmd.doc.getvalue().decode('utf-8'),
'[ :ref:`aws <cli:aws>` ]\n\n',
)

def test_breadcrumbs_service_command_html(self):
Expand All @@ -237,7 +238,8 @@ def test_breadcrumbs_service_command_html(self):
doc_handler = CLIDocumentEventHandler(help_cmd)
doc_handler.doc_breadcrumbs(help_cmd)
self.assertEqual(
help_cmd.doc.getvalue().decode('utf-8'), '[ :ref:`aws <cli:aws>` ]\n\n'
help_cmd.doc.getvalue().decode('utf-8'),
'[ :ref:`aws <cli:aws>` ]\n\n',
)

def test_breadcrumbs_operation_command_html(self):
Expand All @@ -254,7 +256,7 @@ def test_breadcrumbs_operation_command_html(self):
doc_handler.doc_breadcrumbs(help_cmd)
self.assertEqual(
help_cmd.doc.getvalue().decode('utf-8'),
'[ :ref:`aws <cli:aws>` . :ref:`ec2 <cli:aws ec2>` ]\n\n'
'[ :ref:`aws <cli:aws>` . :ref:`ec2 <cli:aws ec2>` ]\n\n',
)

def test_breadcrumbs_wait_command_html(self):
Expand All @@ -274,7 +276,7 @@ def test_breadcrumbs_wait_command_html(self):
(
'[ :ref:`aws <cli:aws>` . :ref:`s3api <cli:aws s3api>`'
' . :ref:`wait <cli:aws s3api wait>` ]\n\n'
)
),
)

def test_documents_json_header_shape(self):
Expand Down Expand Up @@ -418,6 +420,58 @@ def test_includes_webapi_crosslink_in_html(self):
rendered,
)

def test_includes_agent_toolkit_note_in_operation_help(self):
help_command = self.create_help_command()
help_command.event_class = 'ec2.describe-instances'
operation_handler = OperationDocumentEventHandler(help_command)
operation_handler.doc_description(help_command=help_command)
rendered = help_command.doc.getvalue().decode('utf-8')
self.assertIn(
'See also: Official AWS skills may be available, '
'"aws agent-toolkit help".',
rendered,
)

def test_excludes_agent_toolkit_note_for_agent_toolkit_namespace(self):
help_command = self.create_help_command()
help_command.event_class = 'agent-toolkit.list-available-skills'
operation_handler = OperationDocumentEventHandler(help_command)
operation_handler.doc_description(help_command=help_command)
rendered = help_command.doc.getvalue().decode('utf-8')
self.assertNotIn('aws agent-toolkit help', rendered)

def test_includes_agent_toolkit_note_in_service_help(self):
help_cmd = ServiceHelpCommand(
self.session,
mock.Mock(documentation='description'),
self.command_table,
self.arg_table,
self.name,
'ec2',
)
doc_handler = ServiceDocumentEventHandler(help_cmd)
doc_handler.doc_description(help_command=help_cmd)
rendered = help_cmd.doc.getvalue().decode('utf-8')
self.assertIn(
'See also: Official AWS skills may be available, '
'"aws agent-toolkit help".',
rendered,
)

def test_excludes_agent_toolkit_note_for_agent_toolkit_service_help(self):
help_cmd = ServiceHelpCommand(
self.session,
mock.Mock(documentation='description'),
self.command_table,
self.arg_table,
self.name,
'agent-toolkit',
)
doc_handler = ServiceDocumentEventHandler(help_cmd)
doc_handler.doc_description(help_command=help_cmd)
rendered = help_cmd.doc.getvalue().decode('utf-8')
self.assertNotIn('aws agent-toolkit help', rendered)

def test_includes_streaming_blob_options(self):
help_command = self.create_help_command()
blob_shape = Shape('blob_shape', {'type': 'blob'})
Expand Down Expand Up @@ -546,8 +600,12 @@ def test_documents_constraints(self):

def test_meta_description_operation_command_html(self):
help_cmd = ServiceHelpCommand(
self.session, self.obj, self.command_table, self.arg_table,
self.name, 'ec2.run-instances'
self.session,
self.obj,
self.command_table,
self.arg_table,
self.name,
'ec2.run-instances',
)
help_cmd.doc.target = 'html'
doc_handler = OperationDocumentEventHandler(help_cmd)
Expand All @@ -559,15 +617,22 @@ def test_meta_description_operation_command_html(self):

def test_meta_description_service_html(self):
help_cmd = ServiceHelpCommand(
self.session, self.obj, self.command_table, self.arg_table,
self.name, 'ec2'
self.session,
self.obj,
self.command_table,
self.arg_table,
self.name,
'ec2',
)
help_cmd.doc.target = 'html'
doc_handler = ServiceDocumentEventHandler(help_cmd)
doc_handler.doc_meta_description(help_cmd)

meta_description = help_cmd.doc.getvalue().decode('utf-8')
self.assertIn(".. meta::\n :description: Learn about the AWS CLI ", meta_description)
self.assertIn(
".. meta::\n :description: Learn about the AWS CLI ",
meta_description,
)
self.assertIn(' ec2 commands', meta_description)


Expand Down
Loading