Skip to content

Commit

Permalink
tag unstable functionality (#404)
Browse files Browse the repository at this point in the history
* tag unstable functionality

* fix test

* add warning admonition

* integrate suggested changes from #405

* tag more unstable items

* put @_unstable before @Final

* remove @_unstable from __init__.py
  • Loading branch information
DenisBiryukov91 authored Dec 5, 2024
1 parent 663bf93 commit 2cfa961
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module zenoh
:undoc-members:

module zenoh.handlers
============
=====================

.. automodule:: zenoh.handlers
:members:
Expand Down
20 changes: 18 additions & 2 deletions docs/stubs_to_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,23 @@
referencing a type not declared yet (i.e. forward reference)."""

import ast
import inspect
from collections import defaultdict
from pathlib import Path

PACKAGE = (Path(__file__) / "../../zenoh").resolve()
__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
Expand Down Expand Up @@ -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__":
Expand Down
2 changes: 2 additions & 0 deletions tests/stubs_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion zenoh/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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): ...

Expand Down Expand Up @@ -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.
Expand All @@ -348,6 +352,7 @@ class KeyExpr:

_IntoKeyExpr = KeyExpr | str

@_unstable
@final
class Liveliness:
def declare_token(self, key_expr: _IntoKeyExpr) -> LivelinessToken:
Expand Down Expand Up @@ -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: ...
Expand Down Expand Up @@ -484,6 +490,7 @@ class Publisher:
@property
def priority(self) -> Priority: ...
@property
@_unstable
def reliability(self) -> Reliability: ...
def put(
self,
Expand Down Expand Up @@ -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: ...
Expand Down Expand Up @@ -642,6 +650,7 @@ class QueryTarget(Enum):
DEFAULT = BEST_MATCHING

@final
@_unstable
class Reliability(Enum):
BEST_EFFORT = auto()
RELIABLE = auto()
Expand All @@ -657,6 +666,7 @@ class Reply:
@property
def err(self) -> ReplyError | None: ...
@property
@_unstable
def replier_id(self) -> ZenohId | None: ...

@final
Expand Down Expand Up @@ -944,6 +954,7 @@ class Session:
) -> Publisher:
"""Create a Publisher for the given key expression."""

@_unstable
def declare_querier(
self,
key_expr: _IntoKeyExpr,
Expand All @@ -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."""

Expand All @@ -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()
Expand Down

0 comments on commit 2cfa961

Please sign in to comment.