|
29 | 29 |
|
30 | 30 | from collections.abc import Callable |
31 | 31 | from functools import reduce |
| 32 | +import sys |
32 | 33 | from typing import TYPE_CHECKING, Any, TypeVar |
33 | 34 |
|
34 | 35 | from google.protobuf.message import Message |
@@ -91,6 +92,27 @@ def mark_grpc_properties(cls: T) -> T: |
91 | 92 | if name not in props_unique: |
92 | 93 | props_unique.append(name) |
93 | 94 | cls._GRPC_PROPERTIES = tuple(props_unique) |
| 95 | + |
| 96 | + # The 'mark_grpc_properties' decorator is also used on intermediate base |
| 97 | + # classes which do not have the '_SUPPORTED_SINCE' attribute. We only want |
| 98 | + # to add the version information to the final class. |
| 99 | + if hasattr(cls, "_SUPPORTED_SINCE"): |
| 100 | + if isinstance(cls.__doc__, str): |
| 101 | + # When adding to the docstring, we need to match the existing |
| 102 | + # indentation of the docstring (except the first line). |
| 103 | + # See PEP 257 'Handling Docstring Indentation'. |
| 104 | + # Alternatively, we could strip the common indentation from the |
| 105 | + # docstring. |
| 106 | + indent = sys.maxsize |
| 107 | + for line in cls.__doc__.splitlines()[1:]: |
| 108 | + stripped = line.lstrip() |
| 109 | + if stripped: # ignore empty lines |
| 110 | + indent = min(indent, len(line) - len(stripped)) |
| 111 | + if indent == sys.maxsize: |
| 112 | + indent = 0 |
| 113 | + cls.__doc__ += ( |
| 114 | + f"\n\n{indent * ' '}*Added in ACP server version {cls._SUPPORTED_SINCE}.*\n" |
| 115 | + ) |
94 | 116 | return cls |
95 | 117 |
|
96 | 118 |
|
|
0 commit comments