xref: /aosp_15_r20/external/tensorflow/tensorflow/tools/docs/doc_controls.py (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Documentation control decorators."""
16
17from typing import TypeVar
18
19T = TypeVar("T")
20
21
22_DEPRECATED = "_tf_docs_deprecated"
23
24
25def set_deprecated(obj: T) -> T:
26  """Explicitly tag an object as deprecated for the doc generator."""
27  setattr(obj, _DEPRECATED, None)
28  return obj
29
30
31_INHERITABLE_HEADER = "_tf_docs_inheritable_header"
32
33
34def inheritable_header(text):
35
36  def _wrapped(cls):
37    setattr(cls, _INHERITABLE_HEADER, text)
38    return cls
39
40  return _wrapped
41
42
43_DO_NOT_DOC = "_tf_docs_do_not_document"
44
45
46def do_not_generate_docs(obj: T) -> T:
47  """A decorator: Do not generate docs for this object.
48
49  For example the following classes:
50
51  ```
52  class Parent(object):
53    def method1(self):
54      pass
55    def method2(self):
56      pass
57
58  class Child(Parent):
59    def method1(self):
60      pass
61    def method2(self):
62      pass
63  ```
64
65  Produce the following api_docs:
66
67  ```
68  /Parent.md
69    # method1
70    # method2
71  /Child.md
72    # method1
73    # method2
74  ```
75
76  This decorator allows you to skip classes or methods:
77
78  ```
79  @do_not_generate_docs
80  class Parent(object):
81    def method1(self):
82      pass
83    def method2(self):
84      pass
85
86  class Child(Parent):
87    @do_not_generate_docs
88    def method1(self):
89      pass
90    def method2(self):
91      pass
92  ```
93
94  This will only produce the following docs:
95
96  ```
97  /Child.md
98    # method2
99  ```
100
101  Note: This is implemented by adding a hidden attribute on the object, so it
102  cannot be used on objects which do not allow new attributes to be added. So
103  this decorator must go *below* `@property`, `@classmethod`,
104  or `@staticmethod`:
105
106  ```
107  class Example(object):
108    @property
109    @do_not_generate_docs
110    def x(self):
111      return self._x
112  ```
113
114  Args:
115    obj: The object to hide from the generated docs.
116
117  Returns:
118    obj
119  """
120  setattr(obj, _DO_NOT_DOC, None)
121  return obj
122
123
124_DO_NOT_DOC_INHERITABLE = "_tf_docs_do_not_doc_inheritable"
125
126
127def do_not_doc_inheritable(obj: T) -> T:
128  """A decorator: Do not generate docs for this method.
129
130  This version of the decorator is "inherited" by subclasses. No docs will be
131  generated for the decorated method in any subclass. Even if the sub-class
132  overrides the method.
133
134  For example, to ensure that `method1` is **never documented** use this
135  decorator on the base-class:
136
137  ```
138  class Parent(object):
139    @do_not_doc_inheritable
140    def method1(self):
141      pass
142    def method2(self):
143      pass
144
145  class Child(Parent):
146    def method1(self):
147      pass
148    def method2(self):
149      pass
150  ```
151  This will produce the following docs:
152
153  ```
154  /Parent.md
155    # method2
156  /Child.md
157    # method2
158  ```
159
160  When generating docs for a class's arributes, the `__mro__` is searched and
161  the attribute will be skipped if this decorator is detected on the attribute
162  on any class in the `__mro__`.
163
164  Note: This is implemented by adding a hidden attribute on the object, so it
165  cannot be used on objects which do not allow new attributes to be added. So
166  this decorator must go *below* `@property`, `@classmethod`,
167  or `@staticmethod`:
168
169  ```
170  class Example(object):
171    @property
172    @do_not_doc_inheritable
173    def x(self):
174      return self._x
175  ```
176
177  Args:
178    obj: The class-attribute to hide from the generated docs.
179
180  Returns:
181    obj
182  """
183  setattr(obj, _DO_NOT_DOC_INHERITABLE, None)
184  return obj
185
186
187_FOR_SUBCLASS_IMPLEMENTERS = "_tf_docs_tools_for_subclass_implementers"
188
189
190def for_subclass_implementers(obj: T) -> T:
191  """A decorator: Only generate docs for this method in the defining class.
192
193  Also group this method's docs with and `@abstractmethod` in the class's docs.
194
195  No docs will generated for this class attribute in sub-classes.
196
197  The canonical use case for this is `tf.keras.layers.Layer.call`: It's a
198  public method, essential for anyone implementing a subclass, but it should
199  never be called directly.
200
201  Works on method, or other class-attributes.
202
203  When generating docs for a class's arributes, the `__mro__` is searched and
204  the attribute will be skipped if this decorator is detected on the attribute
205  on any **parent** class in the `__mro__`.
206
207  For example:
208
209  ```
210  class Parent(object):
211    @for_subclass_implementers
212    def method1(self):
213      pass
214    def method2(self):
215      pass
216
217  class Child1(Parent):
218    def method1(self):
219      pass
220    def method2(self):
221      pass
222
223  class Child2(Parent):
224    def method1(self):
225      pass
226    def method2(self):
227      pass
228  ```
229
230  This will produce the following docs:
231
232  ```
233  /Parent.md
234    # method1
235    # method2
236  /Child1.md
237    # method2
238  /Child2.md
239    # method2
240  ```
241
242  Note: This is implemented by adding a hidden attribute on the object, so it
243  cannot be used on objects which do not allow new attributes to be added. So
244  this decorator must go *below* `@property`, `@classmethod`,
245  or `@staticmethod`:
246
247  ```
248  class Example(object):
249    @property
250    @for_subclass_implementers
251    def x(self):
252      return self._x
253  ```
254
255  Args:
256    obj: The class-attribute to hide from the generated docs.
257
258  Returns:
259    obj
260  """
261  setattr(obj, _FOR_SUBCLASS_IMPLEMENTERS, None)
262  return obj
263
264
265do_not_doc_in_subclasses = for_subclass_implementers
266
267_DOC_PRIVATE = "_tf_docs_doc_private"
268
269
270def doc_private(obj: T) -> T:
271  """A decorator: Generates docs for private methods/functions.
272
273  For example:
274
275  ```
276  class Try:
277
278    @doc_controls.doc_private
279    def _private(self):
280      ...
281  ```
282
283  As a rule of thumb, private(beginning with `_`) methods/functions are
284  not documented.
285
286  This decorator allows to force document a private method/function.
287
288  Args:
289    obj: The class-attribute to hide from the generated docs.
290
291  Returns:
292    obj
293  """
294
295  setattr(obj, _DOC_PRIVATE, None)
296  return obj
297
298
299_DOC_IN_CURRENT_AND_SUBCLASSES = "_tf_docs_doc_in_current_and_subclasses"
300
301
302def doc_in_current_and_subclasses(obj: T) -> T:
303  """Overrides `do_not_doc_in_subclasses` decorator.
304
305  If this decorator is set on a child class's method whose parent's method
306  contains `do_not_doc_in_subclasses`, then that will be overriden and the
307  child method will get documented. All classes inherting from the child will
308  also document that method.
309
310  For example:
311
312  ```
313  class Parent:
314    @do_not_doc_in_subclasses
315    def method1(self):
316      pass
317    def method2(self):
318      pass
319
320  class Child1(Parent):
321    @doc_in_current_and_subclasses
322    def method1(self):
323      pass
324    def method2(self):
325      pass
326
327  class Child2(Parent):
328    def method1(self):
329      pass
330    def method2(self):
331      pass
332
333  class Child11(Child1):
334    pass
335  ```
336
337  This will produce the following docs:
338
339  ```
340  /Parent.md
341    # method1
342    # method2
343  /Child1.md
344    # method1
345    # method2
346  /Child2.md
347    # method2
348  /Child11.md
349    # method1
350    # method2
351  ```
352
353  Args:
354    obj: The class-attribute to hide from the generated docs.
355
356  Returns:
357    obj
358  """
359
360  setattr(obj, _DOC_IN_CURRENT_AND_SUBCLASSES, None)
361  return obj
362