Repository: boto/boto3
File: boto3/docs/method.py (Python)

Code before:
# Copyright 2015 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 botocore.docs.method import document_model_driven_method


def document_model_driven_resource_method(
        section, method_name, operation_model, event_emitter,
        method_description=None, example_prefix=None, include_input=None,
        include_output=None, exclude_input=None, exclude_output=None,
        document_output=True, resource_action_model=None):

    document_model_driven_method(
        section=section, method_name=method_name,
        operation_model=operation_model,
        event_emitter=event_emitter,
        method_description=method_description,
        example_prefix=example_prefix,
        include_input=include_input,
        include_output=include_output,
        exclude_input=exclude_input,
        exclude_output=exclude_output,
        document_output=document_output
    )

    # If this action returns a reource modify the return example to
    # appropriately reflect that.
    if resource_action_model.resource:
        if 'return' in section.available_sections:
            section.delete_section('return')
        resource_type = resource_action_model.resource.type
                
        new_return_section = section.add_new_section('return')
        return_resource_type = '%s.%s' % (
            operation_model.service_model.service_name,
            resource_type)

        return_type = ':py:class:`%s`' % return_resource_type
        return_description = '%s resource' % (resource_type)

        if resource_action_model.path and '[]' in resource_action_model.path:
            return_type = 'list(%s)' % return_type
            return_description = 'A list of %s resources' % (
                resource_type)

        new_return_section.style.new_line()
        new_return_section.write(
            ':rtype: %s' % return_type)
        new_return_section.style.new_line()
        new_return_section.write(
            ':returns: %s' % return_description)
        new_return_section.style.new_line()


Review comment (bug):
So I think this logic that I originally put in place only accounts for a subset of the all of the possible occasions where a list of resources can be returned. After talking with @trevorrowe, the only true way to tell if a list or resources is returned is if the returned resource definition has at least one identifier that has a `[]` in its path. It would be cool if we can update the logic to that because your fix currently will not fix some other edge cases such as any of the create_tags actions. Here is the model https://github.com/boto/boto3/blob/develop/boto3/data/ec2/2014-10-01/resources-1.json#L528 and this is what the docs output: http://boto3.readthedocs.org/en/latest/reference/services/ec2.html#EC2.Image.create_tags which is incorrect.


Code after:
# Copyright 2015 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 botocore.docs.method import document_model_driven_method


def document_model_driven_resource_method(
        section, method_name, operation_model, event_emitter,
        method_description=None, example_prefix=None, include_input=None,
        include_output=None, exclude_input=None, exclude_output=None,
        document_output=True, resource_action_model=None):

    document_model_driven_method(
        section=section, method_name=method_name,
        operation_model=operation_model,
        event_emitter=event_emitter,
        method_description=method_description,
        example_prefix=example_prefix,
        include_input=include_input,
        include_output=include_output,
        exclude_input=exclude_input,
        exclude_output=exclude_output,
        document_output=document_output
    )

    # If this action returns a resource modify the return example to
    # appropriately reflect that.
    if resource_action_model.resource:
        if 'return' in section.available_sections:
            section.delete_section('return')
        resource_type = resource_action_model.resource.type
                
        new_return_section = section.add_new_section('return')
        return_resource_type = '%s.%s' % (
            operation_model.service_model.service_name,
            resource_type)

        return_type = ':py:class:`%s`' % return_resource_type
        return_description = '%s resource' % (resource_type)

        if _method_returns_resource_list(resource_action_model.resource):
            return_type = 'list(%s)' % return_type
            return_description = 'A list of %s resources' % (
                resource_type)

        new_return_section.style.new_line()
        new_return_section.write(
            ':rtype: %s' % return_type)
        new_return_section.style.new_line()
        new_return_section.write(
            ':returns: %s' % return_description)
        new_return_section.style.new_line()


def _method_returns_resource_list(resource):
    for identifier in resource.identifiers:
        if identifier.path and '[]' in identifier.path:
            return True

    return False