|
| 1 | +.. _stack-documentation-code-with-type-annotations: |
| 2 | + |
| 3 | +################################ |
| 4 | +Documenting code with type hints |
| 5 | +################################ |
| 6 | + |
| 7 | +Many DM packages (especially the middleware suite) use type hints for static analysis, which often duplicates the type information included in docstrings. |
| 8 | +Documentation built with `Documenteer 2.x`_ can often leave this information out, because the `sphinx-autodoc-typehints`_ extension (included automatically) will parse the annotations and include type information in the docs automatically. |
| 9 | + |
| 10 | +.. note:: |
| 11 | + `pipelines.lsst.io`_ is currently still built with Documenteer 1.x, but is expected to transition soon. |
| 12 | + While some :ref:`package doc builds <build-package-docs>` have already been upgraded in anticipation of this transition, their documentation content needs to remain compatible with Documenteer 1.x for now. |
| 13 | + |
| 14 | +Function arguments |
| 15 | +------------------ |
| 16 | + |
| 17 | +To document the parameters to a function or method declared with type hints, |
| 18 | +use regular numpydoc style without the colon or the type information that follows it:: |
| 19 | + |
| 20 | + def run_thing(self, x: int, *args: int, name: str = "", **kwargs: str) -> None: |
| 21 | + """Run the thing. |
| 22 | + |
| 23 | + Parameters |
| 24 | + ---------- |
| 25 | + x |
| 26 | + X coordinate. |
| 27 | + *args |
| 28 | + Some other coordinates. |
| 29 | + name |
| 30 | + The name of the thing. |
| 31 | + **kwargs |
| 32 | + Names of other things. |
| 33 | + """ |
| 34 | + |
| 35 | +Note that ``, optional`` is also unnecessary, as are defaults; default values are automatically pulled from the real function signature. |
| 36 | + |
| 37 | +Function return values |
| 38 | +---------------------- |
| 39 | + |
| 40 | +Return types work automatically when they are not documented at all:: |
| 41 | + |
| 42 | + def return_it() -> str: |
| 43 | + """Return the thing.""" |
| 44 | + return "" |
| 45 | + |
| 46 | +This is a reasonable approach when there is nothing else to document about the returned object. |
| 47 | +When the returned object does merit additional documentation, the type does unfortunately need to be written out (duplicating the annotation), but the returned object should not be named:: |
| 48 | + |
| 49 | + def return_it() -> str: |
| 50 | + """Return the thing. |
| 51 | + |
| 52 | + Returns |
| 53 | + ------- |
| 54 | + str |
| 55 | + The thing. |
| 56 | + """ |
| 57 | + return "" |
| 58 | + |
| 59 | +A simple return type does not need backticks to create a link, but backticks may be needed for more complex types (e.g. generics):: |
| 60 | + |
| 61 | + from collections.abc import Sequence |
| 62 | + |
| 63 | + def return_stuff() -> Sequence[str]: |
| 64 | + """Return some stuff. |
| 65 | + |
| 66 | + Returns |
| 67 | + ------- |
| 68 | + `~collections.abc.Sequence` [`str`] |
| 69 | + The stuff. |
| 70 | + """ |
| 71 | + return [] |
| 72 | + |
| 73 | +.. note:: |
| 74 | + As always, types in docstrings do *not* respect imports in the file, and instead are resolved using the `Sphinx target-resolution rules`_. |
| 75 | + See :ref:`rst-python-link` for details. |
| 76 | + |
| 77 | +Functions that return multiple values via a tuple should have their return types documented just like parameters, i.e. with labels and no types:: |
| 78 | + |
| 79 | + def return_pair() -> tuple[str, int]: |
| 80 | + """Return a pair. |
| 81 | + |
| 82 | + Returns |
| 83 | + ------- |
| 84 | + name |
| 85 | + The name. |
| 86 | + id |
| 87 | + The ID. |
| 88 | + """ |
| 89 | + return ("", 0) |
| 90 | + |
| 91 | +Properties and attributes |
| 92 | +------------------------- |
| 93 | + |
| 94 | +Annotations on properties and attributes are not applied to documentation automatically. |
| 95 | +Their docstrings should continue to include the types parenthetically:: |
| 96 | + |
| 97 | + class Thing: |
| 98 | + """A thing.""" |
| 99 | + |
| 100 | + @property |
| 101 | + def name(self) -> str: |
| 102 | + """Name of the thing (`str`).""" |
| 103 | + return "" |
| 104 | + |
| 105 | + value: int = 0 |
| 106 | + """Value of the thing (`int`).""" |
| 107 | + |
| 108 | +.. note:: |
| 109 | + Attributes without default values (or some sort of ``= RHS``) are not |
| 110 | + included in documentation *at all*, except for those on `~dataclasses.dataclass` types. |
| 111 | + Important instance attributes that cannot have a class-level default value should be made into properties so they can be documented. |
| 112 | + |
| 113 | + |
| 114 | +.. _`Documenteer 2.x`: https://documenteer.lsst.io |
| 115 | +.. _`sphinx-autodoc-typehints`: https://pypi.org/project/sphinx-autodoc-typehints/ |
| 116 | +.. _`pipelines.lsst.io`: https://pipelines.lsst.io |
| 117 | +.. _`Sphinx target-resolution rules`: <https://www.sphinx-doc.org/en/master/usage/domains/python.html#target-resolution>` |
0 commit comments