_docstrings.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import re
  2. import pydoc
  3. from .external.docscrape import NumpyDocString
  4. class DocstringComponents:
  5. regexp = re.compile(r"\n((\n|.)+)\n\s*", re.MULTILINE)
  6. def __init__(self, comp_dict, strip_whitespace=True):
  7. """Read entries from a dict, optionally stripping outer whitespace."""
  8. if strip_whitespace:
  9. entries = {}
  10. for key, val in comp_dict.items():
  11. m = re.match(self.regexp, val)
  12. if m is None:
  13. entries[key] = val
  14. else:
  15. entries[key] = m.group(1)
  16. else:
  17. entries = comp_dict.copy()
  18. self.entries = entries
  19. def __getattr__(self, attr):
  20. """Provide dot access to entries for clean raw docstrings."""
  21. if attr in self.entries:
  22. return self.entries[attr]
  23. else:
  24. try:
  25. return self.__getattribute__(attr)
  26. except AttributeError as err:
  27. # If Python is run with -OO, it will strip docstrings and our lookup
  28. # from self.entries will fail. We check for __debug__, which is actually
  29. # set to False by -O (it is True for normal execution).
  30. # But we only want to see an error when building the docs;
  31. # not something users should see, so this slight inconsistency is fine.
  32. if __debug__:
  33. raise err
  34. else:
  35. pass
  36. @classmethod
  37. def from_nested_components(cls, **kwargs):
  38. """Add multiple sub-sets of components."""
  39. return cls(kwargs, strip_whitespace=False)
  40. @classmethod
  41. def from_function_params(cls, func):
  42. """Use the numpydoc parser to extract components from existing func."""
  43. params = NumpyDocString(pydoc.getdoc(func))["Parameters"]
  44. comp_dict = {}
  45. for p in params:
  46. name = p.name
  47. type = p.type
  48. desc = "\n ".join(p.desc)
  49. comp_dict[name] = f"{name} : {type}\n {desc}"
  50. return cls(comp_dict)
  51. # TODO is "vector" the best term here? We mean to imply 1D data with a variety
  52. # of types?
  53. # TODO now that we can parse numpydoc style strings, do we need to define dicts
  54. # of docstring components, or just write out a docstring?
  55. _core_params = dict(
  56. data="""
  57. data : :class:`pandas.DataFrame`, :class:`numpy.ndarray`, mapping, or sequence
  58. Input data structure. Either a long-form collection of vectors that can be
  59. assigned to named variables or a wide-form dataset that will be internally
  60. reshaped.
  61. """, # TODO add link to user guide narrative when exists
  62. xy="""
  63. x, y : vectors or keys in ``data``
  64. Variables that specify positions on the x and y axes.
  65. """,
  66. hue="""
  67. hue : vector or key in ``data``
  68. Semantic variable that is mapped to determine the color of plot elements.
  69. """,
  70. palette="""
  71. palette : string, list, dict, or :class:`matplotlib.colors.Colormap`
  72. Method for choosing the colors to use when mapping the ``hue`` semantic.
  73. String values are passed to :func:`color_palette`. List or dict values
  74. imply categorical mapping, while a colormap object implies numeric mapping.
  75. """, # noqa: E501
  76. hue_order="""
  77. hue_order : vector of strings
  78. Specify the order of processing and plotting for categorical levels of the
  79. ``hue`` semantic.
  80. """,
  81. hue_norm="""
  82. hue_norm : tuple or :class:`matplotlib.colors.Normalize`
  83. Either a pair of values that set the normalization range in data units
  84. or an object that will map from data units into a [0, 1] interval. Usage
  85. implies numeric mapping.
  86. """,
  87. color="""
  88. color : :mod:`matplotlib color <matplotlib.colors>`
  89. Single color specification for when hue mapping is not used. Otherwise, the
  90. plot will try to hook into the matplotlib property cycle.
  91. """,
  92. ax="""
  93. ax : :class:`matplotlib.axes.Axes`
  94. Pre-existing axes for the plot. Otherwise, call :func:`matplotlib.pyplot.gca`
  95. internally.
  96. """, # noqa: E501
  97. )
  98. _core_returns = dict(
  99. ax="""
  100. :class:`matplotlib.axes.Axes`
  101. The matplotlib axes containing the plot.
  102. """,
  103. facetgrid="""
  104. :class:`FacetGrid`
  105. An object managing one or more subplots that correspond to conditional data
  106. subsets with convenient methods for batch-setting of axes attributes.
  107. """,
  108. jointgrid="""
  109. :class:`JointGrid`
  110. An object managing multiple subplots that correspond to joint and marginal axes
  111. for plotting a bivariate relationship or distribution.
  112. """,
  113. pairgrid="""
  114. :class:`PairGrid`
  115. An object managing multiple subplots that correspond to joint and marginal axes
  116. for pairwise combinations of multiple variables in a dataset.
  117. """,
  118. )
  119. _seealso_blurbs = dict(
  120. # Relational plots
  121. scatterplot="""
  122. scatterplot : Plot data using points.
  123. """,
  124. lineplot="""
  125. lineplot : Plot data using lines.
  126. """,
  127. # Distribution plots
  128. displot="""
  129. displot : Figure-level interface to distribution plot functions.
  130. """,
  131. histplot="""
  132. histplot : Plot a histogram of binned counts with optional normalization or smoothing.
  133. """,
  134. kdeplot="""
  135. kdeplot : Plot univariate or bivariate distributions using kernel density estimation.
  136. """,
  137. ecdfplot="""
  138. ecdfplot : Plot empirical cumulative distribution functions.
  139. """,
  140. rugplot="""
  141. rugplot : Plot a tick at each observation value along the x and/or y axes.
  142. """,
  143. # Categorical plots
  144. stripplot="""
  145. stripplot : Plot a categorical scatter with jitter.
  146. """,
  147. swarmplot="""
  148. swarmplot : Plot a categorical scatter with non-overlapping points.
  149. """,
  150. violinplot="""
  151. violinplot : Draw an enhanced boxplot using kernel density estimation.
  152. """,
  153. pointplot="""
  154. pointplot : Plot point estimates and CIs using markers and lines.
  155. """,
  156. # Multiples
  157. jointplot="""
  158. jointplot : Draw a bivariate plot with univariate marginal distributions.
  159. """,
  160. pairplot="""
  161. jointplot : Draw multiple bivariate plots with univariate marginal distributions.
  162. """,
  163. jointgrid="""
  164. JointGrid : Set up a figure with joint and marginal views on bivariate data.
  165. """,
  166. pairgrid="""
  167. PairGrid : Set up a figure with joint and marginal views on multiple variables.
  168. """,
  169. )
  170. _core_docs = dict(
  171. params=DocstringComponents(_core_params),
  172. returns=DocstringComponents(_core_returns),
  173. seealso=DocstringComponents(_seealso_blurbs),
  174. )