-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #963 from kyleknap/json-skeleton
Json skeleton
- Loading branch information
Showing
20 changed files
with
782 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"). You | ||
# may not use this file except in compliance with the License. A copy of | ||
# the License is located at | ||
# | ||
# http://aws.amazon.com/apache2.0/ | ||
# | ||
# or in the "license" file accompanying this file. This file 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. | ||
from awscli.arguments import CustomArgument | ||
|
||
|
||
class OverrideRequiredArgsArgument(CustomArgument): | ||
"""An argument that if specified makes all other arguments not required | ||
By not required, it refers to not having an error thrown when the | ||
parser does not find an argument that is required on the command line. | ||
To obtain this argument's property of ignoring required arguments, | ||
subclass from this class and fill out the ``ARG_DATA`` parameter as | ||
described below. Note this class is really only useful for subclassing. | ||
""" | ||
|
||
# ``ARG_DATA`` follows the same format as a member of ``ARG_TABLE`` in | ||
# ``BasicCommand`` class as specified in | ||
# ``awscli/customizations/commands.py``. | ||
# | ||
# For example, an ``ARG_DATA`` variable would be filled out as: | ||
# | ||
# ARG_DATA = | ||
# {'name': 'my-argument', | ||
# 'help_text': 'This is argument ensures the argument is specified' | ||
# 'no other arguments are required'} | ||
ARG_DATA = {'name': 'no-required-args'} | ||
|
||
def __init__(self, session): | ||
self._session = session | ||
self._register_argument_action() | ||
super(OverrideRequiredArgsArgument, self).__init__(**self.ARG_DATA) | ||
|
||
def _register_argument_action(self): | ||
self._session.register('before-building-argument-table-parser', | ||
self.override_required_args) | ||
|
||
def override_required_args(self, argument_table, args, **kwargs): | ||
name_in_cmdline = '--' + self.name | ||
# Set all ``Argument`` objects in ``argument_table`` to not required | ||
# if this argument's name is present in the command line. | ||
if name_in_cmdline in args: | ||
for arg_name in argument_table.keys(): | ||
argument_table[arg_name].required = False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"). You | ||
# may not use this file except in compliance with the License. A copy of | ||
# the License is located at | ||
# | ||
# http://aws.amazon.com/apache2.0/ | ||
# | ||
# or in the "license" file accompanying this file. This file 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 json | ||
|
||
from awscli.paramfile import get_paramfile | ||
from awscli.argprocess import ParamError | ||
from awscli.customizations.arguments import OverrideRequiredArgsArgument | ||
|
||
|
||
def register_cli_input_json(cli): | ||
cli.register('building-argument-table', add_cli_input_json) | ||
|
||
|
||
def add_cli_input_json(operation, argument_table, **kwargs): | ||
# This argument cannot support operations with streaming output which | ||
# is designated by the argument name `outfile`. | ||
if 'outfile' not in argument_table: | ||
cli_input_json_argument = CliInputJSONArgument(operation) | ||
cli_input_json_argument.add_to_arg_table(argument_table) | ||
|
||
|
||
class CliInputJSONArgument(OverrideRequiredArgsArgument): | ||
"""This argument inputs a JSON string as the entire input for a command. | ||
Ideally, the value to this argument should be a filled out JSON file | ||
generated by ``--generate-cli-skeleton``. The items in the JSON string | ||
will not clobber other arguments entered into the command line. | ||
""" | ||
ARG_DATA = { | ||
'name': 'cli-input-json', | ||
'help_text': 'Performs service operation based on the JSON string ' | ||
'provided. The JSON string follows the format provided ' | ||
'by ``--generate-cli-skeleton``. If other arguments are ' | ||
'provided on the command line, it will not clobber their ' | ||
'values.' | ||
} | ||
|
||
def __init__(self, operation_object): | ||
self._operation_object = operation_object | ||
super(CliInputJSONArgument, self).__init__( | ||
self._operation_object.session) | ||
|
||
def _register_argument_action(self): | ||
self._operation_object.session.register( | ||
'calling-command', self.add_to_call_parameters) | ||
super(CliInputJSONArgument, self)._register_argument_action() | ||
|
||
def add_to_call_parameters(self, call_parameters, parsed_args, | ||
parsed_globals, **kwargs): | ||
|
||
# Check if ``--cli-input-json`` was specified in the command line. | ||
input_json = getattr(parsed_args, 'cli_input_json', None) | ||
if input_json is not None: | ||
# Retrieve the JSON from the file if needed. | ||
retrieved_json = get_paramfile(input_json) | ||
# Nothing was retrieved from the file. So assume the argument | ||
# is already a JSON string. | ||
if retrieved_json is None: | ||
retrieved_json = input_json | ||
try: | ||
# Try to load the JSON string into a python dictionary | ||
input_data = json.loads(retrieved_json) | ||
except ValueError as e: | ||
raise ParamError( | ||
self.name, "Invalid JSON: %s\nJSON received: %s" | ||
% (e, retrieved_json)) | ||
# Add the members from the input JSON to the call parameters. | ||
self._update_call_parameters(call_parameters, input_data) | ||
|
||
def _update_call_parameters(self, call_parameters, input_data): | ||
for input_key in input_data.keys(): | ||
# Only add the values to ``call_parameters`` if not already | ||
# present. | ||
if input_key not in call_parameters: | ||
call_parameters[input_key] = input_data[input_key] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"). You | ||
# may not use this file except in compliance with the License. A copy of | ||
# the License is located at | ||
# | ||
# http://aws.amazon.com/apache2.0/ | ||
# | ||
# or in the "license" file accompanying this file. This file 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 json | ||
import sys | ||
|
||
from botocore.utils import ArgumentGenerator | ||
|
||
from awscli.customizations.arguments import OverrideRequiredArgsArgument | ||
|
||
|
||
def register_generate_cli_skeleton(cli): | ||
cli.register('building-argument-table', add_generate_skeleton) | ||
|
||
|
||
def add_generate_skeleton(operation, argument_table, **kwargs): | ||
# This argument cannot support operations with streaming output which | ||
# is designated by the argument name `outfile`. | ||
if 'outfile' not in argument_table: | ||
generate_cli_skeleton_argument = GenerateCliSkeletonArgument(operation) | ||
generate_cli_skeleton_argument.add_to_arg_table(argument_table) | ||
|
||
|
||
class GenerateCliSkeletonArgument(OverrideRequiredArgsArgument): | ||
"""This argument writes a generated JSON skeleton to stdout | ||
The argument, if present in the command line, will prevent the intended | ||
command from taking place. Instead, it will generate a JSON skeleton and | ||
print it to standard output. This JSON skeleton then can be filled out | ||
and can be used as input to ``--input-cli-json`` in order to run the | ||
command with the filled out JSON skeleton. | ||
""" | ||
ARG_DATA = { | ||
'name': 'generate-cli-skeleton', | ||
'help_text': 'Prints a sample input JSON to standard output. Note the ' | ||
'specified operation is not run if this argument is ' | ||
'specified. The sample input can be used as an argument ' | ||
'for ``--cli-input-json``.', | ||
'action': 'store_true', | ||
'group_name': 'generate_cli_skeleton' | ||
} | ||
|
||
def __init__(self, operation_object): | ||
self._operation_object = operation_object | ||
super(GenerateCliSkeletonArgument, self).__init__( | ||
self._operation_object.session) | ||
|
||
def _register_argument_action(self): | ||
self._operation_object.session.register( | ||
'calling-command.*', self.generate_json_skeleton) | ||
super(GenerateCliSkeletonArgument, self)._register_argument_action() | ||
|
||
def generate_json_skeleton(self, call_parameters, parsed_args, | ||
parsed_globals, **kwargs): | ||
|
||
# Only perform the method if the ``--generate-cli-skeleton`` was | ||
# included in the command line. | ||
if getattr(parsed_args, 'generate_cli_skeleton', False): | ||
|
||
# Obtain the model of the operation | ||
operation_model = self._operation_object.model | ||
|
||
# Generate the skeleton based on the ``input_shape``. | ||
argument_generator = ArgumentGenerator() | ||
operation_input_shape = operation_model.input_shape | ||
# If the ``input_shape`` is ``None``, generate an empty | ||
# dictionary. | ||
if operation_input_shape is None: | ||
skeleton = {} | ||
else: | ||
skeleton = argument_generator.generate_skeleton( | ||
operation_input_shape) | ||
|
||
# Write the generated skeleton to standard output. | ||
sys.stdout.write(json.dumps(skeleton, indent=4)) | ||
sys.stdout.write('\n') | ||
# This is the return code | ||
return 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.