Ejemplo n.º 1
0
 def doc_option_example(self, arg_name, help_command, **kwargs):
     doc = help_command.doc
     cli_argument = help_command.arg_table[arg_name]
     if cli_argument.group_name in self._arg_groups:
         if cli_argument.group_name in self._documented_arg_groups:
             # Args with group_names (boolean args) don't
             # need to generate example syntax.
             return
     argument_model = cli_argument.argument_model
     docgen = ParamShorthandDocGen()
     if docgen.supports_shorthand(cli_argument):
         # TODO: bcdoc should not know about shorthand syntax. This
         # should be pulled out into a separate handler in the
         # awscli.customizations package.
         example_shorthand_syntax = docgen.generate_shorthand_example(cli_argument)
         if example_shorthand_syntax is None:
             # If the shorthand syntax returns a value of None,
             # this indicates to us that there is no example
             # needed for this param so we can immediately
             # return.
             return
         doc.style.new_paragraph()
         doc.write("Shorthand Syntax")
         doc.style.start_codeblock()
         for example_line in example_shorthand_syntax.splitlines():
             doc.writeln(example_line)
         doc.style.end_codeblock()
     if (
         argument_model is not None
         and argument_model.type_name == "list"
         and argument_model.member.type_name in SCALAR_TYPES
     ):
         # A list of scalars is special.  While you *can* use
         # JSON ( ["foo", "bar", "baz"] ), you can also just
         # use the argparse behavior of space separated lists.
         # "foo" "bar" "baz".  In fact we don't even want to
         # document the JSON syntax in this case.
         member = argument_model.member
         doc.style.new_paragraph()
         doc.write("Syntax")
         doc.style.start_codeblock()
         example_type = self._json_example_value_name(member, include_enum_values=False)
         doc.write("%s %s ..." % (example_type, example_type))
         if isinstance(member, StringShape) and member.enum:
             # If we have enum values, we can tell the user
             # exactly what valid values they can provide.
             self._write_valid_enums(doc, member.enum)
         doc.style.end_codeblock()
         doc.style.new_paragraph()
     elif cli_argument.cli_type_name not in SCALAR_TYPES:
         doc.style.new_paragraph()
         doc.write("JSON Syntax")
         doc.style.start_codeblock()
         self._json_example(doc, argument_model, stack=[])
         doc.style.end_codeblock()
         doc.style.new_paragraph()
 def doc_option_example(self, arg_name, help_command, event_name, **kwargs):
     service_id, operation_name = \
         find_service_and_method_in_event_name(event_name)
     doc = help_command.doc
     cli_argument = help_command.arg_table[arg_name]
     if cli_argument.group_name in self._arg_groups:
         if cli_argument.group_name in self._documented_arg_groups:
             # Args with group_names (boolean args) don't
             # need to generate example syntax.
             return
     argument_model = cli_argument.argument_model
     docgen = ParamShorthandDocGen()
     if docgen.supports_shorthand(cli_argument.argument_model):
         example_shorthand_syntax = docgen.generate_shorthand_example(
             cli_argument, service_id, operation_name)
         if example_shorthand_syntax is None:
             # If the shorthand syntax returns a value of None,
             # this indicates to us that there is no example
             # needed for this param so we can immediately
             # return.
             return
         if example_shorthand_syntax:
             doc.style.new_paragraph()
             doc.write('Shorthand Syntax')
             doc.style.start_codeblock()
             for example_line in example_shorthand_syntax.splitlines():
                 doc.writeln(example_line)
             doc.style.end_codeblock()
     if argument_model is not None and argument_model.type_name == 'list' and \
             argument_model.member.type_name in SCALAR_TYPES:
         # A list of scalars is special.  While you *can* use
         # JSON ( ["foo", "bar", "baz"] ), you can also just
         # use the argparse behavior of space separated lists.
         # "foo" "bar" "baz".  In fact we don't even want to
         # document the JSON syntax in this case.
         member = argument_model.member
         doc.style.new_paragraph()
         doc.write('Syntax')
         doc.style.start_codeblock()
         example_type = self._json_example_value_name(
             member, include_enum_values=False)
         doc.write('%s %s ...' % (example_type, example_type))
         if isinstance(member, StringShape) and member.enum:
             # If we have enum values, we can tell the user
             # exactly what valid values they can provide.
             self._write_valid_enums(doc, member.enum)
         doc.style.end_codeblock()
         doc.style.new_paragraph()
     elif cli_argument.cli_type_name not in SCALAR_TYPES:
         doc.style.new_paragraph()
         doc.write('JSON Syntax')
         doc.style.start_codeblock()
         self._json_example(doc, argument_model, stack=[])
         doc.style.end_codeblock()
         doc.style.new_paragraph()
Ejemplo n.º 3
0
 def doc_option_example(self, arg_name, help_command, **kwargs):
     doc = help_command.doc
     cli_argument = help_command.arg_table[arg_name]
     if cli_argument.group_name in self._arg_groups:
         if cli_argument.group_name in self._documented_arg_groups:
             # Args with group_names (boolean args) don't
             # need to generate example syntax.
             return
     argument_model = cli_argument.argument_model
     docgen = ParamShorthandDocGen()
     if docgen.supports_shorthand(cli_argument):
         # TODO: bcdoc should not know about shorthand syntax. This
         # should be pulled out into a separate handler in the
         # awscli.customizations package.
         example_shorthand_syntax = docgen.generate_shorthand_example(
             cli_argument)
         if example_shorthand_syntax is None:
             # If the shorthand syntax returns a value of None,
             # this indicates to us that there is no example
             # needed for this param so we can immediately
             # return.
             return
         doc.style.new_paragraph()
         doc.write('Shorthand Syntax')
         doc.style.start_codeblock()
         for example_line in example_shorthand_syntax.splitlines():
             doc.writeln(example_line)
         doc.style.end_codeblock()
     if argument_model is not None and argument_model.type_name == 'list' and \
             argument_model.member.type_name in SCALAR_TYPES:
         # A list of scalars is special.  While you *can* use
         # JSON ( ["foo", "bar", "baz"] ), you can also just
         # use the argparse behavior of space separated lists.
         # "foo" "bar" "baz".  In fact we don't even want to
         # document the JSON syntax in this case.
         doc.style.new_paragraph()
         doc.write('Syntax')
         doc.style.start_codeblock()
         example_type = self._json_example_value_name(
             argument_model.member, include_enum_values=False)
         doc.write('%s %s ...' % (example_type, example_type))
         if 'enum' in argument_model.member.metadata:
             # If we have enum values, we can tell the user
             # exactly what valid values they can provide.
             enum = argument_model.member.metadata['enum']
             self._write_valid_enums(doc, enum)
         doc.style.end_codeblock()
         doc.style.new_paragraph()
     elif cli_argument.cli_type_name not in SCALAR_TYPES:
         doc.style.new_paragraph()
         doc.write('JSON Syntax')
         doc.style.start_codeblock()
         self._json_example(doc, argument_model, stack=[])
         doc.style.end_codeblock()
         doc.style.new_paragraph()
Ejemplo n.º 4
0
 def setUp(self):
     super(TestDocGen, self).setUp()
     self.simplify = ParamShorthand()
     self.shorthand_documenter = ParamShorthandDocGen()
Ejemplo n.º 5
0
class TestDocGen(BaseArgProcessTest):
    # These aren't very extensive doc tests, as we want to stay somewhat
    # flexible and allow the docs to slightly change without breaking these
    # tests.
    def setUp(self):
        super(TestDocGen, self).setUp()
        self.simplify = ParamShorthand()
        self.shorthand_documenter = ParamShorthandDocGen()

    def get_generated_example_for(self, argument):
        # Returns a string containing the generated documentation.
        return self.shorthand_documenter.generate_shorthand_example(argument)

    def assert_generated_example_is(self, argument, expected_docs):
        generated_docs = self.get_generated_example_for(argument)
        self.assertEqual(generated_docs, expected_docs)

    def assert_generated_example_contains(self, argument, expected_to_contain):
        generated_docs = self.get_generated_example_for(argument)
        self.assertIn(expected_to_contain, generated_docs)

    def test_gen_map_type_docs(self):
        argument = self.get_param_model('sqs.SetQueueAttributes.Attributes')
        expected_example_str = (
            "--attributes key_name=string,key_name2=string\n"
            "Where valid key names are:\n"
            "  Policy")
        self.assert_generated_example_contains(argument, expected_example_str)

    def test_gen_list_scalar_docs(self):
        argument = self.get_param_model(
            'elb.RegisterInstancesWithLoadBalancer.Instances')
        doc_string = '--instances InstanceId1 InstanceId2 InstanceId3'
        self.assert_generated_example_is(argument, doc_string)

    def test_gen_list_structure_of_scalars_docs(self):
        argument = self.get_param_model('elb.CreateLoadBalancer.Listeners')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn(
            'Key value pairs, with multiple values separated by a space.',
            generated_example)
        self.assertIn('Protocol=string', generated_example)
        self.assertIn('LoadBalancerPort=integer', generated_example)
        self.assertIn('InstanceProtocol=string', generated_example)
        self.assertIn('InstancePort=integer', generated_example)
        self.assertIn('SSLCertificateId=string', generated_example)

    def test_gen_list_structure_multiple_scalar_docs(self):
        argument = self.get_param_model(
            'emr.ModifyInstanceGroups.InstanceGroups')
        expected = ('Key value pairs, where values are separated by commas, '
                    'and multiple pairs are separated by spaces.\n'
                    '--instance-groups InstanceGroupId=string1,'
                    'InstanceCount=integer1,EC2InstanceIdsToTerminate=string1,'
                    'string2 InstanceGroupId=string1,InstanceCount=integer1,'
                    'EC2InstanceIdsToTerminate=string1,string2')
        self.assert_generated_example_is(argument, expected)

    def test_gen_list_structure_list_scalar_scalar_docs(self):
        # Verify that we have *two* top level list items displayed,
        # so we make it clear that multiple values are separated by spaces.
        argument = self.get_param_model('ec2.DescribeInstances.Filters')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('multiple pairs are separated by spaces',
                      generated_example)
        self.assertIn(
            'Name=string1,Values=string1,string2 '
            'Name=string1,Values=string1,string2', generated_example)

    def test_gen_structure_list_scalar_docs(self):
        schema = {
            "type": "object",
            "properties": {
                "Consistent": {
                    "type": "boolean",
                },
                "Args": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        }
        argument_model = create_argument_model_from_schema(schema)
        cli_argument = CustomArgument('test', argument_model=argument_model)

        generated_example = self.get_generated_example_for(cli_argument)
        self.assertIn('Key value pairs', generated_example)
        self.assertIn('Consistent=boolean1,Args=string1,string2',
                      generated_example)
Ejemplo n.º 6
0
 def setUp(self):
     super(TestDocGen, self).setUp()
     self.shorthand_documenter = ParamShorthandDocGen()
Ejemplo n.º 7
0
class TestDocGen(BaseArgProcessTest):
    # These aren't very extensive doc tests, as we want to stay somewhat
    # flexible and allow the docs to slightly change without breaking these
    # tests.
    def setUp(self):
        super(TestDocGen, self).setUp()
        self.shorthand_documenter = ParamShorthandDocGen()

    def get_generated_example_for(self, argument):
        # Returns a string containing the generated documentation.
        return self.shorthand_documenter.generate_shorthand_example(
            argument.cli_name, argument.argument_model)

    def assert_generated_example_is(self, argument, expected_docs):
        generated_docs = self.get_generated_example_for(argument)
        self.assertEqual(generated_docs, expected_docs)

    def assert_generated_example_contains(self, argument, expected_to_contain):
        generated_docs = self.get_generated_example_for(argument)
        self.assertIn(expected_to_contain, generated_docs)

    def test_gen_map_type_docs(self):
        argument = self.get_param_model('sqs.SetQueueAttributes.Attributes')
        expected_example_str = (
            "KeyName1=string,KeyName2=string\n\n"
            "Where valid key names are:\n"
            "  Policy"
        )
        self.assert_generated_example_contains(argument, expected_example_str)

    def test_gen_list_scalar_docs(self):
        argument = self.get_param_model(
            'elb.RegisterInstancesWithLoadBalancer.Instances')
        doc_string = '--instances InstanceId1 InstanceId2 InstanceId3'
        self.assert_generated_example_is(argument, doc_string)

    def test_gen_list_structure_of_scalars_docs(self):
        argument = self.get_param_model('elb.CreateLoadBalancer.Listeners')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Protocol=string', generated_example)
        self.assertIn('LoadBalancerPort=integer', generated_example)
        self.assertIn('InstanceProtocol=string', generated_example)
        self.assertIn('InstancePort=integer', generated_example)
        self.assertIn('SSLCertificateId=string', generated_example)

    def test_gen_list_structure_multiple_scalar_docs(self):
        expected = (
            'Scalar1=string,'
            'Scalar2=string,'
            'List1=string,string ...'
        )
        arg = model.DenormalizedStructureBuilder().with_members(OrderedDict([
            ('List', {'type': 'list',
                      'member': {
                          'type': 'structure',
                          'members': OrderedDict([
                              ('Scalar1', {'type': 'string'}),
                              ('Scalar2', {'type': 'string'}),
                              ('List1', {
                                  'type': 'list',
                                  'member': {'type': 'string'},
                              }),
                          ]),
                      }}),
        ])).build_model().members['List']
        rendered = self.shorthand_documenter.generate_shorthand_example(
            '--foo', arg)
        self.assertIn(expected, rendered)

    def test_gen_list_structure_list_scalar_scalar_docs(self):
        # Verify that we have *two* top level list items displayed,
        # so we make it clear that multiple values are separated by spaces.
        argument = self.get_param_model('ec2.DescribeInstances.Filters')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Name=string,Values=string,string',
                      generated_example)

    def test_gen_structure_list_scalar_docs(self):
        schema = {
            "type": "object",
            "properties": {
                "Consistent": {
                    "type": "boolean",
                },
                "Args": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        }
        argument_model = create_argument_model_from_schema(schema)
        m = model.DenormalizedStructureBuilder().with_members(OrderedDict([
            ('Consistent', {'type': 'boolean'}),
            ('Args', { 'type': 'list', 'member': { 'type': 'string', }}),
        ])).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('Consistent=boolean,Args=string,string',
                      generated_example)

    def test_can_gen_recursive_structure(self):
        argument = self.get_param_model('dynamodb.PutItem.Item')
        generated_example = self.get_generated_example_for(argument)

    def test_can_document_nested_structs(self):
        argument = self.get_param_model('ec2.RunInstances.BlockDeviceMappings')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Ebs={SnapshotId=string', generated_example)

    def test_can_document_nested_lists(self):
        m = model.DenormalizedStructureBuilder().with_members({
            'A': {
                'type': 'list',
                'member': {
                    'type': 'list',
                    'member': {'type': 'string'},
                },
            },
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('A=[[string,string],[string,string]]', generated_example)

    def test_can_generated_nested_maps(self):
        m = model.DenormalizedStructureBuilder().with_members({
            'A': {
                'type': 'map',
                'key': {'type': 'string'},
                'value': {'type': 'string'}
            },
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('A={KeyName1=string,KeyName2=string}', generated_example)

    def test_list_of_structures_with_triple_dots(self):
        list_shape = {
            'type': 'list',
            'member': {'shape': 'StructShape'},
        }
        shapes = {
            'Top': list_shape,
            'String': {'type': 'string'},
            'StructShape': {
                'type': 'structure',
                'members': OrderedDict([
                    ('A', {'shape': 'String'}),
                    ('B', {'shape': 'String'}),
                ])
            }
        }
        m = model.ListShape(
            shape_name='Top',
            shape_model=list_shape,
            shape_resolver=model.ShapeResolver(shapes))
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('A=string,B=string ...', generated_example)

    def test_handle_special_case_value_struct_not_documented(self):
        m = model.DenormalizedStructureBuilder().with_members({
            'Value': {'type': 'string'}
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        # This is one of the special cases, we shouldn't generate any
        # shorthand example for this shape.
        self.assertIsNone(generated_example)

    def test_can_document_recursive_struct(self):
        # It's a little more work to set up a recursive
        # shape because DenormalizedStructureBuilder cannot handle
        # recursion.
        struct_shape = {
            'type': 'structure',
            'members': OrderedDict([
                ('Recurse', {'shape': 'SubShape'}),
                ('Scalar', {'shape': 'String'}),
            ]),
        }
        shapes = {
            'Top': struct_shape,
            'String': {'type': 'string'},
            'SubShape': {
                'type': 'structure',
                'members': OrderedDict([
                    ('SubRecurse', {'shape': 'Top'}),
                    ('Scalar', {'shape': 'String'}),
                ]),
            }
        }
        m = model.StructureShape(
            shape_name='Top',
            shape_model=struct_shape,
            shape_resolver=model.ShapeResolver(shapes))
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn(
            'Recurse={SubRecurse={( ... recursive ... ),Scalar=string},'
            'Scalar=string},Scalar=string',
            generated_example)

    def test_skip_deeply_nested_shorthand(self):
        # The eventual goal is to have a better way to document
        # deeply nested shorthand params, but for now, we'll
        # only document shorthand params up to a certain stack level.
        m = model.DenormalizedStructureBuilder().with_members({
            'A': {
                'type': 'structure',
                'members': {
                    'B': {
                        'type': 'structure',
                        'members': {
                            'C': {
                                'type': 'structure',
                                'members': {
                                    'D': {'type': 'string'},
                                }
                            }
                        }
                    }
                }
            },
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertEqual(generated_example, '')
Ejemplo n.º 8
0
class TestDocGen(BaseArgProcessTest):
    # These aren't very extensive doc tests, as we want to stay somewhat
    # flexible and allow the docs to slightly change without breaking these
    # tests.
    def setUp(self):
        super(TestDocGen, self).setUp()
        self.shorthand_documenter = ParamShorthandDocGen()

    def get_generated_example_for(self, argument):
        # Returns a string containing the generated documentation.
        return self.shorthand_documenter.generate_shorthand_example(
            argument.cli_name, argument.argument_model)

    def assert_generated_example_is(self, argument, expected_docs):
        generated_docs = self.get_generated_example_for(argument)
        self.assertEqual(generated_docs, expected_docs)

    def assert_generated_example_contains(self, argument, expected_to_contain):
        generated_docs = self.get_generated_example_for(argument)
        self.assertIn(expected_to_contain, generated_docs)

    def test_gen_map_type_docs(self):
        argument = self.get_param_model('sqs.SetQueueAttributes.Attributes')
        expected_example_str = ("KeyName1=string,KeyName2=string\n\n"
                                "Where valid key names are:\n"
                                "  Policy")
        self.assert_generated_example_contains(argument, expected_example_str)

    def test_gen_list_scalar_docs(self):
        argument = self.get_param_model(
            'elb.RegisterInstancesWithLoadBalancer.Instances')
        doc_string = '--instances InstanceId1 InstanceId2 InstanceId3'
        self.assert_generated_example_is(argument, doc_string)

    def test_gen_list_structure_of_scalars_docs(self):
        argument = self.get_param_model('elb.CreateLoadBalancer.Listeners')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Protocol=string', generated_example)
        self.assertIn('LoadBalancerPort=integer', generated_example)
        self.assertIn('InstanceProtocol=string', generated_example)
        self.assertIn('InstancePort=integer', generated_example)
        self.assertIn('SSLCertificateId=string', generated_example)

    def test_gen_list_structure_multiple_scalar_docs(self):
        argument = self.get_param_model(
            'emr.ModifyInstanceGroups.InstanceGroups')
        expected = ('InstanceGroupId=string,'
                    'InstanceCount=integer,EC2InstanceIdsToTerminate=string,'
                    'string ...')
        self.assert_generated_example_is(argument, expected)

    def test_gen_list_structure_list_scalar_scalar_docs(self):
        # Verify that we have *two* top level list items displayed,
        # so we make it clear that multiple values are separated by spaces.
        argument = self.get_param_model('ec2.DescribeInstances.Filters')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Name=string,Values=string,string', generated_example)

    def test_gen_structure_list_scalar_docs(self):
        schema = {
            "type": "object",
            "properties": {
                "Consistent": {
                    "type": "boolean",
                },
                "Args": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        }
        argument_model = create_argument_model_from_schema(schema)
        m = model.DenormalizedStructureBuilder().with_members(
            OrderedDict([
                ('Consistent', {
                    'type': 'boolean'
                }),
                ('Args', {
                    'type': 'list',
                    'member': {
                        'type': 'string',
                    }
                }),
            ])).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('Consistent=boolean,Args=string,string',
                      generated_example)

    def test_can_gen_recursive_structure(self):
        argument = self.get_param_model('dynamodb.PutItem.Item')
        generated_example = self.get_generated_example_for(argument)

    def test_can_document_nested_structs(self):
        argument = self.get_param_model('ec2.RunInstances.BlockDeviceMappings')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Ebs={SnapshotId=string', generated_example)

    def test_can_document_nested_lists(self):
        m = model.DenormalizedStructureBuilder().with_members({
            'A': {
                'type': 'list',
                'member': {
                    'type': 'list',
                    'member': {
                        'type': 'string'
                    },
                },
            },
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('A=[[string,string],[string,string]]', generated_example)

    def test_can_generated_nested_maps(self):
        m = model.DenormalizedStructureBuilder().with_members({
            'A': {
                'type': 'map',
                'key': {
                    'type': 'string'
                },
                'value': {
                    'type': 'string'
                }
            },
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('A={KeyName1=string,KeyName2=string}', generated_example)

    def test_list_of_structures_with_triple_dots(self):
        list_shape = {
            'type': 'list',
            'member': {
                'shape': 'StructShape'
            },
        }
        shapes = {
            'Top': list_shape,
            'String': {
                'type': 'string'
            },
            'StructShape': {
                'type':
                'structure',
                'members':
                OrderedDict([
                    ('A', {
                        'shape': 'String'
                    }),
                    ('B', {
                        'shape': 'String'
                    }),
                ])
            }
        }
        m = model.ListShape(shape_name='Top',
                            shape_model=list_shape,
                            shape_resolver=model.ShapeResolver(shapes))
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn('A=string,B=string ...', generated_example)

    def test_handle_special_case_value_struct_not_documented(self):
        m = model.DenormalizedStructureBuilder().with_members({
            'Value': {
                'type': 'string'
            }
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        # This is one of the special cases, we shouldn't generate any
        # shorthand example for this shape.
        self.assertIsNone(generated_example)

    def test_can_document_recursive_struct(self):
        # It's a little more work to set up a recursive
        # shape because DenormalizedStructureBuilder cannot handle
        # recursion.
        struct_shape = {
            'type':
            'structure',
            'members':
            OrderedDict([
                ('Recurse', {
                    'shape': 'SubShape'
                }),
                ('Scalar', {
                    'shape': 'String'
                }),
            ]),
        }
        shapes = {
            'Top': struct_shape,
            'String': {
                'type': 'string'
            },
            'SubShape': {
                'type':
                'structure',
                'members':
                OrderedDict([
                    ('SubRecurse', {
                        'shape': 'Top'
                    }),
                    ('Scalar', {
                        'shape': 'String'
                    }),
                ]),
            }
        }
        m = model.StructureShape(shape_name='Top',
                                 shape_model=struct_shape,
                                 shape_resolver=model.ShapeResolver(shapes))
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertIn(
            'Recurse={SubRecurse={( ... recursive ... ),Scalar=string},'
            'Scalar=string},Scalar=string', generated_example)

    def test_skip_deeply_nested_shorthand(self):
        # The eventual goal is to have a better way to document
        # deeply nested shorthand params, but for now, we'll
        # only document shorthand params up to a certain stack level.
        m = model.DenormalizedStructureBuilder().with_members({
            'A': {
                'type': 'structure',
                'members': {
                    'B': {
                        'type': 'structure',
                        'members': {
                            'C': {
                                'type': 'structure',
                                'members': {
                                    'D': {
                                        'type': 'string'
                                    },
                                }
                            }
                        }
                    }
                }
            },
        }).build_model()
        generated_example = self.shorthand_documenter.generate_shorthand_example(
            '--foo', m)
        self.assertEqual(generated_example, '')
Ejemplo n.º 9
0
from six import BytesIO
from docutils.core import publish_string
import awscli.clidriver
from awscli.argprocess import ParamShorthandDocGen
try:
    from botocore.docs.bcdoc import textwriter
except ImportError:
    from awscli.bcdoc import textwriter

from awsshell import determine_doc_index_filename
from awsshell.utils import remove_html
from awsshell import docs


SHORTHAND_DOC = ParamShorthandDocGen()


def new_index():
    return {'arguments': [], 'argument_metadata': {},
            'commands': [], 'children': {}}


def index_command(index_dict, help_command):
    arg_table = help_command.arg_table
    for arg in arg_table:
        arg_obj = arg_table[arg]
        metadata = {
            'required': arg_obj.required,
            'type_name': arg_obj.cli_type_name,
            'minidoc': '',
Ejemplo n.º 10
0
 def setUp(self):
     super(TestDocGen, self).setUp()
     self.shorthand_documenter = ParamShorthandDocGen()
     self.service_name = 'foo'
     self.operation_name = 'bar'
Ejemplo n.º 11
0
class TestDocGen(BaseArgProcessTest):
    # These aren't very extensive doc tests, as we want to stay somewhat
    # flexible and allow the docs to slightly change without breaking these
    # tests.
    def setUp(self):
        super(TestDocGen, self).setUp()
        self.shorthand_documenter = ParamShorthandDocGen()
        self.service_name = 'foo'
        self.operation_name = 'bar'

    def get_generated_example_for(self, argument):
        # Returns a string containing the generated documentation.
        return self.shorthand_documenter.generate_shorthand_example(
            argument, self.service_name, self.operation_name)

    def assert_generated_example_is(self, argument, expected_docs):
        generated_docs = self.get_generated_example_for(argument)
        self.assertEqual(generated_docs, expected_docs)

    def assert_generated_example_contains(self, argument, expected_to_contain):
        generated_docs = self.get_generated_example_for(argument)
        self.assertIn(expected_to_contain, generated_docs)

    def test_gen_map_type_docs(self):
        argument = self.get_param_model('sqs.SetQueueAttributes.Attributes')
        expected_example_str = ("KeyName1=string,KeyName2=string\n\n"
                                "Where valid key names are:\n")
        self.assert_generated_example_contains(argument, expected_example_str)

    def test_gen_list_scalar_docs(self):
        self.service_name = 'elb'
        self.operation_name = 'register-instances-with-load-balancer'
        argument = self.get_param_model(
            'elb.RegisterInstancesWithLoadBalancer.Instances')
        doc_string = '--instances InstanceId1 InstanceId2 InstanceId3'
        self.assert_generated_example_is(argument, doc_string)

    def test_flattens_marked_single_member_structure_list(self):
        argument = self.create_argument(
            {
                'Arg': {
                    'type': 'list',
                    'member': {
                        'type': 'structure',
                        'members': {
                            'Bar': {
                                'type': 'string'
                            }
                        }
                    }
                }
            }, 'arg')
        argument.argument_model = argument.argument_model.members['Arg']
        uses_old_list = 'awscli.argprocess.ParamShorthand._uses_old_list_case'
        with mock.patch(uses_old_list, mock.Mock(return_value=True)):
            self.assert_generated_example_is(argument, '--arg Bar1 Bar2 Bar3')

    def test_does_not_flatten_unmarked_single_member_structure_list(self):
        argument = self.create_argument(
            {
                'Arg': {
                    'type': 'list',
                    'member': {
                        'type': 'structure',
                        'members': {
                            'Bar': {
                                'type': 'string'
                            }
                        }
                    }
                }
            }, 'arg')
        argument.argument_model = argument.argument_model.members['Arg']
        uses_old_list = 'awscli.argprocess.ParamShorthand._uses_old_list_case'
        with mock.patch(uses_old_list, mock.Mock(return_value=False)):
            self.assert_generated_example_is(argument, 'Bar=string ...')

    def test_gen_list_structure_of_scalars_docs(self):
        argument = self.get_param_model('elb.CreateLoadBalancer.Listeners')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Protocol=string', generated_example)
        self.assertIn('LoadBalancerPort=integer', generated_example)
        self.assertIn('InstanceProtocol=string', generated_example)
        self.assertIn('InstancePort=integer', generated_example)
        self.assertIn('SSLCertificateId=string', generated_example)

    def test_gen_list_structure_multiple_scalar_docs(self):
        expected = ('Scalar1=string,'
                    'Scalar2=string,'
                    'List1=string,string ...')
        m = model.DenormalizedStructureBuilder().with_members(
            OrderedDict([
                ('List', {
                    'type': 'list',
                    'member': {
                        'type':
                        'structure',
                        'members':
                        OrderedDict([
                            ('Scalar1', {
                                'type': 'string'
                            }),
                            ('Scalar2', {
                                'type': 'string'
                            }),
                            ('List1', {
                                'type': 'list',
                                'member': {
                                    'type': 'string'
                                },
                            }),
                        ]),
                    }
                }),
            ])).build_model().members['List']
        argument = mock.Mock()
        argument.argument_model = m
        argument.name = 'foo'
        argument.cli_name = '--foo'
        generated_example = self.get_generated_example_for(argument)
        self.assertIn(expected, generated_example)

    def test_gen_list_structure_list_scalar_scalar_docs(self):
        # Verify that we have *two* top level list items displayed,
        # so we make it clear that multiple values are separated by spaces.
        argument = self.get_param_model('ec2.DescribeInstances.Filters')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Name=string,Values=string,string', generated_example)

    def test_gen_structure_list_scalar_docs(self):
        argument = self.create_argument(
            OrderedDict([
                ('Consistent', {
                    'type': 'boolean'
                }),
                ('Args', {
                    'type': 'list',
                    'member': {
                        'type': 'string'
                    }
                }),
            ]), 'foo')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('Consistent=boolean,Args=string,string',
                      generated_example)

    def test_can_gen_recursive_structure(self):
        argument = self.get_param_model('dynamodb.PutItem.Item')
        generated_example = self.get_generated_example_for(argument)

    def test_can_document_nested_structs(self):
        argument = self.get_param_model('ec2.RunInstances.BlockDeviceMappings')
        generated_example = self.get_generated_example_for(argument)
        self.assertRegexpMatches(generated_example, 'Ebs={\w+=\w+')

    def test_can_document_nested_lists(self):
        argument = self.create_argument({
            'A': {
                'type': 'list',
                'member': {
                    'type': 'list',
                    'member': {
                        'type': 'string'
                    },
                },
            },
        })
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('A=[[string,string],[string,string]]', generated_example)

    def test_can_generated_nested_maps(self):
        argument = self.create_argument({
            'A': {
                'type': 'map',
                'key': {
                    'type': 'string'
                },
                'value': {
                    'type': 'string'
                }
            },
        })
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('A={KeyName1=string,KeyName2=string}', generated_example)

    def test_list_of_structures_with_triple_dots(self):
        list_shape = {
            'type': 'list',
            'member': {
                'shape': 'StructShape'
            },
        }
        shapes = {
            'Top': list_shape,
            'String': {
                'type': 'string'
            },
            'StructShape': {
                'type':
                'structure',
                'members':
                OrderedDict([
                    ('A', {
                        'shape': 'String'
                    }),
                    ('B', {
                        'shape': 'String'
                    }),
                ])
            }
        }
        m = model.ListShape(shape_name='Top',
                            shape_model=list_shape,
                            shape_resolver=model.ShapeResolver(shapes))
        argument = mock.Mock()
        argument.argument_model = m
        argument.name = 'foo'
        argument.cli_name = '--foo'
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('A=string,B=string ...', generated_example)

    def test_handle_special_case_value_struct_not_documented(self):
        argument = self.create_argument({'Value': {'type': 'string'}})
        generated_example = self.get_generated_example_for(argument)
        # This is one of the special cases, we shouldn't generate any
        # shorthand example for this shape.
        self.assertIsNone(generated_example)

    def test_can_document_recursive_struct(self):
        # It's a little more work to set up a recursive
        # shape because DenormalizedStructureBuilder cannot handle
        # recursion.
        struct_shape = {
            'type':
            'structure',
            'members':
            OrderedDict([
                ('Recurse', {
                    'shape': 'SubShape'
                }),
                ('Scalar', {
                    'shape': 'String'
                }),
            ]),
        }
        shapes = {
            'Top': struct_shape,
            'String': {
                'type': 'string'
            },
            'SubShape': {
                'type':
                'structure',
                'members':
                OrderedDict([
                    ('SubRecurse', {
                        'shape': 'Top'
                    }),
                    ('Scalar', {
                        'shape': 'String'
                    }),
                ]),
            }
        }
        m = model.StructureShape(shape_name='Top',
                                 shape_model=struct_shape,
                                 shape_resolver=model.ShapeResolver(shapes))
        argument = mock.Mock()
        argument.argument_model = m
        argument.name = 'foo'
        argument.cli_name = '--foo'
        generated_example = self.get_generated_example_for(argument)
        self.assertIn(
            'Recurse={SubRecurse={( ... recursive ... ),Scalar=string},'
            'Scalar=string},Scalar=string', generated_example)

    def test_skip_deeply_nested_shorthand(self):
        # The eventual goal is to have a better way to document
        # deeply nested shorthand params, but for now, we'll
        # only document shorthand params up to a certain stack level.
        argument = self.create_argument({
            'A': {
                'type': 'structure',
                'members': {
                    'B': {
                        'type': 'structure',
                        'members': {
                            'C': {
                                'type': 'structure',
                                'members': {
                                    'D': {
                                        'type': 'string'
                                    },
                                }
                            }
                        }
                    }
                }
            },
        })
        generated_example = self.get_generated_example_for(argument)
        self.assertEqual(generated_example, '')
Ejemplo n.º 12
0
class TestDocGen(BaseArgProcessTest):
    # These aren't very extensive doc tests, as we want to stay somewhat
    # flexible and allow the docs to slightly change without breaking these
    # tests.
    def setUp(self):
        super(TestDocGen, self).setUp()
        self.simplify = ParamShorthand()
        self.shorthand_documenter = ParamShorthandDocGen()

    def get_generated_example_for(self, argument):
        # Returns a string containing the generated documentation.
        return self.shorthand_documenter.generate_shorthand_example(argument)

    def assert_generated_example_is(self, argument, expected_docs):
        generated_docs = self.get_generated_example_for(argument)
        self.assertEqual(generated_docs, expected_docs)

    def assert_generated_example_contains(self, argument, expected_to_contain):
        generated_docs = self.get_generated_example_for(argument)
        self.assertIn(expected_to_contain, generated_docs)

    def test_gen_map_type_docs(self):
        argument = self.get_param_model('sqs.SetQueueAttributes.Attributes')
        expected_example_str = (
            "--attributes key_name=string,key_name2=string\n"
            "Where valid key names are:\n"
            "  Policy"
        )
        self.assert_generated_example_contains(argument, expected_example_str)

    def test_gen_list_scalar_docs(self):
        argument = self.get_param_model(
            'elb.RegisterInstancesWithLoadBalancer.Instances')
        doc_string = '--instances InstanceId1 InstanceId2 InstanceId3'
        self.assert_generated_example_is(argument, doc_string)

    def test_gen_list_structure_of_scalars_docs(self):
        argument = self.get_param_model('elb.CreateLoadBalancer.Listeners')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn(
            'Key value pairs, with multiple values separated by a space.',
            generated_example)
        self.assertIn('Protocol=string', generated_example)
        self.assertIn('LoadBalancerPort=integer', generated_example)
        self.assertIn('InstanceProtocol=string', generated_example)
        self.assertIn('InstancePort=integer', generated_example)
        self.assertIn('SSLCertificateId=string', generated_example)

    def test_gen_list_structure_multiple_scalar_docs(self):
        argument = self.get_param_model(
            'emr.ModifyInstanceGroups.InstanceGroups')
        expected = (
            'Key value pairs, where values are separated by commas, '
             'and multiple pairs are separated by spaces.\n'
             '--instance-groups InstanceGroupId=string1,'
             'InstanceCount=integer1,EC2InstanceIdsToTerminate=string1,'
             'string2 InstanceGroupId=string1,InstanceCount=integer1,'
             'EC2InstanceIdsToTerminate=string1,string2')
        self.assert_generated_example_is(argument, expected)

    def test_gen_list_structure_list_scalar_scalar_docs(self):
        # Verify that we have *two* top level list items displayed,
        # so we make it clear that multiple values are separated by spaces.
        argument = self.get_param_model('ec2.DescribeInstances.Filters')
        generated_example = self.get_generated_example_for(argument)
        self.assertIn('multiple pairs are separated by spaces',
                      generated_example)
        self.assertIn('Name=string1,Values=string1,string2 '
                      'Name=string1,Values=string1,string2',
                      generated_example)

    def test_gen_structure_list_scalar_docs(self):
        schema = {
            "type": "object",
            "properties": {
                "Consistent": {
                    "type": "boolean",
                },
                "Args": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        }
        argument_model = create_argument_model_from_schema(schema)
        cli_argument = CustomArgument('test', argument_model=argument_model)

        generated_example = self.get_generated_example_for(cli_argument)
        self.assertIn('Key value pairs', generated_example)
        self.assertIn('Consistent=boolean1,Args=string1,string2',
                      generated_example)
Ejemplo n.º 13
0
 def setUp(self):
     super(TestDocGen, self).setUp()
     self.shorthand_documenter = ParamShorthandDocGen()
     self.service_name = 'foo'
     self.operation_name = 'bar'