mirror of
https://github.com/ansible/awx.git
synced 2026-06-25 16:38:03 -02:30
fix: awxkit help flags for detailed & general help
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,28 @@ class CLI(object):
|
||||
def help(self):
|
||||
return '--help' in self.argv or '-h' in self.argv
|
||||
|
||||
def _get_non_option_args(self, before_help=False):
|
||||
"""Extract non-option arguments from argv, optionally only those before help flag."""
|
||||
if before_help and self.help:
|
||||
# Find position of help flag
|
||||
help_pos = next((i for i, arg in enumerate(self.argv) if arg in ('--help', '-h')), len(self.argv))
|
||||
args_to_check = self.argv[:help_pos]
|
||||
else:
|
||||
args_to_check = self.argv
|
||||
|
||||
return [arg for arg in args_to_check if not arg.startswith('-') and arg != 'awx']
|
||||
|
||||
def _is_main_help_request(self):
|
||||
"""
|
||||
Determine if help request is for main CLI (awx --help) vs subcommand (awx users create --help).
|
||||
Returns True if this is a main CLI help request that should exit early.
|
||||
"""
|
||||
if not self.help:
|
||||
return False
|
||||
|
||||
# If there are non-option arguments before help flag, this is subcommand help
|
||||
return len(self._get_non_option_args(before_help=True)) == 0
|
||||
|
||||
def authenticate(self):
|
||||
"""Configure the current session for authentication.
|
||||
|
||||
@@ -224,6 +246,16 @@ class CLI(object):
|
||||
subparsers = self.subparsers[self.resource].add_subparsers(dest='action', metavar='action')
|
||||
subparsers.required = True
|
||||
|
||||
# Add manual help handling for resource-level help
|
||||
# since we disabled add_help=False for resource subparsers
|
||||
if self.help:
|
||||
# Check if this is resource-level help (no action specified)
|
||||
non_option_args = self._get_non_option_args()
|
||||
if len(non_option_args) == 1 and non_option_args[0] == self.resource:
|
||||
# Only resource specified, no action - show resource-level help
|
||||
self.subparsers[self.resource].print_help()
|
||||
return
|
||||
|
||||
# parse the action from OPTIONS
|
||||
parser = ResourceOptionsParser(self.v2, page, self.resource, subparsers)
|
||||
if parser.deprecated:
|
||||
@@ -232,6 +264,18 @@ class CLI(object):
|
||||
description = colored(description, 'yellow')
|
||||
self.subparsers[self.resource].description = description
|
||||
|
||||
# parse any action arguments FIRST before attempting to parse
|
||||
if self.resource != 'settings':
|
||||
for method in ('list', 'modify', 'create'):
|
||||
if method in parser.parser.choices:
|
||||
if method == 'list':
|
||||
http_method = 'GET'
|
||||
elif method == 'modify' and 'PUT' in parser.options:
|
||||
http_method = 'PUT'
|
||||
else:
|
||||
http_method = 'POST'
|
||||
parser.build_query_arguments(method, http_method)
|
||||
|
||||
if from_sphinx:
|
||||
# Our Sphinx plugin runs `parse_action` for *every* available
|
||||
# resource + action in the API so that it can generate usage
|
||||
@@ -244,23 +288,15 @@ class CLI(object):
|
||||
self.parser.parse_known_args(self.argv)[0]
|
||||
except SystemExit:
|
||||
pass
|
||||
else:
|
||||
self.parser.parse_known_args()[0]
|
||||
|
||||
# parse any action arguments
|
||||
if self.resource != 'settings':
|
||||
for method in ('list', 'modify', 'create'):
|
||||
if method in parser.parser.choices:
|
||||
if method == 'list':
|
||||
http_method = 'GET'
|
||||
elif method == 'modify' and 'PUT' in parser.options:
|
||||
http_method = 'PUT'
|
||||
else:
|
||||
http_method = 'POST'
|
||||
parser.build_query_arguments(method, http_method)
|
||||
if from_sphinx:
|
||||
parsed, extra = self.parser.parse_known_args(self.argv)
|
||||
else:
|
||||
# Try to parse to determine if help is requested for a specific action
|
||||
try:
|
||||
self.parser.parse_known_args()[0]
|
||||
except SystemExit:
|
||||
# This happens when required arguments are missing, which is expected behavior
|
||||
# Let argparse handle it and show the appropriate help
|
||||
raise
|
||||
parsed, extra = self.parser.parse_known_args()
|
||||
|
||||
if extra and self.verbose:
|
||||
@@ -313,6 +349,7 @@ class CLI(object):
|
||||
self.argv = argv
|
||||
self.parser = HelpfulArgumentParser(add_help=False)
|
||||
self.parser.add_argument(
|
||||
'-h',
|
||||
'--help',
|
||||
action='store_true',
|
||||
help='prints usage information for the awx tool',
|
||||
@@ -322,6 +359,13 @@ class CLI(object):
|
||||
add_output_formatting_arguments(self.parser, env)
|
||||
|
||||
self.args = self.parser.parse_known_args(self.argv)[0]
|
||||
|
||||
# Early return for help to avoid server connection, but only for main CLI help
|
||||
# Allow subcommand help (like 'awx users create --help') to continue processing
|
||||
if self.help and self._is_main_help_request():
|
||||
self.parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
self.verbose = self.get_config('verbose')
|
||||
if self.verbose:
|
||||
logging.basicConfig(level='DEBUG')
|
||||
|
||||
@@ -126,7 +126,7 @@ class ResourceOptionsParser(object):
|
||||
if method not in action_map:
|
||||
continue
|
||||
method = action_map[method]
|
||||
parser = self.parser.add_parser(method, help='')
|
||||
parser = self.parser.add_parser(method, help='', add_help=True)
|
||||
if method == 'list':
|
||||
parser.add_argument(
|
||||
'--all',
|
||||
@@ -152,7 +152,7 @@ class ResourceOptionsParser(object):
|
||||
if 'DELETE' in self.allowed_options:
|
||||
allowed.append('delete')
|
||||
for method in allowed:
|
||||
parser = self.parser.add_parser(method, help='')
|
||||
parser = self.parser.add_parser(method, help='', add_help=True)
|
||||
self.parser.choices[method].add_argument(
|
||||
'id', type=functools.partial(pk_or_name, self.v2, self.resource), help='the ID (or unique name) of the resource'
|
||||
)
|
||||
|
||||
@@ -167,7 +167,9 @@ def parse_resource(client, skip_deprecated=False):
|
||||
if k in DEPRECATED_RESOURCES:
|
||||
kwargs['aliases'] = [DEPRECATED_RESOURCES[k]]
|
||||
|
||||
client.subparsers[k] = subparsers.add_parser(k, help='', **kwargs)
|
||||
# Disable automatic help handling for resource subparsers to prevent
|
||||
# premature help display before action subparsers are built
|
||||
client.subparsers[k] = subparsers.add_parser(k, help='', add_help=False, **kwargs)
|
||||
|
||||
resource = client.parser.parse_known_args()[0].resource
|
||||
if resource in DEPRECATED_RESOURCES.values():
|
||||
|
||||
Reference in New Issue
Block a user