1# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"). You 4# may not use this file except in compliance with the License. A copy of 5# the License is located at 6# 7# http://aws.amazon.com/apache2.0/ 8# 9# or in the "license" file accompanying this file. This file is 10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 11# ANY KIND, either express or implied. See the License for the specific 12# language governing permissions and limitations under the License. 13from botocore.docs.method import document_model_driven_method 14from botocore.docs.waiter import document_wait_method 15from botocore.docs.paginator import document_paginate_method 16from botocore.docs.bcdoc.restdoc import DocumentStructure 17 18 19class LazyLoadedDocstring(str): 20 """Used for lazily loading docstrings 21 22 You can instantiate this class and assign it to a __doc__ value. 23 The docstring will not be generated till accessed via __doc__ or 24 help(). Note that all docstring classes **must** subclass from 25 this class. It cannot be used directly as a docstring. 26 """ 27 def __init__(self, *args, **kwargs): 28 """ 29 The args and kwargs are the same as the underlying document 30 generation function. These just get proxied to the underlying 31 function. 32 """ 33 super(LazyLoadedDocstring, self).__init__() 34 self._gen_args = args 35 self._gen_kwargs = kwargs 36 self._docstring = None 37 38 def __new__(cls, *args, **kwargs): 39 # Needed in order to sub class from str with args and kwargs 40 return super(LazyLoadedDocstring, cls).__new__(cls) 41 42 def _write_docstring(self, *args, **kwargs): 43 raise NotImplementedError( 44 '_write_docstring is not implemented. Please subclass from ' 45 'this class and provide your own _write_docstring method' 46 ) 47 48 def expandtabs(self, tabsize=8): 49 """Expands tabs to spaces 50 51 So this is a big hack in order to get lazy loaded docstring work 52 for the ``help()``. In the ``help()`` function, ``pydoc`` and 53 ``inspect`` are used. At some point the ``inspect.cleandoc`` 54 method is called. To clean the docs ``expandtabs`` is called 55 and that is where we override the method to generate and return the 56 docstrings. 57 """ 58 if self._docstring is None: 59 self._generate() 60 return self._docstring.expandtabs(tabsize) 61 62 def __str__(self): 63 return self._generate() 64 65 # __doc__ of target will use either __repr__ or __str__ of this class. 66 __repr__ = __str__ 67 68 def _generate(self): 69 # Generate the docstring if it is not already cached. 70 if self._docstring is None: 71 self._docstring = self._create_docstring() 72 return self._docstring 73 74 def _create_docstring(self): 75 docstring_structure = DocumentStructure('docstring', target='html') 76 # Call the document method function with the args and kwargs 77 # passed to the class. 78 self._write_docstring( 79 docstring_structure, *self._gen_args, 80 **self._gen_kwargs) 81 return docstring_structure.flush_structure().decode('utf-8') 82 83 84class ClientMethodDocstring(LazyLoadedDocstring): 85 def _write_docstring(self, *args, **kwargs): 86 document_model_driven_method(*args, **kwargs) 87 88 89class WaiterDocstring(LazyLoadedDocstring): 90 def _write_docstring(self, *args, **kwargs): 91 document_wait_method(*args, **kwargs) 92 93 94class PaginatorDocstring(LazyLoadedDocstring): 95 def _write_docstring(self, *args, **kwargs): 96 document_paginate_method(*args, **kwargs) 97