Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type annotations directly to clients #208

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions authzed/api/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import asyncio
from typing import Any, Callable
from typing import Any, Callable, Sequence, Optional, Tuple

import grpc
import grpc.aio
from grpc_interceptor import ClientCallDetails, ClientInterceptor
from grpc_interceptor.client import ClientInterceptorReturnType

from authzed.api.v1.core_pb2 import (
AlgebraicSubjectSet,
Expand Down Expand Up @@ -72,17 +73,18 @@ class Client(SchemaServiceStub, PermissionsServiceStub, ExperimentalServiceStub,
v1 Authzed gRPC API client - Auto-detects sync or async depending on if initialized within an event loop
"""

def __init__(self, target, credentials, options=None, compression=None):
def __init__(self, target: str, credentials, options=None, compression=None) -> None:
channel = self.create_channel(target, credentials, options, compression)
self.init_stubs(channel)

def init_stubs(self, channel):
def init_stubs(self, channel) -> None:
SchemaServiceStub.__init__(self, channel)
PermissionsServiceStub.__init__(self, channel)
ExperimentalServiceStub.__init__(self, channel)
WatchServiceStub.__init__(self, channel)

def create_channel(self, target, credentials, options=None, compression=None):
def create_channel(self, target: str, credentials: grpc.ChannelCredentials, options: Optional[Sequence[Tuple[str, Any]]]=None, compression=None) -> (grpc.aio.Channel | grpc.Channel):
channelfn: Callable
try:
asyncio.get_running_loop()
channelfn = grpc.aio.secure_channel
Expand All @@ -97,31 +99,31 @@ class AsyncClient(Client):
v1 Authzed gRPC API client, for use with asyncio.
"""

def __init__(self, target, credentials, options=None, compression=None):
def __init__(self, target: str, credentials, options=None, compression=None) -> None:
channel = grpc.aio.secure_channel(target, credentials, options, compression)
self.init_stubs(channel)


class SyncClient(Client):
"""
v1 Authzed gRPC API client, running synchronously.
"""

def __init__(self, target, credentials, options=None, compression=None):
def __init__(self, target, credentials, options=None, compression=None) -> None:
channel = grpc.secure_channel(target, credentials, options, compression)
self.init_stubs(channel)


class TokenAuthorization(ClientInterceptor):
def __init__(self, token: str):
def __init__(self, token: str) -> None:
self._token = token

def intercept(
self,
method: Callable,
request_or_iterator: Any,
call_details: grpc.ClientCallDetails,
):
) -> ClientInterceptorReturnType:
metadata: list[tuple[str, str | bytes]] = [("authorization", f"Bearer {self._token}")]
if call_details.metadata is not None:
metadata = [*metadata, *call_details.metadata]
Expand Down Expand Up @@ -153,7 +155,7 @@ def __init__(
token: str,
options=None,
compression=None,
):
) -> None:
fake_credentials = grpc.local_channel_credentials()
channel = self.create_channel(target, fake_credentials, options, compression)
auth_interceptor = TokenAuthorization(token)
Expand Down
47 changes: 0 additions & 47 deletions authzed/api/v1/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -69,53 +69,6 @@ from authzed.api.v1.schema_service_pb2_grpc import SchemaServiceAsyncStub, Schem
from authzed.api.v1.watch_service_pb2 import WatchRequest, WatchResponse
from authzed.api.v1.watch_service_pb2_grpc import WatchServiceAsyncStub, WatchServiceStub

class Client(SchemaServiceStub, PermissionsServiceStub, ExperimentalServiceStub, WatchServiceStub):
"""The Client is typed as a synchronous client (though in practice it works with both sync and async code).
If you are using the async code, you should switch to the AsyncClient class instead in order to get proper type hints
"""

def __init__(
self,
target: str,
credentials: grpc.ChannelCredentials,
options: Optional[Sequence[Tuple[str, Any]]] = None,
compression: Optional[grpc.Compression] = None,
) -> None: ...

class SyncClient(
SchemaServiceStub, PermissionsServiceStub, ExperimentalServiceStub, WatchServiceStub
):
def __init__(
self,
target: str,
credentials: grpc.ChannelCredentials,
options: Optional[Sequence[Tuple[str, Any]]] = None,
compression: Optional[grpc.Compression] = None,
) -> None: ...

class AsyncClient(
SchemaServiceAsyncStub,
PermissionsServiceAsyncStub,
ExperimentalServiceAsyncStub,
WatchServiceAsyncStub,
):
def __init__(
self,
target: str,
credentials: grpc.ChannelCredentials,
options: Optional[Sequence[Tuple[str, Any]]] = None,
compression: Optional[grpc.Compression] = None,
) -> None: ...

class InsecureClient(Client):
def __init__(
self,
target: str,
token: str,
options=None,
compression=None,
) -> None: ...

__all__ = [
"Client",
# Core
Expand Down
Loading