Skip to content

Commit

Permalink
feat: Allow empty strings for directive prefixes (#285)
Browse files Browse the repository at this point in the history
docs: Add hint mentioning that pydantic directive prefixes allow empty strings
  • Loading branch information
mansenfranzen authored Apr 26, 2024
1 parent 80cf3e9 commit be21d37
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 30 deletions.
32 changes: 28 additions & 4 deletions docs/source/users/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,13 @@ Contains all modifications for pydantic `BaseModel`.
:directive_option: model-signature-prefix
:values: pydantic model, class, foobar

Define the signature prefix for pydantic models.
Define the signature prefix for pydantic model. This is especially useful
when you want to distinguish pydantic models from other classes.

.. hint::

An empty string is also a valid value. This will remove the prefix
completely.


.. config_description:: autopydantic_model
Expand Down Expand Up @@ -395,7 +401,13 @@ Contains all modifications for pydantic `BaseSettings`.
:directive_option: settings-signature-prefix
:values: pydantic settings, class, foobar

Define the signature prefix for pydantic settings.
Define the signature prefix for pydantic settings. This is especially useful
when you want to distinguish pydantic settings from other classes.

.. hint::

An empty string is also a valid value. This will remove the prefix
completely.


.. config_description:: autopydantic_settings
Expand Down Expand Up @@ -575,7 +587,13 @@ Fields
:enable: members, field-doc-policy=docstring
:values: field, attribute, foobar

Define the signature prefix for pydantic field.
Define the signature prefix for pydantic fields. This is especially useful
when you want to distinguish pydantic fields from other attributes.

.. hint::

An empty string is also a valid value. This will remove the prefix
completely.


----------
Expand Down Expand Up @@ -621,7 +639,13 @@ Validators
:enable: members, model-show-validator-members, undoc-members
:values: validator, classmethod, foobar

Define the signature prefix for pydantic validator.
Define the signature prefix for pydantic validators. This is especially useful
when you want to distinguish pydantic validators from other attributes.

.. hint::

An empty string is also a valid value. This will remove the prefix
completely.


-------
Expand Down
14 changes: 6 additions & 8 deletions sphinxcontrib/autodoc_pydantic/directives/directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class PydanticDirectiveMixin:
"""Base class for pydantic directive providing common functionality."""

config_name: str
default_prefix: str

def __init__(self, *args) -> None: # noqa: ANN002
super().__init__(*args)
Expand All @@ -44,15 +43,18 @@ def get_signature_prefix(self, *_) -> list[Node]: # noqa: ANN002

config_name = f'{self.config_name}-signature-prefix'
prefix = self.pyautodoc.get_value(config_name)
value = prefix or self.default_prefix

# empty prefix should not add any nodes
if prefix == '':
return []

# account for changed signature in sphinx 4.3, see #62
if sphinx.version_info < (4, 3):
return f'{value} ' # type: ignore[return-value]
return f'{prefix} ' # type: ignore[return-value]

from sphinx.addnodes import desc_sig_space

return [Text(value), desc_sig_space()]
return [Text(prefix), desc_sig_space()]


class PydanticModel(PydanticDirectiveMixin, PyClasslike):
Expand All @@ -67,7 +69,6 @@ class PydanticModel(PydanticDirectiveMixin, PyClasslike):
)

config_name = 'model'
default_prefix = 'class'


class PydanticSettings(PydanticDirectiveMixin, PyClasslike):
Expand All @@ -82,7 +83,6 @@ class PydanticSettings(PydanticDirectiveMixin, PyClasslike):
)

config_name = 'settings'
default_prefix = 'class'


class PydanticField(PydanticDirectiveMixin, PyAttribute):
Expand All @@ -102,7 +102,6 @@ class PydanticField(PydanticDirectiveMixin, PyAttribute):
)

config_name = 'field'
default_prefix = 'attribute'

def get_field_name(self, sig: str) -> str:
"""Get field name from signature. Borrows implementation from
Expand Down Expand Up @@ -218,7 +217,6 @@ class PydanticValidator(PydanticDirectiveMixin, PyMethod):
)

config_name = 'validator'
default_prefix = 'classmethod'

def get_field_href_from_mapping(
self, inspector: ModelInspector, mapping: ValidatorFieldMap
Expand Down
3 changes: 1 addition & 2 deletions tests/test_configuration_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,8 +885,7 @@ def test_autodoc_pydantic_field_signature_prefix_directive(parse_rst):

# empty
doctree = parse_rst(input_rst, conf={'autodoc_pydantic_field_signature_prefix': ''})
prefix = desc_annotation_directive_prefix('attribute')
assert_node(doctree[1][0][0], [desc_annotation, prefix])
assert_node(doctree[1][0][0], [desc_addname, 'FieldSignaturePrefix.'])

# custom
input_rst = [
Expand Down
5 changes: 2 additions & 3 deletions tests/test_configuration_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This module contains tests for pydantic model configurations."""

import pytest
from sphinx.addnodes import desc_annotation
from sphinx.addnodes import desc_annotation, desc_addname
from sphinx.testing.util import assert_node

from sphinxcontrib.autodoc_pydantic.directives.autodocumenters import (
Expand Down Expand Up @@ -1271,8 +1271,7 @@ def test_autodoc_pydantic_model_signature_prefix_directive(parse_rst):

# empty
doctree = parse_rst(input_rst, conf={'autodoc_pydantic_model_signature_prefix': ''})
prefix = desc_annotation_directive_prefix('class')
assert_node(doctree[1][0][0], [desc_annotation, prefix])
assert_node(doctree[1][0][0], [desc_addname, 'target.configuration.'])

# custom
input_rst = [
Expand Down
10 changes: 5 additions & 5 deletions tests/test_configuration_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

from typing import List

from sphinx.addnodes import desc_annotation
from sphinx.addnodes import desc_addname, desc_annotation
from sphinx.testing.util import assert_node

from sphinxcontrib.autodoc_pydantic.directives.autodocumenters import (
PydanticSettingsDocumenter,
)

from .compatibility import desc_annotation_directive_prefix

KWARGS = dict(documenter=PydanticSettingsDocumenter.objtype, deactivate_all=True)
Expand Down Expand Up @@ -1004,10 +1005,10 @@ def test_autodoc_pydantic_settings_signature_prefix(autodocument, parse_rst):
actual = autodocument(options_doc={'settings-signature-prefix': ''}, **kwargs)
assert result == actual


def test_autodoc_pydantic_settings_signature_prefix_directive(parse_rst):
"""Tests pydantic_settings directive."""


def test_autodoc_pydantic_settings_signature_prefix_directive(parse_rst):
# default
input_rst = [
'',
Expand All @@ -1026,8 +1027,7 @@ def test_autodoc_pydantic_settings_signature_prefix_directive(parse_rst):
doctree = parse_rst(
input_rst, conf={'autodoc_pydantic_settings_signature_prefix': ''}
)
prefix = desc_annotation_directive_prefix('class')
assert_node(doctree[1][0][0], [desc_annotation, prefix])
assert_node(doctree[1][0][0], [desc_addname, 'target.configuration.'])

# custom
input_rst = [
Expand Down
17 changes: 9 additions & 8 deletions tests/test_configuration_validator.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
"""This module contains tests for pydantic validator configurations."""

from docutils.nodes import (
paragraph,
emphasis,
paragraph,
)
from sphinx.addnodes import (
desc,
desc_signature,
desc_name,
desc_content,
desc_annotation,
desc_addname,
pending_xref,
desc_annotation,
desc_content,
desc_name,
desc_signature,
index,
pending_xref,
)
from sphinx.testing.util import assert_node

from sphinxcontrib.autodoc_pydantic.directives.autodocumenters import (
PydanticValidatorDocumenter,
)

from .compatibility import desc_annotation_directive_prefix

KWARGS = dict(documenter=PydanticValidatorDocumenter.objtype, deactivate_all=True)
Expand Down Expand Up @@ -449,8 +451,7 @@ def test_autodoc_pydantic_validator_signature_prefix_directive(parse_rst):
doctree = parse_rst(
input_rst, conf={'autodoc_pydantic_validator_signature_prefix': ''}
)
prefix = desc_annotation_directive_prefix('classmethod')
assert_node(doctree[1][0][0], [desc_annotation, prefix])
assert_node(doctree[1][0][0], [desc_addname, 'ValidatorSignaturePrefix.'])

# custom
input_rst = [
Expand Down

0 comments on commit be21d37

Please sign in to comment.