Skip to content

Commit

Permalink
More robust paths (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
flying-sheep authored Jul 20, 2023
1 parent 76f168b commit 71501f4
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ jobs:
- name: dependencies
run: |
pip install --upgrade pip wheel
pip install -e .[test,typehints]
pip install .[test,typehints]
- name: tests
run: pytest --color=yes
5 changes: 1 addition & 4 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import sys
from datetime import datetime
from importlib.metadata import metadata
from pathlib import Path
Expand All @@ -8,9 +7,6 @@

HERE = Path(__file__).parent

# necessary for rtd_gh_links’ linkcode support
sys.path.insert(0, HERE.parent / "src")

# Clean build env
for file in HERE.glob("scanpydoc.*.rst"):
file.unlink()
Expand Down Expand Up @@ -49,6 +45,7 @@

# Generate .rst stubs for modules using autosummary
autosummary_generate = True
autosummary_ignore_module_all = False
# Don’t add module paths to documented functions’ names
add_module_names = False

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ source = 'vcs'
version-file = 'src/scanpydoc/_version.py'

[tool.hatch.envs.docs]
python = '3.11'
features = ['doc']
[tool.hatch.envs.docs.scripts]
build = 'sphinx-build -M html docs docs/_build'
Expand Down
6 changes: 3 additions & 3 deletions src/scanpydoc/elegant_typehints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def x() -> Tuple[int, float]:
from .example import example_func


__all__ = ["example_func", "setup"]


HERE = Path(__file__).parent.resolve()

qualname_overrides_default = {
Expand Down Expand Up @@ -88,9 +91,6 @@ def _init_vars(app: Sphinx, config: Config):
config.html_static_path.append(str(HERE / "static"))


example_func.__module__ = "scanpydoc.elegant_typehints" # Make it show up here


@_setup_sig
def setup(app: Sphinx) -> dict[str, Any]:
"""Patches :mod:`sphinx_autodoc_typehints` for a more elegant display."""
Expand Down
33 changes: 17 additions & 16 deletions src/scanpydoc/rtd_github_links/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@
.. code:: python
import sys
from pathlib import Path
HERE = Path(__file__).parent
# make sure modules are import from the right place
sys.path.insert(0, HERE.parent / "src")
extensions = [
"scanpydoc",
"sphinx.ext.linkcode",
Expand Down Expand Up @@ -67,6 +60,7 @@

import inspect
import sys
from importlib import import_module
from pathlib import Path, PurePosixPath
from types import ModuleType
from typing import Any
Expand Down Expand Up @@ -108,14 +102,18 @@ def _get_obj_module(qualname: str) -> tuple[Any, ModuleType]:
# retrieve object and find original module name
mod = sys.modules[modname]
obj = None
del modname
for attr_name in attr_path:
try:
thing = getattr(mod if obj is None else obj, attr_name)
except AttributeError:
except AttributeError as e:
if is_dataclass(obj):
thing = next(f for f in fields(obj) if f.name == attr_name)
else:
raise
try:
thing = import_module(f"{mod.__name__}.{attr_name}")
except ImportError:
raise e from None
if isinstance(thing, ModuleType):
mod = thing
else:
Expand All @@ -137,12 +135,15 @@ def _get_linenos(obj):
return start, start + len(lines) - 1


def _module_path(module: ModuleType) -> PurePosixPath:
stem = PurePosixPath(*module.__name__.split("."))
if Path(module.__file__).name == "__init__.py":
return stem / "__init__.py"
else:
return stem.with_suffix(".py")
def _module_path(obj: Any, module: ModuleType) -> PurePosixPath:
"""Relative module path to parent directory of toplevel module."""
try:
file = Path(inspect.getabsfile(obj))
except TypeError:
file = Path(module.__file__)
offset = -1 if file.name == "__init__.py" else 0
parts = module.__name__.split(".")
return PurePosixPath(*file.parts[offset - len(parts) :])


def github_url(qualname: str) -> str:
Expand All @@ -159,7 +160,7 @@ def github_url(qualname: str) -> str:
except Exception:
print(f"Error in github_url({qualname!r}):", file=sys.stderr)
raise
path = rtd_links_prefix / _module_path(module)
path = rtd_links_prefix / _module_path(obj, module)
start, end = _get_linenos(obj)
fragment = f"#L{start}-L{end}" if start and end else ""
return f"{github_base_url}/{path}{fragment}"
Expand Down
32 changes: 23 additions & 9 deletions tests/test_rtd_github_links.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from dataclasses import Field
from importlib import import_module
from pathlib import Path, PurePosixPath

import pytest
Expand All @@ -16,17 +17,30 @@ def _env(monkeypatch: MonkeyPatch) -> None:


@pytest.fixture(params=[".", "src"])
def pfx(monkeypatch: MonkeyPatch, _env, request):
def prefix(monkeypatch: MonkeyPatch, _env, request) -> PurePosixPath:
pfx = PurePosixPath(request.param)
monkeypatch.setattr("scanpydoc.rtd_github_links.rtd_links_prefix", pfx)
return pfx


def test_as_function(pfx):
pth = "x" / pfx / "scanpydoc/rtd_github_links/__init__.py"
assert github_url("scanpydoc.rtd_github_links") == str(pth)
s, e = _get_linenos(github_url)
assert github_url("scanpydoc.rtd_github_links.github_url") == f"{pth}#L{s}-L{e}"
return "x" / pfx / "scanpydoc"


@pytest.mark.parametrize(
("module", "name", "obj_path"),
[
pytest.param(
*("rtd_github_links", "github_url", "rtd_github_links/__init__.py"),
id="basic",
),
pytest.param(
*("elegant_typehints", "example_func", "elegant_typehints/example.py"),
id="reexport",
),
],
)
def test_as_function(prefix, module, name, obj_path):
assert github_url(f"scanpydoc.{module}") == str(prefix / module / "__init__.py")
obj = getattr(import_module(f"scanpydoc.{module}"), name)
s, e = _get_linenos(obj)
assert github_url(f"scanpydoc.{module}.{name}") == f"{prefix}/{obj_path}#L{s}-L{e}"


def test_get_obj_module():
Expand Down

0 comments on commit 71501f4

Please sign in to comment.