From 19d8fe38bd0cdefb62a52041c813f7f0d2cf39a1 Mon Sep 17 00:00:00 2001 From: Jared Dillard Date: Fri, 3 Mar 2023 09:20:32 -0800 Subject: [PATCH] MAINT: Add docstrings and type hints (#61) Taken from the following work by @neflyte: https://github.com/mattermost/docs/pull/5038 Co-authored-by: Alan Lew --- CHANGELOG.rst | 2 + sphinx_sitemap/__init__.py | 88 +++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 242727f..aca4b15 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,8 @@ Changelog * |:bug:| FIX: Fix incremental building by preventing multiprocessing queue from being pickled with environment `#62 `_ +* |:wrench:| MAINT: Add docstrings and type hints + `#61 `_ 2.5.0 ----- diff --git a/sphinx_sitemap/__init__.py b/sphinx_sitemap/__init__.py index ffcab01..1b5960a 100644 --- a/sphinx_sitemap/__init__.py +++ b/sphinx_sitemap/__init__.py @@ -13,9 +13,11 @@ import os import queue -import xml.etree.ElementTree as ET from multiprocessing import Manager +from typing import Any, Dict, List, Optional +from xml.etree import ElementTree +from sphinx.application import Sphinx from sphinx.util.logging import getLogger __version__ = "2.5.0" @@ -23,8 +25,14 @@ logger = getLogger(__name__) -def setup(app): - """Setup connects events to the sitemap builder""" +def setup(app: Sphinx) -> Dict[str, Any]: + """ + Sphinx extension setup function. + It adds config values and connects Sphinx events to the sitemap builder. + + :param app: The Sphinx Application instance + :return: A dict of Sphinx extension options + """ app.add_config_value("site_url", default=None, rebuild="") app.add_config_value( "sitemap_url_scheme", default="{lang}{version}{link}", rebuild="" @@ -49,9 +57,16 @@ def setup(app): } -def get_locales(app, exception): +def get_locales(app: Sphinx) -> List[str]: + """ + Get a list of locales from the extension config or automatically detect based + on Sphinx Application config. + + :param app: The Sphinx Application instance + :return: A list of locales + """ # Manually configured list of locales - sitemap_locales = app.builder.config.sitemap_locales + sitemap_locales: Optional[List[str]] = app.builder.config.sitemap_locales if sitemap_locales: # special value to add nothing -> use primary language only if sitemap_locales == [None]: @@ -71,7 +86,13 @@ def get_locales(app, exception): return locales -def record_builder_type(app): +def record_builder_type(app: Sphinx): + """ + Determine if the Sphinx Builder is an instance of DirectoryHTMLBuilder and store that in the + application environment. + + :param app: The Sphinx Application instance + """ # builder isn't initialized in the setup so we do it here builder = getattr(app, "builder", None) if builder is None: @@ -80,20 +101,29 @@ def record_builder_type(app): builder.env.app.sitemap_links = Manager().Queue() -def hreflang_formatter(lang): +def hreflang_formatter(lang: str) -> str: """ - sitemap hreflang should follow correct format. - Use hyphen instead of underscore in language and country value. - ref: https://en.wikipedia.org/wiki/Hreflang#Common_Mistakes - source: https://github.com/readthedocs/readthedocs.org/pull/5638 + Format the supplied locale code into a string that is compatible with `hreflang`. + See also: + + - https://en.wikipedia.org/wiki/Hreflang#Common_Mistakes + - https://github.com/readthedocs/readthedocs.org/pull/5638 + + :param lang: The locale string to format + :return: The formatted locale string """ if "_" in lang: return lang.replace("_", "-") return lang -def add_html_link(app, pagename, templatename, context, doctree): - """As each page is built, collect page names for the sitemap""" +def add_html_link(app: Sphinx, pagename: str, templatename, context, doctree): + """ + As each page is built, collect page names for the sitemap + + :param app: The Sphinx Application instance + :param pagename: The current page being built + """ env = app.builder.env if app.builder.config.html_file_suffix is None: file_suffix = ".html" @@ -102,7 +132,7 @@ def add_html_link(app, pagename, templatename, context, doctree): # Support DirectoryHTMLBuilder path structure # where generated links between pages omit the index.html - if env.is_directory_builder: + if env.is_directory_builder: # type: ignore if pagename == "index": sitemap_link = "" elif pagename.endswith("/index"): @@ -112,11 +142,15 @@ def add_html_link(app, pagename, templatename, context, doctree): else: sitemap_link = pagename + file_suffix - env.app.sitemap_links.put(sitemap_link) + env.app.sitemap_links.put(sitemap_link) # type: ignore -def create_sitemap(app, exception): - """Generates the sitemap.xml from the collected HTML page links""" +def create_sitemap(app: Sphinx, exception): + """ + Generates the sitemap.xml from the collected HTML page links. + + :param app: The Sphinx Application instance + """ site_url = app.builder.config.site_url or app.builder.config.html_baseurl if site_url: site_url.rstrip("/") + "/" @@ -128,7 +162,7 @@ def create_sitemap(app, exception): ) return - if app.env.app.sitemap_links.empty(): + if app.env.app.sitemap_links.empty(): # type: ignore logger.info( "sphinx-sitemap: No pages generated for %s" % app.config.sitemap_filename, type="sitemap", @@ -136,11 +170,13 @@ def create_sitemap(app, exception): ) return - ET.register_namespace("xhtml", "http://www.w3.org/1999/xhtml") + ElementTree.register_namespace("xhtml", "http://www.w3.org/1999/xhtml") - root = ET.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9") + root = ElementTree.Element( + "urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + ) - locales = get_locales(app, exception) + locales = get_locales(app) if app.builder.config.version: version = app.builder.config.version + "/" @@ -149,24 +185,24 @@ def create_sitemap(app, exception): while True: try: - link = app.env.app.sitemap_links.get_nowait() + link = app.env.app.sitemap_links.get_nowait() # type: ignore except queue.Empty: break - url = ET.SubElement(root, "url") + url = ElementTree.SubElement(root, "url") scheme = app.config.sitemap_url_scheme if app.builder.config.language: lang = app.builder.config.language + "/" else: lang = "" - ET.SubElement(url, "loc").text = site_url + scheme.format( + ElementTree.SubElement(url, "loc").text = site_url + scheme.format( lang=lang, version=version, link=link ) for lang in locales: lang = lang + "/" - ET.SubElement( + ElementTree.SubElement( url, "{http://www.w3.org/1999/xhtml}link", rel="alternate", @@ -175,7 +211,7 @@ def create_sitemap(app, exception): ) filename = app.outdir + "/" + app.config.sitemap_filename - ET.ElementTree(root).write( + ElementTree.ElementTree(root).write( filename, xml_declaration=True, encoding="utf-8", method="xml" )