rougail/docs/ext/extinclude.py

96 lines
3.2 KiB
Python
Raw Normal View History

2024-10-14 19:17:44 +02:00
from __future__ import annotations
from docutils import nodes
from sphinx.application import Sphinx
from sphinx.util.docutils import SphinxDirective, SphinxRole
from sphinx.util.typing import ExtensionMetadata
2024-10-14 22:51:05 +02:00
from sphinx.directives.code import LiteralInclude, container_wrapper
2024-10-14 19:17:44 +02:00
2024-10-16 13:24:14 +02:00
import requests
2025-11-22 08:04:51 +01:00
from requests.exceptions import RequestException
from docutils.parsers.rst import directives
2024-10-14 19:28:12 +02:00
2024-10-14 22:51:05 +02:00
class ExtInclude(LiteralInclude):
"""A directive to include code that comes from an url
2024-10-14 19:17:44 +02:00
2024-10-14 22:51:05 +02:00
Sample use::
2024-10-14 19:17:44 +02:00
2024-10-14 22:51:05 +02:00
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_010/firefox/00-proxy.yml
:linenos:
:language: yaml
:caption: this is a interesting code
- parameter required
- linenos, language and caption are optionnal.
:default language: yaml
:default caption: extinclude parameter (url)
"""
2024-10-14 19:17:44 +02:00
def run(self) -> list[nodes.Node]:
2024-10-14 22:51:05 +02:00
url = self.arguments[0]
2025-11-22 08:04:51 +01:00
try:
headers = {
'accept': 'application/text',
'Content-Type': 'application/text',
2024-10-16 13:24:14 +02:00
}
2025-11-22 08:04:51 +01:00
response = requests.get(url, headers=headers)
response.raise_for_status() # This will raise an exception for 4xx/5xx status codes
except requests.exceptions.HTTPError as e:
if response.status_code == 404:
error_msg = f"extinclude: URL not found (404): {url}"
else:
error_msg = f"extinclude: HTTP error {response.status_code}: {url}"
# Create an error node that will be displayed in the documentation
error_node = nodes.error()
para = nodes.paragraph()
para += nodes.Text(error_msg)
error_node += para
self.state.document.reporter.warning(error_msg, line=self.lineno)
return [error_node]
except requests.exceptions.RequestException as e:
error_msg = f"extinclude: Failed to fetch URL {url}: {str(e)}"
# Create an error node that will be displayed in the documentation
error_node = nodes.error()
para = nodes.paragraph()
para += nodes.Text(error_msg)
error_node += para
self.state.document.reporter.warning(error_msg, line=self.lineno)
return [error_node]
2024-10-16 13:24:14 +02:00
code = response.text
2024-10-15 07:31:31 +02:00
2024-10-14 22:51:05 +02:00
literal = nodes.literal_block(code, code)
if 'language' in self.options:
literal['language'] = self.options['language']
else:
literal['language'] = 'yaml'
literal['linenos'] = 'linenos' in self.options
if 'caption' in self.options:
caption = self.options.get('caption')
else:
caption = url
literal['caption'] = caption
2024-10-15 07:31:31 +02:00
if 'name' in self.options:
literal['name'] = self.options.get('name')
2024-10-14 22:51:05 +02:00
literal = container_wrapper(self, literal, caption)
self.add_name(literal)
2024-10-15 07:31:31 +02:00
return [literal]
2024-10-14 19:17:44 +02:00
def setup(app: Sphinx) -> ExtensionMetadata:
2024-10-14 22:51:05 +02:00
app.add_directive('extinclude', ExtInclude)
2024-10-14 19:17:44 +02:00
return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}