Skip to content

Typing pending_xref node attrributes (and maybe all addnodes) #12208

@chrisjsewell

Description

@chrisjsewell

Currently, pending_xref includes no information about what attributes it is expected to have:

sphinx/sphinx/addnodes.py

Lines 477 to 485 in bfce4f5

class pending_xref(nodes.Inline, nodes.Element):
"""Node for cross-references that cannot be resolved without complete
information about all documents.
These nodes are resolved before writing output, in
BuildEnvironment.resolve_references.
"""
child_text_separator = ''

There are definitely some attributes that are expected, i.e. they are accessed with node['name'] and would KeyError except if the attribute is not present, then there are ones that are maybe optional, i.e. they are accessed with node.get('name')

I haven't checked if there are actually any open issue, but there definitely seems like there are discrepancies in the code base, here are some examples:

elif node.get('refdomain', 'std') not in ('', 'std'):
msg = (__('%s:%s reference target not found: %s') %
(node['refdomain'], typ, target))

here the "check" treats refdomain as if it is optional, but then the msg creation treats it as if it is required 😅

for pendingnode in largetree.findall(addnodes.pending_xref):
docname = pendingnode['refdocname']
sectname = pendingnode['refsectname']

here refsectname is treated as required, but if you actually search for refsectname in the code base, it is definitely not set in a lot of places:

sphinx/builders/texinfo.py:
  166:             sectname = pendingnode['refsectname']
sphinx/builders/latex/__init__.py:
  375:             sectname = pendingnode['refsectname']
sphinx/domains/std/__init__.py:
  776:             contnode['refsectname'] = sectname

Am I missing something here? How is some of this stuff not excepting?

@danieleades do you have any thoughts on how to type Node subclasses, to have some kind of enforcing of available attributes.
Ideally it would be enforced for instantiating the node, and for accessing attributes in an existing node, but I know this would be extremely difficult, if not impossible 😏

Also cc @picnixz may have an opinion?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions