pyTooling.Sphinx.DependencyTable

A Sphinx directive rendering a project’s dependencies as a table, from the requirements rather than by hand.

A dependency table states, per package, which version is required, what it is licensed under, and what it drags in. Written by hand it is wrong within a release or two: pyTooling’s own documentation table was missing four of the packages doc/requirements.txt requires, listed one that isn’t required at all, and called Sphinx BSD-3-Clause when it is BSD-2-Clause.

The entrypoints are declared in conf.py and named by the documents, the way sphinx_reports declares its reports:

# doc/conf.py
pyTooling_Dependency_PackageOverrides = "Dependency.PackageOverrides.yaml"
pyTooling_Dependency_Requirements = {
  "package":       {"file":    "../requirements.txt"},
  "documentation": {"file":    "requirements.txt"},
  "yaml":          {"package": "pyTooling[yaml]"}
}
.. dependency-table:: documentation
   :caption: Documentation dependencies

A requirements file is read - with its -r includes followed - while conf.py is being processed, so a path that doesn’t exist ends the build with one clear message instead of an error box in the middle of a page.

The data is fetched live from the package index, once per build and shared between every table of that build: requirements.txt, tests/requirements.txt and doc/requirements.txt overlap heavily, and a package they share is downloaded once. That still costs real time, so every table reports what it spent, measured with a Stopwatch, and the build ends with the total.

Variables

Functions

  • readEntrypoints(): Turn pyTooling_Dependency_Requirements into entrypoints, reading every requirements file it names.

  • prepareEntrypoints(): Call-back for Sphinx’ config-inited event, reading the entrypoints and the license overrides.

  • formatUnresolvedLicenses(): Describe the packages needing a license override, grouped by what the package index published for them.

Classes

  • Entrypoint: One entry of pyTooling_Dependency_Requirements: an identifier and the requirements it stands for.

  • DependencyCollector: The entrypoints a build declared, the package index it queries, and what querying it cost.

  • DependencyTable: The dependency-table directive: an entrypoint’s dependencies, rendered from the requirements.


Variables

pyTooling.Sphinx.DependencyTable.DEFAULT_INDEX_URL

URL of the package index the tables are built from, unless conf.py names another.

'https://pypi.org'
pyTooling.Sphinx.DependencyTable.DEFAULT_API_URL

URL of that index’s JSON API.

'https://pypi.org/pypi/'
pyTooling.Sphinx.DependencyTable.DEFAULT_DEPTH

Levels of sub-dependencies rendered when nothing says otherwise; 0 expands until the tree ends.

0
pyTooling.Sphinx.DependencyTable.DEFAULT_SIMPLIFIED_VERSIONS

Whether a version constraint is reduced to its lower bound when the document doesn’t say.

True
pyTooling.Sphinx.DependencyTable.OPERATOR_SYMBOLS

Comparison operators as a reader writes them. Order matters - the two-character forms have to be tried first.

(('<=', '≤'), ('>=', '≥'), ('!=', '≠'), ('==', '='))
pyTooling.Sphinx.DependencyTable.TABLE_COLUMNS

The table’s columns, as (title, relative width).

(('Package', 3), ('Version', 1), ('License', 2), ('Dependencies', 4))
pyTooling.Sphinx.DependencyTable.ENTRYPOINT_FIELDS

The fields one entrypoint may state in conf.py, exactly one of them.

The singular forms take a string and the plural forms an iterable of strings; they are otherwise the same statement, and a project writes whichever reads better where it stands.

('file', 'files', 'package', 'packages')
pyTooling.Sphinx.DependencyTable.CONFIG_PREFIX

Prefix every configuration value of this extension carries in conf.py.

'pyTooling_Dependency'
pyTooling.Sphinx.DependencyTable.DEFAULT_VERSION_FORMAT

How many parts of a version number a table prints when the document doesn’t say.

<VersionFormat.MajorMinor: 2>
pyTooling.Sphinx.DependencyTable.DEFAULT_DEPENDENCY_FORMAT

What a line of a dependency tree states when the document doesn’t say.

<DependencyFormat.PackageVersionLicense: 4>

Functions

pyTooling.Sphinx.DependencyTable.readEntrypoints(configuration, confDirectory)[source]

Turn pyTooling_Dependency_Requirements into entrypoints, reading every requirements file it names.

A requirements file is read here rather than when a table is built, so a path that doesn’t exist ends the build with one message naming the identifier instead of an error box in the middle of a page - and so two tables naming the same file read it once.

Parameters:
  • configuration (Any) – Value of pyTooling_Dependency_Requirements.

  • confDirectory (Path) – Directory conf.py lives in; relative paths are resolved against it.

Return type:

dict[str, Entrypoint]

Returns:

Every declared entrypoint, by its identifier.

Raises:
  • MissingDependencyError – If the ‘pypi’ extra isn’t installed.

  • SphinxExtensionError – If the configuration is malformed, or a requirements file can’t be read.

pyTooling.Sphinx.DependencyTable.prepareEntrypoints(sphinx, config)[source]

Call-back for Sphinx’ config-inited event, reading the entrypoints and the license overrides.

A build declaring no entrypoint does nothing here - not even import pyTooling.Dependency.Python, so a project using only this extension’s roles doesn’t need the pypi extra.

Parameters:
  • sphinx (Sphinx) – The Sphinx application.

  • config (Config) – The configuration, after conf.py was read.

Raises:

SphinxExtensionError – If the configuration is malformed, or a requirements or license override file can’t be read.

Return type:

None

pyTooling.Sphinx.DependencyTable.formatUnresolvedLicenses(unresolved)[source]

Describe the packages needing a license override, grouped by what the package index published for them.

Grouped rather than listed one per line, because one ambiguous statement usually accounts for most of the list: License :: OSI Approved :: BSD License names three licenses, so every package whose only license information is that classifier lands here for the same reason and is worth reading as one group.

Parameters:

unresolved (Mapping[str, tuple[str, ...]]) – Names of the packages needing an override, mapped to what the index published for them.

Return type:

str

Returns:

The message, as one line naming the count and two lines per reason.


Classes

class pyTooling.Sphinx.DependencyTable.Entrypoint(identifier, files=(), packages=(), requirements=None)[source]

One entry of pyTooling_Dependency_Requirements: an identifier and the requirements it stands for.

A file entrypoint is read while conf.py is being processed and carries its requirements from then on. A package entrypoint can only be resolved by asking the package index, so it carries the package’s name and extra and is resolved the first time a table names it.

Inheritance

Inheritance diagram of Entrypoint

Parameters:
__init__(identifier, files=(), packages=(), requirements=None)[source]

Describe one entrypoint.

Parameters:
  • identifier (str) – Name the documents refer to this entrypoint by.

  • files (tuple[Path, ...]) – Optional, every requirements file read, for a file entrypoint. Default: ().

  • packages (tuple[tuple[str, str | None], ...]) – Optional, the packages and their extras, for a package entrypoint. Default: ().

  • requirements (dict[str, Requirement] | None) – Optional, the requirements, if they are known already. Default: None.

Return type:

None

_identifier: str

Name the documents refer to this entrypoint by.

_files: tuple[Path, ...]

Every requirements file read, references included.

_packages: tuple[tuple[str, str | None], ...]

The packages to read, as name and extra.

_requirements: dict[str, Requirement] | None

The resolved requirements, by canonical package name.

property Identifier: str

Name the documents refer to this entrypoint by.

Returns:

The identifier.

property Files: tuple[Path, ...]

The requirements file and every file it includes.

Returns:

The files this entrypoint was read from; empty for a package entrypoint.

property Packages: tuple[tuple[str, str | None], ...]

The packages this entrypoint reads the requirements of, as (name, extra) pairs.

Returns:

The packages, or an empty tuple for a file entrypoint.

property Requirements: dict[str, Requirement] | None

The requirements this entrypoint stands for.

Returns:

Every required package by its canonical name, or None if they weren’t resolved yet.

CacheRequirements(requirements)[source]

Remember the requirements the package index answered with.

A package entrypoint can only be resolved by asking the index; remembering the answer is what keeps a second table naming the same entrypoint from asking again.

Parameters:

requirements (dict[str, Requirement]) – Every required package, by its canonical name.

Return type:

None

__repr__()[source]

Return a representation naming what this entrypoint reads.

Return type:

str

Returns:

The identifier and its source.

classmethod GetMethodsWithAttributes(predicate: Nullable[TAttributeFilter[TAttr]] = None) → dict[Callable[..., Any], tuple[Attribute, ...]]

Return the class’ methods that carry at least one matching attribute.

Parameters:

predicate (Nullable[TAttributeFilter[TAttr]]) – Optional, an attribute class, an iterable of attribute classes, or None to accept every attribute.

Return type:

dict[Callable[…, Any], tuple[Attribute, …]]

Returns:

Dictionary of methods and the matching attributes attached to them.

Raises:
  • ValueError – If an element of parameter ‘predicate’ is not a sub-class of Attribute.

  • ValueError – If parameter ‘predicate’ is neither an attribute class nor an iterable of those.

__getstate__() → dict[str, Any]

Return the object’s state for pickling, collecting every slot of the class hierarchy.

Return type:

dict[str, Any]

Returns:

Dictionary of slot names and their values.

Raises:

ExtendedTypeError – If a slot was never assigned, so it has no value to serialize.

__setstate__(state: dict[str, Any]) → None

Restore the object’s state from unpickling, requiring exactly the slots of the class hierarchy.

Parameters:

state (dict[str, Any]) – Dictionary of slot names and their values.

Raises:

ExtendedTypeError – If the given state misses a slot or carries an unexpected one.

Return type:

None

class pyTooling.Sphinx.DependencyTable.DependencyCollector(entrypoints, indexURL, apiURL, overrides)[source]

The entrypoints a build declared, the package index it queries, and what querying it cost.

One collector is shared by every table of a build: a package required by two entrypoints is downloaded once, and the time is accumulated so the build can report a total. It exists because the alternative - a table that queries the index for itself - multiplies a documentation build’s runtime by however many tables it has, and requirements.txt, tests/requirements.txt and doc/requirements.txt share most of what they require.

The index is opened the first time a table asks for a package, not when the collector is created: a project may declare its entrypoints and then build a document that shows none of them, and that build should not open an HTTP session.

Inheritance

Inheritance diagram of DependencyCollector

Parameters:
__init__(entrypoints, indexURL, apiURL, overrides)[source]

Collect what a build declared, without opening the package index yet.

Parameters:
  • entrypoints (dict[str, Entrypoint]) – The entrypoints declared in conf.py, by identifier.

  • indexURL (str) – URL of the package index’s website.

  • apiURL (str) – URL of the package index’s JSON API.

  • overrides (LicenseOverrides) – Licenses stated by hand.

Return type:

None

_entrypoints: dict[str, Entrypoint]

The entrypoints declared in conf.py.

_indexURL: str

URL of the package index’s website.

_apiURL: str

URL of the package index’s JSON API.

_overrides: LicenseOverrides

Licenses stated by hand, where the index can’t.

_graph: PythonPackageDependencyGraph | None

Graph the downloaded packages are collected in.

_index: PythonPackageIndex | None

The package index this build queries, once opened.

_projects: dict[str, Project | None]

Projects downloaded so far; None if unknown.

_detailed: set[str]

Releases whose details were downloaded.

_undescribed: set[str]

Releases the index lists but can’t describe.

_unresolved: dict[str, tuple[str, ...]]

Packages whose license the index couldn’t answer for,

_stopwatch: Stopwatch

Runs only while a request to the index is in flight.

property Entrypoints: dict[str, Entrypoint]

The entrypoints declared in conf.py.

Returns:

Every entrypoint by its identifier.

property Index: PythonPackageIndex

The package index this build queries, opened the first time it is asked for.

Returns:

The package index.

property RequestCount: int

Number of requests sent to the package index.

The stopwatch runs for exactly one span per request, so this is its ActiveCount - counting them a second time in a field of our own would be a second answer to one question.

Returns:

Number of requests sent.

property Seconds: float

Time spent waiting for the package index, in seconds.

This is the stopwatch’s Activity - the sum of the intervals it ran - not its duration, because it is paused between requests and everything the build does in between is not time this collector spent.

Returns:

Seconds spent on the index.

property UnresolvedLicenses: dict[str, tuple[str, ...]]

Packages whose license the index couldn’t answer for, and what it published instead.

The published fields are what the override file has to answer for, so they are kept rather than only the package’s name: License :: OSI Approved :: BSD License names three licenses and is never guessed at, and a license field holding a license’s title instead of its SPDX identifier doesn’t parse.

Returns:

Names of the packages needing a license override, mapped to what the index published for them.

Project(packageName)[source]

Return a project, downloading it the first time it is asked for.

A package the index doesn’t know is remembered as unknown, so a table naming it doesn’t ask again for every row that mentions it.

Parameters:

packageName (str) – Name of the package to look up.

Return type:

Project | None

Returns:

The project, or None if the index doesn’t know it.

Raises:

MissingDependencyError – If the ‘pypi’ extra isn’t installed.

Details(release)[source]

Make sure a release knows its own requirements and its license.

A release the index lists but can’t describe - a yanked one, or a version its release endpoint spells differently - is remembered as unusable and answered with None. Handing back the release itself would be worse than useless: its lazily loaded properties would each retry the download and raise.

Parameters:

release (Release) – The release to fill in.

Return type:

Release | None

Returns:

The release with its details, or None if the index can’t describe it.

Raises:

MissingDependencyError – If the ‘pypi’ extra isn’t installed.

classmethod GetMethodsWithAttributes(predicate: Nullable[TAttributeFilter[TAttr]] = None) → dict[Callable[..., Any], tuple[Attribute, ...]]

Return the class’ methods that carry at least one matching attribute.

Parameters:

predicate (Nullable[TAttributeFilter[TAttr]]) – Optional, an attribute class, an iterable of attribute classes, or None to accept every attribute.

Return type:

dict[Callable[…, Any], tuple[Attribute, …]]

Returns:

Dictionary of methods and the matching attributes attached to them.

Raises:
  • ValueError – If an element of parameter ‘predicate’ is not a sub-class of Attribute.

  • ValueError – If parameter ‘predicate’ is neither an attribute class nor an iterable of those.

__getstate__() → dict[str, Any]

Return the object’s state for pickling, collecting every slot of the class hierarchy.

Return type:

dict[str, Any]

Returns:

Dictionary of slot names and their values.

Raises:

ExtendedTypeError – If a slot was never assigned, so it has no value to serialize.

__setstate__(state: dict[str, Any]) → None

Restore the object’s state from unpickling, requiring exactly the slots of the class hierarchy.

Parameters:

state (dict[str, Any]) – Dictionary of slot names and their values.

Raises:

ExtendedTypeError – If the given state misses a slot or carries an unexpected one.

Return type:

None

class pyTooling.Sphinx.DependencyTable.DependencyTable(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]

The dependency-table directive: an entrypoint’s dependencies, rendered from the requirements.

One argument, the identifier of an entrypoint declared in pyTooling_Dependency_Requirements. :depth: says how many levels of sub-dependencies to expand, :simplified-versions: whether a constraint is reduced to its lower bound, and :caption: puts a caption under the table; which package index is queried and which licenses are stated by hand are build-wide and configured in conf.py.

Inheritance

Inheritance diagram of DependencyTable

directiveName: str = 'dependency-table'

Name the directive is invoked by.

configValues: ClassVar[dict[str, tuple[Any, Literal['env'], Any]]] = {'APIURL': ('https://pypi.org/pypi/', 'env', <class 'str'>), 'IndexURL': ('https://pypi.org', 'env', <class 'str'>), 'PackageOverrides': (None, 'env', (<class 'str'>, <class 'pathlib.Path'>)), 'Requirements': ({}, 'env', <class 'dict'>)}

The configuration values this directive adds to conf.py, as name: (default, rebuild, types). Each is registered with CONFIG_PREFIX as prefix, e.g. pyTooling_Dependency_Requirements.

Requirements maps an identifier to what it names - a file, files, a package or packages. The other three are build-wide, because one package index is queried per build and one override file answers for it. All four are "env"-rebuilt: changing any of them changes every table.

_simplify: bool

Whether this table’s version constraints are reduced to their lower bound.

_versionFormat: VersionFormat

How many parts of a version number this table prints.

_dependencyFormat: DependencyFormat

What a line of this table’s dependency trees states.

has_content = False

A boolean; True if content is allowed.

required_arguments = 1

Number of required directive arguments: the entrypoint’s identifier.

optional_arguments = 0

Number of optional arguments after the required ones.

final_argument_whitespace = False

A boolean; True if the last argument may contain spaces.

option_spec: dict[str, Any] = {'caption': <function strip>, 'dependency-format': <function stripAndNormalize>, 'depth': <function nonnegative_int>, 'simplified-versions': <function stripAndNormalize>, 'version-format': <function stripAndNormalize>}

Mapping of option names to validator functions.

run()[source]

Resolve the named entrypoint against the package index and return its requirements as a table.

Return type:

list[Node]

Returns:

A table node, or an error node when the entrypoint couldn’t be resolved.

_ParseFormatOption(optionName, enumType, default)[source]

Read an option naming a member of an enumeration, or fall back to its default.

_ParseEnumOption requires the option and lower-cases what it reads; these two have a default and are written the way the members are spelled, so a document says :version-format: MajorMinor rather than major_minor.

Parameters:
  • optionName (str) – Name of the option to read.

  • enumType (type[TypeVar(_FormatType, VersionFormat, DependencyFormat)]) – The enumeration its value names a member of.

  • default (TypeVar(_FormatType, VersionFormat, DependencyFormat)) – The member to use when the option isn’t given.

Return type:

TypeVar(_FormatType, VersionFormat, DependencyFormat)

Returns:

The named member.

Raises:

SphinxExtensionError – If the value names no member.

_Collector()[source]

Return the build’s collector, which prepareEntrypoints() created when conf.py was read.

The collector belongs to the running application rather than to the directive, because a document with three tables would otherwise open three indexes and download the same packages three times. It deliberately does not live on the build environment: Sphinx pickles that between runs, and neither an open HTTP session nor a cached view of a package index survives being pickled - or should.

Return type:

DependencyCollector

Returns:

The collector shared by every table of this build.

Raises:

SphinxExtensionError – If no entrypoint was configured.

_Resolve(identifier, collector)[source]

Return what the named entrypoint requires.

A file entrypoint was read when conf.py was processed and answers immediately; a package entrypoint is resolved against the package index the first time a table names it, and remembers the answer.

Parameters:
  • identifier (str) – Identifier the document names.

  • collector (DependencyCollector) – The build’s collector.

Return type:

dict[str, Requirement]

Returns:

Every required package, by its canonical name.

Raises:
  • MissingDependencyError – If the ‘pypi’ extra isn’t installed.

  • SphinxExtensionError – If the identifier is unknown, or the package index can’t answer for the entrypoint’s package.

_PublishedRequirements(packageName, extra, collector)[source]

Ask the package index what a package’s latest release requires.

Parameters:
  • packageName (str) – Name of the package to ask about.

  • extra (str | None) – Extra whose requirements are wanted, or None for the package’s own.

  • collector (DependencyCollector) – The build’s collector.

Return type:

list[Requirement]

Returns:

What that release requires.

Raises:

SphinxExtensionError – If the index doesn’t know the package, can’t describe its latest release, or the package has no such extra.

_CreateTable(identifier, requirements, collector)[source]

Render the requirements as a four-column table.

Parameters:
  • identifier (str) – Identifier of the entrypoint, used as the table’s identifier.

  • requirements (dict[str, Requirement]) – Every required package, by its canonical name.

  • collector (DependencyCollector) – The build’s collector.

Return type:

table

Returns:

The finished table.

static _CreateEmptyRow(columnCount)[source]

Render the one row a table with no requirements gets: a single cell spanning every column.

A table showing nothing but its header reads as a defect. pyTooling’s own requirements.txt is empty - the package has no mandatory dependencies - and that is a statement worth printing.

Parameters:

columnCount (int) – Number of columns the cell has to span.

Return type:

row

Returns:

The table row.

_CreateDoubleRowTableHeader(columns, identifier, classes)

Create a table whose header spans two rows, so a column can group sub-columns.

A column’s subColumns is None when it spans both header rows, and otherwise holds the (title, width) pairs below it.

Parameters:
Return type:

tgroup

Returns:

The table’s column group, with both header rows already in it.

_CreateRotatedTableHeader(columns, identifier, classes)

Create a table whose header titles are rotated, for many narrow columns.

Parameters:
  • columns (list[tuple[str, list[str] | None]]) – One (title, classes) pair per column; the classes are put on the header cell.

  • identifier (str) – Identifier of the table.

  • classes (list[str]) – CSS classes to put on the table.

Return type:

tgroup

Returns:

The table’s column group, with the header row already in it.

_CreateRow(requirement, collector, depth)[source]

Render one required package as a table row.

A package the index doesn’t know, or one with no release matching the requirement, still gets a row - the specifier the entrypoint states is worth showing even when nothing else could be resolved.

Parameters:
  • requirement (Requirement) – The requirement to render.

  • collector (DependencyCollector) – The build’s collector.

  • depth (int | None) – Levels of sub-dependencies still to expand.

Return type:

row

Returns:

The table row.

_CreateSingleRowTableHeader(columns, identifier, classes)

Create a table with a single header row.

Parameters:
  • columns (list[tuple[str, int | None]]) – One (title, width) pair per column; a width of None leaves it to the writer.

  • identifier (str) – Identifier of the table.

  • classes (list[str]) – CSS classes to put on the table.

Return type:

tgroup

Returns:

The table’s column group, with the header row already in it.

_ParseBooleanOption(optionName, default=None)

Read an option written as yes/true or no/false.

Parameters:
  • optionName (str) – Name of the option to read.

  • default (bool | None) – Optional, the value to return when the option wasn’t given.

Return type:

bool

Returns:

The option’s value.

Raises:
  • SphinxExtensionError – If the option wasn’t given and has no default.

  • SphinxExtensionError – If the option’s value is neither of the two accepted spellings.

_ParseEnumOption(optionName, enumType, default=None)

Read an option naming a member of an enumeration.

The written value is lowered and its dashes become underscores, so horizontal-table in a document selects the horizontal_table member - a document reads in the spelling documents use, and the enumeration keeps the spelling Python uses.

Parameters:
  • optionName (str) – Name of the option to read.

  • enumType (type[TypeVar(_EnumType, bound= Enum)]) – The enumeration whose members the value is looked up in.

  • default (TypeVar(_EnumType, bound= Enum) | None) – Optional, the member to return when the option wasn’t given.

Return type:

TypeVar(_EnumType, bound= Enum)

Returns:

The named member of the enumeration.

Raises:
  • SphinxExtensionError – If the option wasn’t given and has no default.

  • SphinxExtensionError – If the value names no member of the enumeration.

_ParseStringOption(optionName, default=None, regexp='\\\\w+')

Read an option that has to match a regular expression.

The pattern defaults to one or more word characters.

Parameters:
  • optionName (str) – Name of the option to read.

  • default (str | None) – Optional, the value to return when the option wasn’t given.

  • regexp (str) – Optional, the pattern the value has to match.

Return type:

str

Returns:

The option’s value.

Raises:
  • SphinxExtensionError – If the option wasn’t given and has no default.

  • SphinxExtensionError – If the option’s value doesn’t match the pattern.

__annotate_func__()

The type of the None singleton.

__init__(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)
Return type:

None

_internalError(container, location, message, exception)

Report an exception a directive couldn’t recover from, in the log and on the page.

A directive that fails silently leaves a hole in the documentation that nobody notices. This puts the message where a reader sees it and the traceback where a maintainer does.

Parameters:
  • container (container) – The container the message is put into.

  • location (str) – Name of the logger, which is what the log line is attributed to.

  • message (str) – What went wrong, in one sentence.

  • exception (Exception) – The exception that was caught.

Return type:

list[Node]

Returns:

The container, as the list a directive’s run returns.

_object_hierarchy_parts(sig_node)

Returns a tuple of strings, one entry for each part of the object’s hierarchy (e.g. ('module', 'submodule', 'Class', 'method')). The returned tuple is used to properly nest children within parents in the table of contents, and can also be used within the _toc_entry_name() method.

This method must not be used outwith table of contents generation.

Return type:

tuple[str, ...]

Parameters:

sig_node (desc_signature)

_toc_entry_name(sig_node)

Returns the text of the table of contents entry for the object.

This function is called once, in run(), to set the name for the table of contents entry (a special attribute _toc_name is set on the object node, later used in environment.collectors.toctree.TocTreeCollector.process_doc().build_toc() when the table of contents entries are collected).

To support table of contents entries for their objects, domains must override this method, also respecting the configuration setting toc_object_entries_show_parents. Domains must also override _object_hierarchy_parts(), with one (string) entry for each part of the object’s hierarchy. The result of this method is set on the signature node, and can be accessed as sig_node['_toc_parts'] for use within this method. The resulting tuple is also used to properly nest children within parents in the table of contents.

An example implementations of this method is within the python domain (PyObject._toc_entry_name()). The python domain sets the _toc_parts attribute within the handle_signature() method.

Return type:

str

Parameters:

sig_node (desc_signature)

add_name(node)

Append self.options[‘name’] to node[‘names’] if it exists.

Also normalize the name string and register it as explicit target.

Return type:

None

add_target_and_index(name, sig, signode)

Add cross-reference IDs and entries to self.indexnode, if applicable.

name is whatever handle_signature() returned.

Return type:

None

Parameters:
  • name (ObjDescT)

  • sig (str)

  • signode (desc_signature)

after_content()

Called after parsing content.

Used to reset information about the current directive context on the build environment.

Return type:

None

assert_has_content()

Throw an ERROR-level DirectiveError if the directive doesn’t have contents.

before_content()

Called before parsing content.

Used to set information about the current directive context on the build environment.

Return type:

None

property config: Config

Reference to the Config object.

Added in version 1.8.

directive_error(level, message)

Return a DirectiveError suitable for being thrown as an exception.

Call “raise self.directive_error(level, message)” from within a directive implementation to return one single system message at level level, which automatically gets the directive block and the line number added.

Preferably use the debug, info, warning, error, or severe wrapper methods, e.g. self.error(message) to generate an ERROR-level directive error.

property env: BuildEnvironment

Reference to the BuildEnvironment object.

Added in version 1.8.

get_location()

Get current location info for logging.

Added in version 4.2.

Return type:

str

get_signatures()

Retrieve the signatures to document from the directive arguments.

By default, signatures are given as arguments, one per line.

Return type:

list[str]

get_source_info()

Get source and line number.

Added in version 3.0.

Return type:

tuple[str | None, int | None]

handle_signature(sig, signode)

Parse the signature sig.

The individual nodes are then appended to signode. If ValueError is raised, parsing is aborted and the whole sig is put into a single desc_name node.

The return value should be a value that identifies the object. It is passed to add_target_and_index() unchanged, and otherwise only used to skip duplicates.

Return type:

TypeVar(ObjDescT)

Parameters:
  • sig (str)

  • signode (desc_signature)

parse_content_to_nodes(allow_section_headings=False)

Parse the directive’s content into nodes.

Parameters:

allow_section_headings (bool) – Are titles (sections) allowed in the directive’s content? Note that this option bypasses Docutils’ usual checks on doctree structure, and misuse of this option can lead to an incoherent doctree. In Docutils, section nodes should only be children of Structural nodes, which includes document, section, and sidebar nodes.

Return type:

list[Node]

Added in version 7.4.

Return type:

list[Node]

Parameters:

allow_section_headings (bool)

parse_inline(text, *, lineno=-1)

Parse text as inline elements.

Parameters:
  • text (str) – The text to parse, which should be a single line or paragraph. This cannot contain any structural elements (headings, transitions, directives, etc).

  • lineno (int) – The line number where the interpreted text begins.

Return type:

tuple[list[Node], list[system_message]]

Returns:

A list of nodes (text and inline elements) and a list of system_messages.

Added in version 7.4.

parse_text_to_nodes(text='', /, *, offset=-1, allow_section_headings=False)

Parse text into nodes.

Parameters:
  • text (str) – Text, in string form. StringList is also accepted.

  • allow_section_headings (bool) – Are titles (sections) allowed in text? Note that this option bypasses Docutils’ usual checks on doctree structure, and misuse of this option can lead to an incoherent doctree. In Docutils, section nodes should only be children of Structural nodes, which includes document, section, and sidebar nodes.

  • offset (int) – The offset of the content.

Return type:

list[Node]

Added in version 7.4.

Return type:

list[Node]

Parameters:
  • text (str)

  • offset (int)

  • allow_section_headings (bool)

set_source_info(node)

Set source and line number to the node.

Added in version 2.1.

Return type:

None

Parameters:

node (Node)

transform_content(content_node)

Can be used to manipulate the content.

Called after creating the content through nested parsing, but before the object-description-transform event is emitted, and before the info-fields are transformed.

Return type:

None

Parameters:

content_node (desc_content)

_SelectRelease(project, requirement, collector)[source]

Return the newest release satisfying a requirement.

Pre-releases are skipped unless the specifier asks for them, because that is what an installer would resolve to and the table describes what would be installed.

Parameters:
  • project (Project | None) – The project to pick a release of, or None if the index doesn’t know it.

  • requirement (Requirement) – The requirement to satisfy.

  • collector (DependencyCollector) – The build’s collector.

Return type:

Release | None

Returns:

The newest matching release, or None if nothing matches.

static _FormatVersion(version, versionFormat)[source]

Shorten a version number to the parts a table prints.

≥0.4.6 says more than a reader of a dependency table needs; the parts that matter are the ones a constraint is usually written against. A version with fewer parts than asked for is left as it is - ≥9 does not become ≥9.0 - because padding would state a precision the requirement didn’t.

Parameters:
  • version (str) – The version, as the constraint writes it.

  • versionFormat (VersionFormat) – How many parts to keep.

Return type:

str

Returns:

The shortened version.

static _FormatSpecifier(specifier, simplify, versionFormat)[source]

Render a version constraint the way a reader writes one.

The comparison operators become their mathematical symbols and the versions are shortened to versionFormat. A simplified constraint keeps only what a package has to be at least: an upper bound and an exclusion say what a release must not be, which is the packaging problem rather than the reader’s, and ~= is written as the lower bound it implies. Simplifying everything away leaves the constraint as it was written - <4.0 alone is still the whole statement.

Parameters:
  • specifier (SpecifierSet) – The constraint to render.

  • simplify (bool) – Whether to reduce the constraint to its lower bound.

  • versionFormat (VersionFormat) – How many parts of each version to keep.

Return type:

str

Returns:

The constraint, or any when nothing is constrained.

static _PackageURL(project)[source]

Return the page a package’s name should link to, most useful first.

A project states none of these reliably, so there are three chances at one: its documentation answers what is this, its repository answers where does it come from, and its page on the package index is what the index itself can always answer. Only a package the index doesn’t know at all goes unlinked.

Parameters:

project (Project | None) – The project, or None if the index doesn’t know it.

Return type:

str | None

Returns:

The URL to link the name to, or None if there is nothing to link to.

classmethod _PackageEntry(requirement, project)[source]

Render the package’s name, linked to where a reader can find out about it.

Parameters:
  • requirement (Requirement) – The requirement naming the package.

  • project (Project | None) – The project, or None if the index doesn’t know it.

Return type:

entry

Returns:

The table entry.

static _LicenseEntry(release)[source]

Render a release’s license, linked to its text where one is known.

The license’ name is shown rather than its SPDX identifier - Apache License 2.0, not Apache-2.0 - because the table is read by a person and the identifier is what an expression writes.

A license that didn’t resolve is an UnknownLicense, never a blank cell, and it is shown as the index published it - in italics, so it reads as a quotation rather than as an identifier. The reader should see that the index said something, and what it was.

Parameters:

release (Release | None) – The release to render the license of, or None.

Return type:

entry

Returns:

The table entry.

static _LicenseName(release)[source]

Return the name(s) of the licenses a release is published under.

Parameters:

release (Release | None) – The release to name the license of, or None.

Return type:

str | None

Returns:

The license’ name, or None if nothing resolved.

static _PublishedLicense(release)[source]

Return what the package index published, for a license that didn’t resolve.

Parameters:

release (Release | None) – The release, or None if the index couldn’t describe it.

Return type:

str

Returns:

What was published, or unknown when that was nothing either.

static _LicenseURL(release)[source]

Return the page a license should link to, most specific first.

The project’s own LICENSE file wins: it is the license as this project publishes it, which is the document a reader auditing a dependency actually wants. Most projects don’t state one, though - it comes from project_urls or from the override file - so a license on the SPDX List falls back to its own published pages, in the order of who is speaking: the licensor’s own page, then OSI’s entry, then SPDX’s. A LicenseRef- has none of those and stays unlinked, because nothing published it.

Parameters:

release (Release | None) – The release to link the license of, or None.

Return type:

str | None

Returns:

The URL to link to, or None if nothing published this license.

_DependenciesEntry(release, collector, depth, visited)[source]

Render a release’s own requirements as a nested bullet list.

Only the unconditional requirements are listed - what an extra pulls in is that extra’s table, not this one. A package already on the path is not expanded again, so a dependency cycle terminates.

Parameters:
  • release (Release | None) – The release to render the dependencies of, or None.

  • collector (DependencyCollector) – The build’s collector.

  • depth (int | None) – Levels still to expand; at zero nothing is expanded.

  • visited (set[str]) – Packages already on this path, lower-cased.

Return type:

entry

Returns:

The table entry.

_CreateBulletList(requirements, collector, depth, visited)[source]

Render requirements as a bullet list, each item expanded by one more level.

Parameters:
  • requirements (list[Requirement]) – The requirements to list.

  • collector (DependencyCollector) – The build’s collector.

  • depth (int | None) – Levels still to expand below this list.

  • visited (set[str]) – Packages already on this path, lower-cased.

Return type:

bullet_list

Returns:

The bullet list.

_RequirementParagraph(requirement, project, release)[source]

Render one line of a dependency tree: the package, what is required of it, and what it is licensed under.

The license is the reason a dependency tree is in this table at all - a package pulls in what its own dependencies are licensed under, and reading that off the tree is the point. It is linked and parenthesised so the line still reads as one requirement.

Parameters:
  • requirement (Requirement) – The requirement to render.

  • project (Project | None) – The project, or None if the index doesn’t know it.

  • release (Release | None) – The release satisfying the requirement, or None if none was found.

Return type:

paragraph

Returns:

The paragraph.