Search code examples
pythonpython-sphinx

how to add line number in a sphinx warning?


I'm writting an extention to display inline icons (https://github.com/sphinx-contrib/icon) in for sphinx and I realized the warnings I raise are not displaying the line number in the doc, making more difficult to debug:

WARNING: icon "sync" is not part of fontawesome

What I would like to write is:

path/to/file.rst:10: WARNING: icon "sync" is not part of fontawesome

AS I think it's relevant I raise warnings as such:

def visit_icon_node_html(translator: SphinxTranslator, node: icon_node) -> None:
    """Visit the html output."""
    font, glyph = get_glyph(node["icon"])
    translator.body.append(f'<i class="{Fontawesome.html_font[font]} fa-{glyph}">')

    return

def get_glyph(text) -> Tuple[str, str]:
    """Get the glyph from text.

    Args:
        text: The text to transform (e.g. "fas fa-folder")

    Returns:
        (glyph, font): from the provided text. skip the node if one of them does not exist
    """
    # split the icon name to find the name inside
    m = re.match(Fontawesome.regex, text)
    if not m:
        logger.warning(f'invalid icon name: "{text}"')
        raise nodes.SkipNode
    if m.group("font") not in Fontawesome.html_font:
        logger.warning(f'font "{m.group("font")}" is not part of fontawesome')
        raise nodes.SkipNode
    if m.group("glyph") not in Fontawesome.metadata:
        logger.warning(f'icon "{m.group("glyph")}" is not part of fontawesome')
        raise nodes.SkipNode

I assume I need to add a paremeter the get_glyph and pass it to the logger but which one ?


Solution

  • You need to go one step higher. To create a new role or a directive one needs to create a class hinerited from SphinxRole or SphinxDirective. Both these class embed an internal method returning the tuple: (file, lineos): get_source_info. So I update my Icon class:

    class Icon(SphinxRole):
        """The icon sphinxrole interpreter."""
    
        def run(self) -> Tuple[List[nodes.Node], List[str]]:
            """Setup the role in the builder context."""
            return [icon_node(icon=self.text, location=self.get_source_info())], []
    

    And passed this location parameter to my get_glyph method via the node:

    def visit_icon_node_html(translator: SphinxTranslator, node: icon_node) -> None:
        """Visit the html output."""
        font, glyph = get_glyph(node["icon"], node["location"])
        translator.body.append(f'<i class="{Fontawesome.html_font[font]} fa-{glyph}">')
    
        return
    
    def get_glyph(text: str, location: Tuple[str, int]) -> Tuple[str, str]:
        """Get the glyph from text.
    
        Args:
            text: The text to transform (e.g. "fas fa-folder")
            location: The file and lineos of the role
    
        Returns:
            (glyph, font): from the provided text. skip the node if one of them does not exist
        """
        # split the icon name to find the name inside
        m = re.match(Fontawesome.regex, text)
        if not m:
            logger.warning(f'invalid icon name: "{text}"', location=location)
            raise nodes.SkipNode
    

    The method would be the same for a Directive.