[PATCH 12/57] docs/qapi-domain: add :since: directive option

John Snow posted 57 patches 4 weeks ago
There is a newer version of this series
[PATCH 12/57] docs/qapi-domain: add :since: directive option
Posted by John Snow 4 weeks ago
Add a little special markup for registering "Since:" information. Adding
it as an option instead of generic content lets us hoist the information
into the Signature bar, optionally put it in the index, etc.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapi_domain.py | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
index 6168c23936f..9919dacd4e6 100644
--- a/docs/sphinx/qapi_domain.py
+++ b/docs/sphinx/qapi_domain.py
@@ -4,6 +4,7 @@
 
 from __future__ import annotations
 
+import re
 from typing import (
     TYPE_CHECKING,
     AbstractSet,
@@ -104,6 +105,18 @@ def process_link(
         return title, target
 
 
+def since_validator(param: str) -> str:
+    """
+    Validate the `:since: X.Y` option field.
+    """
+    match = re.match(r"[0-9]+\.[0-9]+", param)
+    if not match:
+        raise ValueError(
+            f":since: requires a version number in X.Y format; not {param!r}"
+        )
+    return param
+
+
 # Alias for the return of handle_signature(), which is used in several places.
 # (In the Python domain, this is Tuple[str, str] instead.)
 Signature = str
@@ -124,6 +137,8 @@ class QAPIObject(ObjectDescription[Signature]):
         {
             # Borrowed from the Python domain:
             "module": directives.unchanged,  # Override contextual module name
+            # These are QAPI originals:
+            "since": since_validator,
         }
     )
 
@@ -135,9 +150,19 @@ def get_signature_prefix(self) -> List[nodes.Node]:
             SpaceNode(" "),
         ]
 
-    def get_signature_suffix(self) -> list[nodes.Node]:
+    def get_signature_suffix(self) -> List[nodes.Node]:
         """Returns a suffix to put after the object name in the signature."""
-        return []
+        ret: List[nodes.Node] = []
+
+        if "since" in self.options:
+            ret += [
+                SpaceNode(" "),
+                addnodes.desc_sig_element(
+                    "", f"(Since: {self.options['since']})"
+                ),
+            ]
+
+        return ret
 
     def handle_signature(self, sig: str, signode: desc_signature) -> Signature:
         """
-- 
2.48.1
Re: [PATCH 12/57] docs/qapi-domain: add :since: directive option
Posted by Markus Armbruster 3 weeks, 5 days ago
John Snow <jsnow@redhat.com> writes:

> Add a little special markup for registering "Since:" information. Adding
> it as an option instead of generic content lets us hoist the information
> into the Signature bar, optionally put it in the index, etc.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  docs/sphinx/qapi_domain.py | 29 +++++++++++++++++++++++++++--
>  1 file changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
> index 6168c23936f..9919dacd4e6 100644
> --- a/docs/sphinx/qapi_domain.py
> +++ b/docs/sphinx/qapi_domain.py
> @@ -4,6 +4,7 @@
>  
>  from __future__ import annotations
>  
> +import re
>  from typing import (
>      TYPE_CHECKING,
>      AbstractSet,
> @@ -104,6 +105,18 @@ def process_link(
>          return title, target
>  
>  
> +def since_validator(param: str) -> str:
> +    """
> +    Validate the `:since: X.Y` option field.
> +    """
> +    match = re.match(r"[0-9]+\.[0-9]+", param)

This accepts arbitrary crap after the version.  Example:
"9.2.50v9.2.0-2253-ge8a0110293" is fine.  Intentional?

> +    if not match:
> +        raise ValueError(
> +            f":since: requires a version number in X.Y format; not {param!r}"
> +        )
> +    return param

Schema validation is the frontend's job.  Ideally, a backend doesn't
report any errors.  The backends generating C don't.  A backend
generating docs has to: all the reST processing happens there, and
therefore reST errors can only be diagnosed there.  Since "no errors"
purity is impossible for this backend, we can be pragmatic about sinning
a bit more.

Still, I think this one should rather go into the doc comment parser.

This is not a demand.  We can always clean it up later.

> +
> +
>  # Alias for the return of handle_signature(), which is used in several places.
>  # (In the Python domain, this is Tuple[str, str] instead.)
>  Signature = str
> @@ -124,6 +137,8 @@ class QAPIObject(ObjectDescription[Signature]):
>          {
>              # Borrowed from the Python domain:
>              "module": directives.unchanged,  # Override contextual module name
> +            # These are QAPI originals:
> +            "since": since_validator,
>          }
>      )
>  
> @@ -135,9 +150,19 @@ def get_signature_prefix(self) -> List[nodes.Node]:
>              SpaceNode(" "),
>          ]
>  
> -    def get_signature_suffix(self) -> list[nodes.Node]:
> +    def get_signature_suffix(self) -> List[nodes.Node]:
>          """Returns a suffix to put after the object name in the signature."""
> -        return []
> +        ret: List[nodes.Node] = []
> +
> +        if "since" in self.options:
> +            ret += [
> +                SpaceNode(" "),
> +                addnodes.desc_sig_element(
> +                    "", f"(Since: {self.options['since']})"
> +                ),
> +            ]
> +
> +        return ret
>  
>      def handle_signature(self, sig: str, signode: desc_signature) -> Signature:
>          """
Re: [PATCH 12/57] docs/qapi-domain: add :since: directive option
Posted by John Snow 3 weeks, 4 days ago
On Fri, Mar 7, 2025 at 1:59 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > Add a little special markup for registering "Since:" information. Adding
> > it as an option instead of generic content lets us hoist the information
> > into the Signature bar, optionally put it in the index, etc.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > ---
> >  docs/sphinx/qapi_domain.py | 29 +++++++++++++++++++++++++++--
> >  1 file changed, 27 insertions(+), 2 deletions(-)
> >
> > diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
> > index 6168c23936f..9919dacd4e6 100644
> > --- a/docs/sphinx/qapi_domain.py
> > +++ b/docs/sphinx/qapi_domain.py
> > @@ -4,6 +4,7 @@
> >
> >  from __future__ import annotations
> >
> > +import re
> >  from typing import (
> >      TYPE_CHECKING,
> >      AbstractSet,
> > @@ -104,6 +105,18 @@ def process_link(
> >          return title, target
> >
> >
> > +def since_validator(param: str) -> str:
> > +    """
> > +    Validate the `:since: X.Y` option field.
> > +    """
> > +    match = re.match(r"[0-9]+\.[0-9]+", param)
>
> This accepts arbitrary crap after the version.  Example:
> "9.2.50v9.2.0-2253-ge8a0110293" is fine.  Intentional?
>

Nope! O:-) I forgot that match doesn't imply ^...$


>
> > +    if not match:
> > +        raise ValueError(
> > +            f":since: requires a version number in X.Y format; not
> {param!r}"
> > +        )
> > +    return param
>
> Schema validation is the frontend's job.  Ideally, a backend doesn't
> report any errors.  The backends generating C don't.  A backend
> generating docs has to: all the reST processing happens there, and
> therefore reST errors can only be diagnosed there.  Since "no errors"
> purity is impossible for this backend, we can be pragmatic about sinning
> a bit more.
>
> Still, I think this one should rather go into the doc comment parser.
>
> This is not a demand.  We can always clean it up later.
>

You *can* technically use this without touching the QAPI parser at all,
nothing stops you. I.e., you *could* write a QMP reference manual by hand
into an .rst if you wanted.

That said, I know we probably won't. I can remove the validator.


>
> > +
> > +
> >  # Alias for the return of handle_signature(), which is used in several
> places.
> >  # (In the Python domain, this is Tuple[str, str] instead.)
> >  Signature = str
> > @@ -124,6 +137,8 @@ class QAPIObject(ObjectDescription[Signature]):
> >          {
> >              # Borrowed from the Python domain:
> >              "module": directives.unchanged,  # Override contextual
> module name
> > +            # These are QAPI originals:
> > +            "since": since_validator,
> >          }
> >      )
> >
> > @@ -135,9 +150,19 @@ def get_signature_prefix(self) -> List[nodes.Node]:
> >              SpaceNode(" "),
> >          ]
> >
> > -    def get_signature_suffix(self) -> list[nodes.Node]:
> > +    def get_signature_suffix(self) -> List[nodes.Node]:
> >          """Returns a suffix to put after the object name in the
> signature."""
> > -        return []
> > +        ret: List[nodes.Node] = []
> > +
> > +        if "since" in self.options:
> > +            ret += [
> > +                SpaceNode(" "),
> > +                addnodes.desc_sig_element(
> > +                    "", f"(Since: {self.options['since']})"
> > +                ),
> > +            ]
> > +
> > +        return ret
> >
> >      def handle_signature(self, sig: str, signode: desc_signature) ->
> Signature:
> >          """
>
>