codekingpro/portable-devtools
115k
1# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.2#3# Licensed under the Apache License, Version 2.0 (the "License"). You4# may not use this file except in compliance with the License. A copy of5# the License is located at6#7# http://aws.amazon.com/apache2.0/8#9# or in the "license" file accompanying this file. This file is10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF11# ANY KIND, either express or implied. See the License for the specific12# language governing permissions and limitations under the License.13import inspect14import types15 16from botocore.docs.example import (17 RequestExampleDocumenter,18 ResponseExampleDocumenter,19)20from botocore.docs.params import (21 RequestParamsDocumenter,22 ResponseParamsDocumenter,23)24 25AWS_DOC_BASE = 'https://docs.aws.amazon.com/goto/WebAPI'26 27 28def get_instance_public_methods(instance):29 """Retrieves an objects public methods30 31 :param instance: The instance of the class to inspect32 :rtype: dict33 :returns: A dictionary that represents an instance's methods where34 the keys are the name of the methods and the35 values are the handler to the method.36 """37 instance_members = inspect.getmembers(instance)38 instance_methods = {}39 for name, member in instance_members:40 if not name.startswith('_'):41 if inspect.ismethod(member):42 instance_methods[name] = member43 return instance_methods44 45 46def document_model_driven_signature(47 section, name, operation_model, include=None, exclude=None48):49 """Documents the signature of a model-driven method50 51 :param section: The section to write the documentation to.52 53 :param name: The name of the method54 55 :param operation_model: The operation model for the method56 57 :type include: Dictionary where keys are parameter names and58 values are the shapes of the parameter names.59 :param include: The parameter shapes to include in the documentation.60 61 :type exclude: List of the names of the parameters to exclude.62 :param exclude: The names of the parameters to exclude from63 documentation.64 """65 params = {}66 if operation_model.input_shape:67 params = operation_model.input_shape.members68 69 parameter_names = list(params.keys())70 71 if include is not None:72 for member in include:73 parameter_names.append(member.name)74 75 if exclude is not None:76 for member in exclude:77 if member in parameter_names:78 parameter_names.remove(member)79 80 signature_params = ''81 if parameter_names:82 signature_params = '**kwargs'83 section.style.start_sphinx_py_method(name, signature_params)84 85 86def document_custom_signature(87 section, name, method, include=None, exclude=None88):89 """Documents the signature of a custom method90 91 :param section: The section to write the documentation to.92 93 :param name: The name of the method94 95 :param method: The handle to the method being documented96 97 :type include: Dictionary where keys are parameter names and98 values are the shapes of the parameter names.99 :param include: The parameter shapes to include in the documentation.100 101 :type exclude: List of the names of the parameters to exclude.102 :param exclude: The names of the parameters to exclude from103 documentation.104 """105 signature = inspect.signature(method)106 # "raw" class methods are FunctionType and they include "self" param107 # object methods are MethodType and they skip the "self" param108 if isinstance(method, types.FunctionType):109 self_param = next(iter(signature.parameters))110 self_kind = signature.parameters[self_param].kind111 # safety check that we got the right parameter112 assert self_kind == inspect.Parameter.POSITIONAL_OR_KEYWORD113 new_params = signature.parameters.copy()114 del new_params[self_param]115 signature = signature.replace(parameters=new_params.values())116 signature_params = str(signature).lstrip('(')117 signature_params = signature_params.rstrip(')')118 section.style.start_sphinx_py_method(name, signature_params)119 120 121def document_custom_method(section, method_name, method):122 """Documents a non-data driven method123 124 :param section: The section to write the documentation to.125 126 :param method_name: The name of the method127 128 :param method: The handle to the method being documented129 """130 full_method_name = f"{section.context.get('qualifier', '')}{method_name}"131 document_custom_signature(section, full_method_name, method)132 method_intro_section = section.add_new_section('method-intro')133 method_intro_section.writeln('')134 doc_string = inspect.getdoc(method)135 if doc_string is not None:136 method_intro_section.style.write_py_doc_string(doc_string)137 138 139def document_model_driven_method(140 section,141 method_name,142 operation_model,143 event_emitter,144 method_description=None,145 example_prefix=None,146 include_input=None,147 include_output=None,148 exclude_input=None,149 exclude_output=None,150 document_output=True,151 include_signature=True,152):153 """Documents an individual method154 155 :param section: The section to write to156 157 :param method_name: The name of the method158 159 :param operation_model: The model of the operation160 161 :param event_emitter: The event emitter to use to emit events162 163 :param example_prefix: The prefix to use in the method example.164 165 :type include_input: Dictionary where keys are parameter names and166 values are the shapes of the parameter names.167 :param include_input: The parameter shapes to include in the168 input documentation.169 170 :type include_output: Dictionary where keys are parameter names and171 values are the shapes of the parameter names.172 :param include_input: The parameter shapes to include in the173 output documentation.174 175 :type exclude_input: List of the names of the parameters to exclude.176 :param exclude_input: The names of the parameters to exclude from177 input documentation.178 179 :type exclude_output: List of the names of the parameters to exclude.180 :param exclude_input: The names of the parameters to exclude from181 output documentation.182 183 :param document_output: A boolean flag to indicate whether to184 document the output.185 186 :param include_signature: Whether or not to include the signature.187 It is useful for generating docstrings.188 """189 # Add the signature if specified.190 if include_signature:191 document_model_driven_signature(192 section,193 method_name,194 operation_model,195 include=include_input,196 exclude=exclude_input,197 )198 199 # Add the description for the method.200 method_intro_section = section.add_new_section('method-intro')201 method_intro_section.include_doc_string(method_description)202 if operation_model.deprecated:203 method_intro_section.style.start_danger()204 method_intro_section.writeln(205 'This operation is deprecated and may not function as '206 'expected. This operation should not be used going forward '207 'and is only kept for the purpose of backwards compatiblity.'208 )209 method_intro_section.style.end_danger()210 service_uid = operation_model.service_model.metadata.get('uid')211 if service_uid is not None:212 method_intro_section.style.new_paragraph()213 method_intro_section.write("See also: ")214 link = f"{AWS_DOC_BASE}/{service_uid}/{operation_model.name}"215 method_intro_section.style.external_link(216 title="AWS API Documentation", link=link217 )218 method_intro_section.writeln('')219 220 # Add the example section.221 example_section = section.add_new_section('request-example')222 example_section.style.new_paragraph()223 example_section.style.bold('Request Syntax')224 225 context = {226 'special_shape_types': {227 'streaming_input_shape': operation_model.get_streaming_input(),228 'streaming_output_shape': operation_model.get_streaming_output(),229 'eventstream_output_shape': operation_model.get_event_stream_output(),230 },231 }232 233 if operation_model.input_shape:234 RequestExampleDocumenter(235 service_name=operation_model.service_model.service_name,236 operation_name=operation_model.name,237 event_emitter=event_emitter,238 context=context,239 ).document_example(240 example_section,241 operation_model.input_shape,242 prefix=example_prefix,243 include=include_input,244 exclude=exclude_input,245 )246 else:247 example_section.style.new_paragraph()248 example_section.style.start_codeblock()249 example_section.write(example_prefix + '()')250 251 # Add the request parameter documentation.252 request_params_section = section.add_new_section('request-params')253 if operation_model.input_shape:254 RequestParamsDocumenter(255 service_name=operation_model.service_model.service_name,256 operation_name=operation_model.name,257 event_emitter=event_emitter,258 context=context,259 ).document_params(260 request_params_section,261 operation_model.input_shape,262 include=include_input,263 exclude=exclude_input,264 )265 266 # Add the return value documentation267 return_section = section.add_new_section('return')268 return_section.style.new_line()269 if operation_model.output_shape is not None and document_output:270 return_section.write(':rtype: dict')271 return_section.style.new_line()272 return_section.write(':returns: ')273 return_section.style.indent()274 return_section.style.new_line()275 276 # If the operation is an event stream, describe the tagged union277 event_stream_output = operation_model.get_event_stream_output()278 if event_stream_output:279 event_section = return_section.add_new_section('event-stream')280 event_section.style.new_paragraph()281 event_section.write(282 'The response of this operation contains an '283 ':class:`.EventStream` member. When iterated the '284 ':class:`.EventStream` will yield events based on the '285 'structure below, where only one of the top level keys '286 'will be present for any given event.'287 )288 event_section.style.new_line()289 290 # Add an example return value291 return_example_section = return_section.add_new_section(292 'response-example'293 )294 return_example_section.style.new_line()295 return_example_section.style.bold('Response Syntax')296 return_example_section.style.new_paragraph()297 ResponseExampleDocumenter(298 service_name=operation_model.service_model.service_name,299 operation_name=operation_model.name,300 event_emitter=event_emitter,301 context=context,302 ).document_example(303 return_example_section,304 operation_model.output_shape,305 include=include_output,306 exclude=exclude_output,307 )308 309 # Add a description for the return value310 return_description_section = return_section.add_new_section(311 'description'312 )313 return_description_section.style.new_line()314 return_description_section.style.bold('Response Structure')315 return_description_section.style.new_paragraph()316 ResponseParamsDocumenter(317 service_name=operation_model.service_model.service_name,318 operation_name=operation_model.name,319 event_emitter=event_emitter,320 context=context,321 ).document_params(322 return_description_section,323 operation_model.output_shape,324 include=include_output,325 exclude=exclude_output,326 )327 else:328 return_section.write(':returns: None')329 