sphinx-notfound-page icon indicating copy to clipboard operation
sphinx-notfound-page copied to clipboard

Rendering the 404 page causes AttributeError: 'Sphinx' object has no attribute 'get_target_uri'

Open greyli opened this issue 3 years ago • 5 comments

Hi, I tried to add sphinx-notfound-page (Version 0.6 or master) for Flask (with Pallets Sphinx Themes).

with the following conf:

extensions = [
    # ...
    'notfound.extension',
]
notfound_template = '404.html'
notfound_urls_prefix = None

then the build failed:

Running Sphinx v3.5.4
loading translations [en]... done
making output directory... done
...
generating indices... genindex py-modindex done

Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/builders/html/__init__.py", line 1054, in handle_page
    output = self.templates.render(templatename, ctx)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/readthedocs_ext/readthedocs.py", line 185, in rtd_render
    content = old_render(template, render_context)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/jinja2glue.py", line 192, in render
    return self.environment.get_template(template).render(context)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/jinja2/environment.py", line 1127, in render
    self.environment.handle_exception()
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/jinja2/environment.py", line 814, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/pallets_sphinx_themes/themes/pocoo/404.html", line 3, in top-level template code
    {% set title = _('Page Not Found') %}
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/pallets_sphinx_themes/themes/pocoo/layout.html", line 22, in top-level template code
    {% set version_warning = current_version.banner() if current_version %}
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/jinja2/sandbox.py", line 382, in call
    return __context.call(__obj, *args, **kwargs)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/pallets_sphinx_themes/versions.py", line 156, in banner
    ).format(latest=latest.name, href=latest.href(context))
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/pallets_sphinx_themes/versions.py", line 134, in href
    path = builder.get_target_uri(pagename)
AttributeError: 'Sphinx' object has no attribute 'get_target_uri'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/cmd/build.py", line 280, in build_main
    app.build(args.force_all, filenames)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/application.py", line 352, in build
    self.builder.build_update()
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 298, in build_update
    len(to_build))
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 363, in build
    self.finish()
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/builders/html/__init__.py", line 622, in finish
    self.finish_tasks.add_task(self.gen_pages_from_extensions)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/util/parallel.py", line 49, in add_task
    res = task_func()
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/builders/html/__init__.py", line 646, in gen_pages_from_extensions
    self.handle_page(pagename, context, template)
  File "/home/docs/checkouts/readthedocs.org/user_builds/flaskx/envs/fix-docs-404/lib/python3.7/site-packages/sphinx/builders/html/__init__.py", line 1062, in handle_page
    (pagename, exc)) from exc
sphinx.errors.ThemeError: An error happened in rendering the page 404.
Reason: AttributeError("'Sphinx' object has no attribute 'get_target_uri'")

Theme error:
An error happened in rendering the page 404.
Reason: AttributeError("'Sphinx' object has no attribute 'get_target_uri'")

Full build log: https://readthedocs.org/projects/flaskx/builds/13534094/

The error related to this line in Pallets Sphinx Theme. I'm not quite sure if it's an issue of sphinx-notfound-page since I'm not very familiar with Sphinx, any thoughts will be helpful. Thanks!

Related issue: https://github.com/pallets/pallets-sphinx-themes/issues/34

greyli avatar Apr 18 '21 14:04 greyli

Hi! Thanks for opening this issue.

I took a quick look at this and it seems that for some reason builder variable at the line you linked is a Sphinx sphinx.application.Sphinx instead of a Sphinx HTML builder (e.g. sphinx.builders.html.StandaloneHTMLBuilder).

I don't know too much about how the theme works, but I'd say that this line https://github.com/pallets/pallets-sphinx-themes/blob/master/src/pallets_sphinx_themes/versions.py#L132 is not returning what we are expecting (an Sphinx HTML builder)

We are overriding the pathto function for the context at https://github.com/readthedocs/sphinx-notfound-page/blob/master/notfound/extension.py#L148 so that may be the reason.

Could you explain a little more what pathto.__closure__[0].cell_contents does?

humitos avatar Apr 19 '21 18:04 humitos

@greyli friendly ping :)

humitos avatar Nov 03 '21 16:11 humitos

Could you explain a little more what pathto.closure[0].cell_contents does?

I'm not familiar with the Sphinx theme either...

Hey @davidism, could you explain what this line does?

greyli avatar Nov 08 '21 02:11 greyli

It's been a long time since I looked at this code.

That function is called in the Jinja page template to generate a URL to a different version of the docs. It's a bit hazy, but I recall having to be fairly careful about how I generated the URL to account for different Sphinx configurations.

In order to generate a URL, I need to call the get_target_uri method on the Sphinx builder object, but neither of those are available in the Jinja render context. However, the pathto function, which is defined as an inner function of the buider.handle_page method, is available. Since pathto references self, I can look at the function closure to get that reference to self again, which is the builder object.

It's entirely possible I missed something while writing this code the first time. These Sphinx objects, and the way they're called and interact, is essentially undocumented, so I spent quite a lot of time just stepping through with a debugger and finding things that would generate the values I needed. If there had been a way to get a reference to the builder at a different time, I would hopefully have used that, but one way or another I couldn't find that while writing the code.

davidism avatar Nov 08 '21 03:11 davidism