1818import inspect
1919import os
2020import pathlib
21+ import textwrap
22+ import types
2123import typing
22- from typing import Any , Callable , List , Sequence , Tuple
24+ from typing import Any , Callable , List , Sequence , Tuple , Union
25+
2326
2427from tensorflow_docs .api_generator import doc_controls
2528from tensorflow_docs .api_generator import doc_generator_visitor
@@ -167,7 +170,7 @@ def util_2
167170 return filtered_children
168171
169172
170- def _get_imported_symbols (obj ):
173+ def _get_imported_symbols (obj : Union [ str , types . ModuleType ] ):
171174 """Returns a list of symbol names imported by the given `obj`."""
172175
173176 class ImportNodeVisitor (ast .NodeVisitor ):
@@ -177,15 +180,24 @@ def __init__(self):
177180 self .imported_symbols = []
178181
179182 def _add_imported_symbol (self , node ):
180- self .imported_symbols .extend ([alias .name for alias in node .names ])
183+ for alias in node .names :
184+ name = alias .asname or alias .name
185+ if name == '*' :
186+ continue
187+ if '.' in name :
188+ continue
189+ self .imported_symbols .append (name )
181190
182191 def visit_Import (self , node ): # pylint: disable=invalid-name
183192 self ._add_imported_symbol (node )
184193
185194 def visit_ImportFrom (self , node ): # pylint: disable=invalid-name
186195 self ._add_imported_symbol (node )
187196
188- source = get_source .get_source (obj )
197+ if isinstance (obj , str ):
198+ source = textwrap .dedent (obj )
199+ else :
200+ source = get_source .get_source (obj )
189201 if source is None :
190202 return []
191203
@@ -197,21 +209,57 @@ def visit_ImportFrom(self, node): # pylint: disable=invalid-name
197209
198210def explicit_package_contents_filter (path : Sequence [str ], parent : Any ,
199211 children : Children ) -> Children :
200- """Filter modules to only include explicit contents.
201-
202- This function returns the children explicitly included by this module, meaning
203- that it will exclude:
212+ """Filter submodules, only keep what's explicitly included.
204213
205- * Modules in a package not explicitly imported by the package (submodules
206- are implicitly injected into their parent's namespace).
207- * Modules imported by a module that is not a package.
214+ This filter only affects the visibility of **modules**. Other objects are not
215+ affected.
208216
209217 This filter is useful if you explicitly define your API in the packages of
210- your library, but do not expliticly define that API in the `__all__` variable
211- of each module. The purpose is to make it easier to maintain that API.
218+ your library (the __init__.py files), but do not expliticly define that API
219+ in the `__all__` variable of each module. The purpose is to make it easier to
220+ maintain that API.
221+
222+ **This filter makes it so that modules are only documented where they are
223+ explicitly imported in an __init__.py**
224+
225+ ### Packages
226+
227+ Lots of imports **indirectly** inject modules into package namespaces, this
228+ filter helps you ignore those. Anywhere you `import pkg.sub1` it will inject
229+ `sub1` into the `pkg` namsspace.
230+
231+ When filtering a package it only keeps modules that are **directly**
232+ impotrted in the package. This code, injects `[sub0, sub1, sub2, sub3, sub4,
233+ sub_sub1, *]` into the pkg namespace:
234+
235+ pkg/__init__.py
236+
237+ ```
238+ import sub0
239+ import pkg.sub1
240+ from pkg import sub2
241+ from pkg.sub3 import sub_sub1
242+ from pkg.sub4 import *
243+ ```
244+
245+ But this filter will only keep the modules `[sub0, sub2, sub_sub1]` in the
246+ docs for `pkg`.
247+
248+ ### Regular modules
249+
250+ For regular modules all modules in the namespace are assumed to be
251+ implementation details and/or documented in their source location. For example
252+ in this package:
253+
254+ ```
255+ pkg/
256+ __init__.py
257+ sub1.py
258+ sub2.py
259+ ```
212260
213- Note: This filter does work with wildcard imports, however it is generally not
214- recommended to use wildcard imports.
261+ If you `import sub2` in `__init__.py` `sub2` will documented in `pkg`
262+ But if you `import sub2` in `sub1.py` `sub2` will not be documented in `sub1`
215263
216264 Args:
217265 path: A tuple of names forming the path to the object.
0 commit comments