wpilibsuite / sphinxext-opengraph

Sphinx extension to generate unique OpenGraph metadata
https://sphinxext-opengraph.readthedocs.io
Other
74 stars 27 forks source link

[Feature Request] `html_logo` and `html_favicon` as URLs #98

Open leycec opened 1 year ago

leycec commented 1 year ago

Thanks so much for the wondrous Sphinx extension, intrepid @wpilibsuite team! Go, robots beating each other up! :robot: :boxing_glove: :robot:

Sadly, sphinxext-opengraph currently raises non-human-readable exceptions when either the standard html_logo or html_favicon Sphinx settings are defined as remote URLs rather than local filenames. When run against our ReadTheDocs-hosted @beartype documentation defining html_logo as a URL, for example, sphinx-build logs this exception traceback:

Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/events.py", line 96, in emit
    results.append(listener.handler(self.app, *args))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinxext/opengraph/__init__.py", line 254, in html_page_context
    context["metatags"] += get_tags(app, context, doctree, app.config)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinxext/opengraph/__init__.py", line 165, in get_tags
    image_path = create_social_card(
                 ^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinxext/opengraph/socialcards.py", line 105, in create_social_card
    plt_objects = render_social_card(
                  ^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinxext/opengraph/socialcards.py", line 140, in render_social_card
    ) = create_social_card_objects(**kwargs_fig)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinxext/opengraph/socialcards.py", line 274, in create_social_card_objects
    img = mpimg.imread(image)
          ^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/matplotlib/image.py", line 1541, in imread
    with img_open(fname) as image:
         ^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/PIL/Image.py", line 3227, in open
    fp = builtins.open(filename, "rb")
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/home/docs/checkouts/readthedocs.org/user_builds/beartype/checkouts/latest/doc/src/https:/raw.githubusercontent.com/beartype/beartype-assets/main/badge/bear-ified.svg'

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

Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/cmd/build.py", line 284, in build_main
    app.build(args.force_all, args.filenames)
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/application.py", line 347, in build
    self.builder.build_update()
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/builders/__init__.py", line 311, in build_update
    self.build(to_build,
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/builders/__init__.py", line 377, in build
    self.write(docnames, list(updated_docnames), method)
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/builders/__init__.py", line 579, in write
    self._write_serial(sorted(docnames))
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/builders/__init__.py", line 589, in _write_serial
    self.write_doc(docname, doctree)
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/builders/html/__init__.py", line 677, in write_doc
    self.handle_page(docname, ctx, event_arg=doctree)
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/builders/html/__init__.py", line 1078, in handle_page
    newtmpl = self.app.emit_firstresult('html-page-context', pagename,
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/application.py", line 475, in emit_firstresult
    return self.events.emit_firstresult(event, *args,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/events.py", line 117, in emit_firstresult
    for result in self.emit(name, *args, allowed_exceptions=allowed_exceptions):
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/beartype/envs/latest/lib/python3.11/site-packages/sphinx/events.py", line 107, in emit
    raise ExtensionError(__("Handler %r for event %r threw an exception") %
sphinx.errors.ExtensionError: Handler <function html_page_context at 0x7f9c0c4dd440> for event 'html-page-context' threw an exception (exception: [Errno 2] No such file or directory: '/home/docs/checkouts/readthedocs.org/user_builds/beartype/checkouts/latest/doc/src/https:/raw.githubusercontent.com/beartype/beartype-assets/main/badge/bear-ified.svg')

Extension error (sphinxext.opengraph):
Handler <function html_page_context at 0x7f9c0c4dd440> for event 'html-page-context' threw an exception (exception: [Errno 2] No such file or directory: '/home/docs/checkouts/readthedocs.org/user_builds/beartype/checkouts/latest/doc/src/https:/raw.githubusercontent.com/beartype/beartype-assets/main/badge/bear-ified.svg')

Clearly, sphinxext-opengraph expects the html_logo and html_favicon settings to be local filenames and concatenates accordingly. Woops.

Fascinatingly, Sphinx only generalized these settings to accept URLs in mid-2021. When Sphinx did so, it also publicized a new sphinx.util.isurl() helper function that might be of assistance here if were actually implemented correctly. Sadly, it's not. Nobody should call that function, because whoever implemented that function clearly just gave up:

# W3C: "Are you a joke to me!?!?"
def isurl(url: str) -> bool:
    """Check *url* is URL or not."""
    if url and '://' in url:
        return True
    else:
        return False

:rofl: