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