def linkcode_resolve(domain, info): """Produce URLs to GitHub sources, for ``sphinx.ext.linkcode``""" if domain != "py": return None if not info["module"]: return None module_name = info["module"] item_name = info["fullname"] module_path = module_name.replace(".", "/") uri = github_uri % module_path # just the file is too broad try: item = importlib.import_module(module_name) except Exception as ex: log.warning( "Ignoring failed import while searching lineno of '%s:%s': %s(%s)", module_name, item_name, type(ex).__name__, ex, ) else: try: ## Descend from module towards the item # for name in item_name.split("."): child = getattr(item, name, None) if not child: break item = child source, lineno = func_sourcelines(item, human=0) end_lineno = lineno + len(source) - 1 uri = f"{uri}#L{lineno}-L{end_lineno}" return uri except TypeError as ex: # don't clutter logs, these are mostly non functions. assert "module, class, method, function," in str(ex), (ex, item_name) except OSError as ex: # don't clutter logs, these are mostly non functions or `__new__` specials. assert "could not find class definition" in str( ex) or "could not get source code" in str(ex), (ex, item_name) except Exception as ex: log.warning( "Ignoring error on while searching lineno of '%s': %s(%s)", item, type(ex).__name__, ex, )
def test_func_sourcelines_builtin(fn): exp = ["<built-in function eval>"] got = base.func_sourcelines(fn, human=1) assert got == (exp, -1)
def test_func_sourcelines_method(fn): exp = "def foo(self):\n pass" got = base.func_sourcelines(fn, human=1) assert "".join(got[0]).strip() == exp assert got[1] > 200