From f2d0408456e92048b303a91586a9f2e08c29ca30 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 4 Dec 2024 13:48:23 +0100 Subject: [PATCH 1/7] tag unstable functionality --- zenoh/__init__.pyi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/zenoh/__init__.pyi b/zenoh/__init__.pyi index 007fa6dd..6c3bad4b 100644 --- a/zenoh/__init__.pyi +++ b/zenoh/__init__.pyi @@ -32,6 +32,14 @@ _RustHandler = ( _PythonCallback = Callable[[_T], Any] _PythonHandler = tuple[_PythonCallback[_T], _H] +def unstable(original): + _WARNING = "Warning: This API has been marked as unstable: it works as advertised, but it may be changed in a future release." + if original.__doc__: + original.__doc__ += "\n" + _WARNING + else: + original.__doc__ = _WARNING + return original + @final class ZError(Exception): ... @@ -349,6 +357,7 @@ class KeyExpr: _IntoKeyExpr = KeyExpr | str @final +@unstable class Liveliness: def declare_token(self, key_expr: _IntoKeyExpr) -> LivelinessToken: """Create a LivelinessToken for the given key expression.""" @@ -414,6 +423,7 @@ class Liveliness: """Create a Subscriber for liveliness changes matching the given key expression.""" @final +@unstable class LivelinessToken: def __enter__(self) -> Self: ... def __exit__(self, *_args, **_kwargs): ... @@ -484,6 +494,7 @@ class Publisher: @property def priority(self) -> Priority: ... @property + @unstable def reliability(self) -> Reliability: ... def put( self, @@ -574,8 +585,9 @@ class Queryable(Generic[_H]): def __iter__(self) -> Never: ... @final +@unstable 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 +654,7 @@ class QueryTarget(Enum): DEFAULT = BEST_MATCHING @final +@unstable class Reliability(Enum): BEST_EFFORT = auto() RELIABLE = auto() @@ -944,6 +957,7 @@ class Session: ) -> Publisher: """Create a Publisher for the given key expression.""" + @unstable def declare_querier( self, key_expr: _IntoKeyExpr, From 800a60c37fa6b52a471cd973c12687ae8696b0dd Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 4 Dec 2024 16:14:40 +0100 Subject: [PATCH 2/7] fix test --- zenoh/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zenoh/__init__.py b/zenoh/__init__.py index cbccd941..f362136f 100644 --- a/zenoh/__init__.py +++ b/zenoh/__init__.py @@ -17,3 +17,7 @@ from . import ext except ImportError: pass + + +def unstable(original): + return original From 5310bec244df82757265d90cd87cca86a827e2a4 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 4 Dec 2024 20:10:34 +0100 Subject: [PATCH 3/7] add warning admonition --- docs/index.rst | 2 +- zenoh/__init__.pyi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 42c4daa7..2933bf0e 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/zenoh/__init__.pyi b/zenoh/__init__.pyi index 6c3bad4b..5e3a625e 100644 --- a/zenoh/__init__.pyi +++ b/zenoh/__init__.pyi @@ -33,7 +33,7 @@ _PythonCallback = Callable[[_T], Any] _PythonHandler = tuple[_PythonCallback[_T], _H] def unstable(original): - _WARNING = "Warning: This API has been marked as unstable: it works as advertised, but it may be changed in a future release." + _WARNING = ".. warning:: This API has been marked as unstable: it works as advertised, but it may be changed in a future release." if original.__doc__: original.__doc__ += "\n" + _WARNING else: From d642e54d930eb80b5d5e8e73883e96854a021b1a Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 4 Dec 2024 20:28:09 +0100 Subject: [PATCH 4/7] integrate suggested changes from #405 --- docs/stubs_to_sources.py | 20 ++++++++++++++++++-- zenoh/__init__.py | 4 ++-- zenoh/__init__.pyi | 21 ++++++++------------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/docs/stubs_to_sources.py b/docs/stubs_to_sources.py index 4c3595ff..2476f560 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/zenoh/__init__.py b/zenoh/__init__.py index f362136f..e89c0949 100644 --- a/zenoh/__init__.py +++ b/zenoh/__init__.py @@ -19,5 +19,5 @@ pass -def unstable(original): - return original +def _unstable(item): + return item diff --git a/zenoh/__init__.pyi b/zenoh/__init__.pyi index 5e3a625e..e76ecadb 100644 --- a/zenoh/__init__.pyi +++ b/zenoh/__init__.pyi @@ -32,13 +32,8 @@ _RustHandler = ( _PythonCallback = Callable[[_T], Any] _PythonHandler = tuple[_PythonCallback[_T], _H] -def unstable(original): - _WARNING = ".. warning:: This API has been marked as unstable: it works as advertised, but it may be changed in a future release." - if original.__doc__: - original.__doc__ += "\n" + _WARNING - else: - original.__doc__ = _WARNING - return original +def _unstable(item: _T) -> _T: + """marker for unstable functionality""" @final class ZError(Exception): ... @@ -357,7 +352,7 @@ class KeyExpr: _IntoKeyExpr = KeyExpr | str @final -@unstable +@_unstable class Liveliness: def declare_token(self, key_expr: _IntoKeyExpr) -> LivelinessToken: """Create a LivelinessToken for the given key expression.""" @@ -423,7 +418,7 @@ class Liveliness: """Create a Subscriber for liveliness changes matching the given key expression.""" @final -@unstable +@_unstable class LivelinessToken: def __enter__(self) -> Self: ... def __exit__(self, *_args, **_kwargs): ... @@ -494,7 +489,7 @@ class Publisher: @property def priority(self) -> Priority: ... @property - @unstable + @_unstable def reliability(self) -> Reliability: ... def put( self, @@ -585,7 +580,7 @@ class Queryable(Generic[_H]): def __iter__(self) -> Never: ... @final -@unstable +@_unstable class Querier: """A querier that allows to send queries to a queryable. Queriers are automatically undeclared when dropped.""" @@ -654,7 +649,7 @@ class QueryTarget(Enum): DEFAULT = BEST_MATCHING @final -@unstable +@_unstable class Reliability(Enum): BEST_EFFORT = auto() RELIABLE = auto() @@ -957,7 +952,7 @@ class Session: ) -> Publisher: """Create a Publisher for the given key expression.""" - @unstable + @_unstable def declare_querier( self, key_expr: _IntoKeyExpr, From 8dddbac0cfd64408250c8cfa74ba0774a4755bdb Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 4 Dec 2024 20:42:59 +0100 Subject: [PATCH 5/7] tag more unstable items --- zenoh/__init__.pyi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zenoh/__init__.pyi b/zenoh/__init__.pyi index e76ecadb..cd1bc2b5 100644 --- a/zenoh/__init__.pyi +++ b/zenoh/__init__.pyi @@ -333,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. @@ -665,6 +666,7 @@ class Reply: @property def err(self) -> ReplyError | None: ... @property + @_unstable def replier_id(self) -> ZenohId | None: ... @final @@ -966,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.""" @@ -981,6 +984,7 @@ class SessionInfo: """Return the ZenohId of the zenoh peers this process is currently connected to.""" @final +@_unstable class SetIntersectionLevel(Enum): DISJOINT = auto() INTERSECTS = auto() From ff9268515c7736e938d2e50dae3abeb88bf59195 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 4 Dec 2024 20:48:01 +0100 Subject: [PATCH 6/7] put @_unstable before @final --- zenoh/__init__.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zenoh/__init__.pyi b/zenoh/__init__.pyi index cd1bc2b5..482d11c9 100644 --- a/zenoh/__init__.pyi +++ b/zenoh/__init__.pyi @@ -352,8 +352,8 @@ class KeyExpr: _IntoKeyExpr = KeyExpr | str -@final @_unstable +@final class Liveliness: def declare_token(self, key_expr: _IntoKeyExpr) -> LivelinessToken: """Create a LivelinessToken for the given key expression.""" @@ -418,8 +418,8 @@ class Liveliness: ) -> Subscriber[None]: """Create a Subscriber for liveliness changes matching the given key expression.""" -@final @_unstable +@final class LivelinessToken: def __enter__(self) -> Self: ... def __exit__(self, *_args, **_kwargs): ... @@ -580,8 +580,8 @@ class Queryable(Generic[_H]): @overload def __iter__(self) -> Never: ... -@final @_unstable +@final class Querier: """A querier that allows to send queries to a queryable. Queriers are automatically undeclared when dropped.""" @@ -983,8 +983,8 @@ class SessionInfo: def peers_zid(self) -> list[ZenohId]: """Return the ZenohId of the zenoh peers this process is currently connected to.""" -@final @_unstable +@final class SetIntersectionLevel(Enum): DISJOINT = auto() INTERSECTS = auto() From ca5f3e8fa59e9fb9b283969d9155849c4e6aabe2 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 5 Dec 2024 10:34:38 +0100 Subject: [PATCH 7/7] remove @_unstable from __init__.py --- tests/stubs_check.py | 2 ++ zenoh/__init__.py | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/stubs_check.py b/tests/stubs_check.py index 8cb07c0d..2f71c853 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__.py b/zenoh/__init__.py index e89c0949..cbccd941 100644 --- a/zenoh/__init__.py +++ b/zenoh/__init__.py @@ -17,7 +17,3 @@ from . import ext except ImportError: pass - - -def _unstable(item): - return item