diff --git a/docs/index.rst b/docs/index.rst index 42c4daa..2933bf0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -69,7 +69,7 @@ module zenoh :undoc-members: module zenoh.handlers -============ +===================== .. automodule:: zenoh.handlers :members: diff --git a/docs/stubs_to_sources.py b/docs/stubs_to_sources.py index 4c3595f..2476f56 100644 --- a/docs/stubs_to_sources.py +++ b/docs/stubs_to_sources.py @@ -22,6 +22,7 @@ referencing a type not declared yet (i.e. forward reference).""" import ast +import inspect from collections import defaultdict from pathlib import Path @@ -29,6 +30,15 @@ __INIT__ = PACKAGE / "__init__.py" +def _unstable(item): + warning = ".. warning:: This API has been marked as unstable: it works as advertised, but it may be changed in a future release." + if item.__doc__: + item.__doc__ += "\n" + warning + else: + item.__doc__ = warning + return item + + class RemoveOverload(ast.NodeTransformer): def __init__(self): self.current_cls = None @@ -95,10 +105,16 @@ def main(): entry.rename(PACKAGE / f"{entry.stem}.py") # read stub code with open(__INIT__) as f: - stub = ast.parse(f.read()) + stub: ast.Module = ast.parse(f.read()) + # replace _unstable + for i, stmt in enumerate(stub.body): + if isinstance(stmt, ast.FunctionDef) and stmt.name == "_unstable": + stub.body[i] = ast.parse(inspect.getsource(_unstable)) + # remove overload + stub = RemoveOverload().visit(stub) # write modified code with open(__INIT__, "w") as f: - f.write(ast.unparse(RemoveOverload().visit(stub))) + f.write(ast.unparse(stub)) if __name__ == "__main__": diff --git a/tests/stubs_check.py b/tests/stubs_check.py index 8cb07c0..2f71c85 100644 --- a/tests/stubs_check.py +++ b/tests/stubs_check.py @@ -34,6 +34,8 @@ def visit_ClassDef(self, node: ast.ClassDef): self.current_cls = None def visit_FunctionDef(self, node: ast.FunctionDef): + if node.name == "_unstable": + return func = getattr(self.current_cls or self.module, node.name) if node.name.startswith("__") or node.name.endswith("serializer"): pass diff --git a/zenoh/__init__.pyi b/zenoh/__init__.pyi index 007fa6d..482d11c 100644 --- a/zenoh/__init__.pyi +++ b/zenoh/__init__.pyi @@ -32,6 +32,9 @@ _RustHandler = ( _PythonCallback = Callable[[_T], Any] _PythonHandler = tuple[_PythonCallback[_T], _H] +def _unstable(item: _T) -> _T: + """marker for unstable functionality""" + @final class ZError(Exception): ... @@ -330,6 +333,7 @@ class KeyExpr: def includes(self, other: _IntoKeyExpr) -> bool: """Returns true if self includes other, i.e. the set defined by self contains every key belonging to the set defined by other.""" + @_unstable def relation_to(self, other: _IntoKeyExpr) -> SetIntersectionLevel: """Returns the relation between self and other from self's point of view (SetIntersectionLevel::Includes signifies that self includes other). Note that this is slower than keyexpr::intersects and keyexpr::includes, so you should favor these methods for most applications. @@ -348,6 +352,7 @@ class KeyExpr: _IntoKeyExpr = KeyExpr | str +@_unstable @final class Liveliness: def declare_token(self, key_expr: _IntoKeyExpr) -> LivelinessToken: @@ -413,6 +418,7 @@ class Liveliness: ) -> Subscriber[None]: """Create a Subscriber for liveliness changes matching the given key expression.""" +@_unstable @final class LivelinessToken: def __enter__(self) -> Self: ... @@ -484,6 +490,7 @@ class Publisher: @property def priority(self) -> Priority: ... @property + @_unstable def reliability(self) -> Reliability: ... def put( self, @@ -573,9 +580,10 @@ class Queryable(Generic[_H]): @overload def __iter__(self) -> Never: ... +@_unstable @final class Querier: - """A querier that allows to send queries to a queryable.. + """A querier that allows to send queries to a queryable. Queriers are automatically undeclared when dropped.""" def __enter__(self) -> Self: ... @@ -642,6 +650,7 @@ class QueryTarget(Enum): DEFAULT = BEST_MATCHING @final +@_unstable class Reliability(Enum): BEST_EFFORT = auto() RELIABLE = auto() @@ -657,6 +666,7 @@ class Reply: @property def err(self) -> ReplyError | None: ... @property + @_unstable def replier_id(self) -> ZenohId | None: ... @final @@ -944,6 +954,7 @@ class Session: ) -> Publisher: """Create a Publisher for the given key expression.""" + @_unstable def declare_querier( self, key_expr: _IntoKeyExpr, @@ -957,6 +968,7 @@ class Session: ) -> Querier: """Create a Querier for the given key expression.""" + @_unstable def liveliness(self) -> Liveliness: """Obtain a Liveliness instance tied to this Zenoh session.""" @@ -971,6 +983,7 @@ class SessionInfo: def peers_zid(self) -> list[ZenohId]: """Return the ZenohId of the zenoh peers this process is currently connected to.""" +@_unstable @final class SetIntersectionLevel(Enum): DISJOINT = auto()