docstring.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. # Copyright 2015 ksyun.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://www.apache.org/licenses/LICENSE-2.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.
  13. from kscore.docs.method import document_model_driven_method
  14. from kscore.docs.waiter import document_wait_method
  15. from kscore.docs.paginator import document_paginate_method
  16. from kscore.docs.bcdoc.restdoc import DocumentStructure
  17. class LazyLoadedDocstring(str):
  18. """Used for lazily loading docstrings
  19. You can instantiate this class and assign it to a __doc__ value.
  20. The docstring will not be generated till accessed via __doc__ or
  21. help(). Note that all docstring classes **must** subclass from
  22. this class. It cannot be used directly as a docstring.
  23. """
  24. def __init__(self, *args, **kwargs):
  25. """
  26. The args and kwargs are the same as the underlying document
  27. generation function. These just get proxied to the underlying
  28. function.
  29. """
  30. super(LazyLoadedDocstring, self).__init__()
  31. self._gen_args = args
  32. self._gen_kwargs = kwargs
  33. self._docstring = None
  34. def __new__(cls, *args, **kwargs):
  35. # Needed in order to sub class from str with args and kwargs
  36. return super(LazyLoadedDocstring, cls).__new__(cls)
  37. def _write_docstring(self, *args, **kwargs):
  38. raise NotImplementedError(
  39. '_write_docstring is not implemented. Please subclass from '
  40. 'this class and provide your own _write_docstring method'
  41. )
  42. def expandtabs(self, tabsize=8):
  43. """Expands tabs to spaces
  44. So this is a big hack in order to get lazy loaded docstring work
  45. for the ``help()``. In the ``help()`` function, ``pydoc`` and
  46. ``inspect`` are used. At some point the ``inspect.cleandoc``
  47. method is called. To clean the docs ``expandtabs`` is called
  48. and that is where we override the method to generate and return the
  49. docstrings.
  50. """
  51. if self._docstring is None:
  52. self._generate()
  53. return self._docstring.expandtabs(tabsize)
  54. def __str__(self):
  55. return self._generate()
  56. # __doc__ of target will use either __repr__ or __str__ of this class.
  57. __repr__ = __str__
  58. def _generate(self):
  59. # Generate the docstring if it is not already cached.
  60. if self._docstring is None:
  61. self._docstring = self._create_docstring()
  62. return self._docstring
  63. def _create_docstring(self):
  64. docstring_structure = DocumentStructure('docstring')
  65. # Call the document method function with the args and kwargs
  66. # passed to the class.
  67. self._write_docstring(
  68. docstring_structure, *self._gen_args,
  69. **self._gen_kwargs)
  70. return docstring_structure.flush_structure().decode('utf-8')
  71. class ClientMethodDocstring(LazyLoadedDocstring):
  72. def _write_docstring(self, *args, **kwargs):
  73. document_model_driven_method(*args, **kwargs)
  74. class WaiterDocstring(LazyLoadedDocstring):
  75. def _write_docstring(self, *args, **kwargs):
  76. document_wait_method(*args, **kwargs)
  77. class PaginatorDocstring(LazyLoadedDocstring):
  78. def _write_docstring(self, *args, **kwargs):
  79. document_paginate_method(*args, **kwargs)