Skip to content

Defining a type alias referencing a type imported in a TYPE_CHECKING block causes pdoc to exit with a NameError on the imported type #821

@wgmo

Description

@wgmo

Problem Description

Presence of type alias referencing a type which is imported in an if typing.TYPE_CHECKING block causes pdoc to exit with a NameError on the imported type.

Related I think: #695

Consider the code:

from __future__ import annotations

import typing

import numpy

if typing.TYPE_CHECKING:
    from numpy.typing import NDArray

type Array = NDArray[numpy.float64]

This requires python 3.12 or newer for the type alias, and can be happily imported and used.

Running pdoc over this causes a failure because it does not see the NDArray type:

$ PDOC_ALLOW_EXEC=1 uv run --quiet --locked pdoc -d google -o docs --math foo/
Traceback (most recent call last):
  File "/home/me/pdoc_test/.venv/bin/pdoc", line 10, in <module>
    sys.exit(cli())
             ~~~^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/__main__.py", line 198, in cli
    pdoc.pdoc(
    ~~~~~~~~~^
        *opts.modules,
        ^^^^^^^^^^^^^^
        output_directory=opts.output_directory,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/__init__.py", line 529, in pdoc
    out = render.html_module(module, all_modules)
  File "/home/williamg/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/render.py", line 106, in html_module
    return env.get_template("module.html.jinja2").render(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        module=module,
        ^^^^^^^^^^^^^^
    ...<7 lines>...
        mtime=mtime,
        ^^^^^^^^^^^^
    )
    ^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/jinja2/environment.py", line 1295, in render
    self.environment.handle_exception()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/jinja2/environment.py", line 942, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/module.html.jinja2", line 315, in top-level template code
    {%- if loop.nextitem -%}
    ^^^^^^^^^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/frame.html.jinja2", line 36, in top-level template code
    {% block body %}
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/frame.html.jinja2", line 42, in block 'body'
    {% block content %}{% endblock %}
    ^^^^^^^^^^^^^^^^^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/module.html.jinja2", line 101, in block 'content'
    {% block module_contents %}
    ^^^^^^^^^^^^^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/module.html.jinja2", line 104, in block 'module_contents'
    {{ member(m) }}
    ^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/jinja2/runtime.py", line 784, in _invoke
    rv = self._func(*arguments)
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/module.html.jinja2", line 202, in template
    {{ variable(doc) }}
    ^^^^^^^^^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/jinja2/runtime.py", line 784, in _invoke
    rv = self._func(*arguments)
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/module.html.jinja2", line 181, in template
    <span class="name">{{ var.name }}</span>{{ annotation(var) }}{{ default_value(var) }}
    ^^^^^^^^^^^^^^^^^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/jinja2/runtime.py", line 784, in _invoke
    rv = self._func(*arguments)
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/templates/default/module.html.jinja2", line 149, in template
    {%- if var.default_value_str %}
    ^^^^^^^^^^^^^^^^^^^^^
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/jinja2/environment.py", line 490, in getattr
    return getattr(obj, attribute)
  File "/home/williamg/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/functools.py", line 1039, in __get__
    val = self.func(instance)
  File "/home/me/pdoc_test/.venv/lib/python3.13/site-packages/pdoc/doc.py", line 1135, in default_value_str
    formatted = formatannotation(self.default_value.__value__)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/me/pdoc_test/foo/foo.py", line 7, in Array
    type Array = NDArray[numpy.float64]
                 ^^^^^^^
NameError: name 'NDArray' is not defined. Did you mean: 'Array'?

Steps to reproduce the behavior:

  1. write a file foo.py containing the code above
  2. run pdoc on the file

System Information

$ uv run pdoc --version
pdoc: 15.0.4
Python: 3.13.1
Platform: Linux-5.15.167.4-microsoft-standard-WSL2-x86_64-with-glibc2.36

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions