(
obj: typing.Any, module: types.ModuleType, parts: Parts = ()
)
| 131 | |
| 132 | |
| 133 | def traverse( |
| 134 | obj: typing.Any, module: types.ModuleType, parts: Parts = () |
| 135 | ) -> "typing.Iterable[DocEntry]": |
| 136 | if inspect.ismodule(obj): |
| 137 | parts += (obj.__name__,) |
| 138 | |
| 139 | if any(f(obj) for f in (inspect.ismodule, inspect.isclass, inspect.isbuiltin)): |
| 140 | yield DocEntry(parts, pydoc._getowndoc(obj)) |
| 141 | |
| 142 | for name, attr in inspect.getmembers(obj): |
| 143 | if name in IGNORED_ATTRS: |
| 144 | continue |
| 145 | |
| 146 | if attr == obj: |
| 147 | continue |
| 148 | |
| 149 | if (module is obj) and (not is_child_of(attr, module)): |
| 150 | continue |
| 151 | |
| 152 | # Don't recurse into modules imported by our module. i.e. `ipaddress.py` imports `re` don't traverse `re` |
| 153 | if (not inspect.ismodule(obj)) and inspect.ismodule(attr): |
| 154 | continue |
| 155 | |
| 156 | new_parts = parts + (name,) |
| 157 | |
| 158 | attr_typ = type(attr) |
| 159 | is_type_or_builtin = any(attr_typ is x for x in (type, type(__builtins__))) |
| 160 | |
| 161 | if is_type_or_builtin: |
| 162 | yield from traverse(attr, module, new_parts) |
| 163 | continue |
| 164 | |
| 165 | is_callable = ( |
| 166 | callable(attr) |
| 167 | or not issubclass(attr_typ, type) |
| 168 | or attr_typ.__name__ in ("getset_descriptor", "member_descriptor") |
| 169 | ) |
| 170 | |
| 171 | is_func = any( |
| 172 | f(attr) |
| 173 | for f in (inspect.isfunction, inspect.ismethod, inspect.ismethoddescriptor) |
| 174 | ) |
| 175 | |
| 176 | if is_callable or is_func: |
| 177 | yield DocEntry(new_parts, pydoc._getowndoc(attr)) |
| 178 | |
| 179 | |
| 180 | def find_doc_entries() -> "Iterable[DocEntry]": |
no test coverage detected