Skip to content

Show module docstrings in the explore UI#346

Open
Edim wants to merge 3 commits into
seddonym:mainfrom
Edim:ui-module-descriptions
Open

Show module docstrings in the explore UI#346
Edim wants to merge 3 commits into
seddonym:mainfrom
Edim:ui-module-descriptions

Conversation

@Edim

@Edim Edim commented Mar 6, 2026

Copy link
Copy Markdown

When using import-linter explore, the UI now surfaces module docstrings in two places:

  • Below the breadcrumb bar: the docstring of the current package's __init__.py
    is shown in italic, giving immediate context about the module being explored.
  • Node tooltips: hovering over a graph node shows a tooltip with the child module's
    docstring (if available). For package nodes, the tooltip also shows the name of the
    module you'll navigate to on click.

Docstrings are extracted statically via ast.parse() + ast.get_docstring(), so no
module code is executed during rendering.

Checklist

  • Add tests for the change.
  • Add any appropriate documentation.
  • Run just check.
  • Add a summary of changes to docs/release_notes.md.
  • Add your name to docs/authors.md (in alphabetical order).

@seddonym

Copy link
Copy Markdown
Owner

Hi, thanks for your contribution! It's an interesting idea.

Sorry I haven't got around to reviewing this yet, but I will do over the next few days.

@seddonym seddonym left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your submission!

I like this idea, but I think the visual design needs a bit of work before it's ready to go in.

In particular:

  • Line breaks should be respected.
  • Not so keen on the italics running across the top of the page. Could we try it in the top of the right sidebar, in non-italic text? Maybe it should be collapsible in case the text is long.
  • I think it should possibly be clearer where the text has come from - e.g. an unobtrusive label so people know it's from the module docstring.
  • Non-blocking, but the tooltip hovering doesn't work well for long module docstrings. Maybe we should just display the first line when hovering?

Here's an example with django.templates which might be a good reference point.

Image

Might take a bit of back and forth to get this one right, if you're not up for that, I completely understand!

@Edim

Edim commented Mar 27, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed feedback! I've addressed all the points:

  • Docstring moved to the right sidebar with a collapsible "Module docstring" header, using non-italic text.
  • Long docstrings are truncated with a "Show more" / "Show less" toggle.
  • Line breaks are now respected in the sidebar display.
  • Tooltips show a truncated preview (max 120 chars) instead of the full docstring.
  • The sidebar is scrollable when content overflows.
image

Let me know if you'd like any further adjustments!

@Edim
Edim requested a review from seddonym March 27, 2026 20:23

@seddonym seddonym left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay in reviewing, this is looking pretty good!

Have left some comments, happy to discuss them / hear your ideas.

spec = importlib.util.find_spec(module)
if spec is None or spec.origin is None:
return None
if not spec.origin.endswith("__init__.py"):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for this check?

if not spec.origin.endswith("__init__.py"):
return None
try:
source = Path(spec.origin).read_text(encoding="utf-8")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python files aren't necessarily utf-8 encoded.

In Grimp (the library that Import Linter uses for static analysis) we read files using tokenize.open.

https://github.com/python-grimp/grimp/blob/main/src/grimp/adaptors/filesystem.py#L35

There's a test for handling these kinds of files here. We should probably have similar coverage for this here, do you agree?

tree = ast.parse(source)
return ast.get_docstring(tree)
except Exception:
return None

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we log a warning with the exception message here? Would be helpful for debugging.

def test_returns_child_descriptions(self, client):
response = client.get("/api/graph/testpackage")
data = response.json()
assert "child_descriptions" in data

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we assert on the entire value of child_descriptions? It'll be clearer what we expect there, and we get a better diff if the test fails.

Comment thread docs/release_notes.md

## latest

* Show module docstring below the breadcrumb bar when exploring a package.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is out of date, it's in the sidebar.

Comment thread docs/ui.md

### Module descriptions

When a package has a docstring in its `__init__.py`, a brief description is shown below

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs need updating to reflect the new UI.

Comment thread docs/ui.md

### Module descriptions

When a package has a docstring in its `__init__.py`, a brief description is shown below

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit difficult to read longer module descriptions in the UI.

Image

What do you think about making it possible to resize the sidebar? Not sure how difficult that would be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants