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 hints #64

Closed
wants to merge 7 commits 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
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ clean:
rm -f ./tests/*_grpc.py

proto: clean
python3 -m grpc_tools.protoc -I. --python_out=. --python_grpc_out=. grpclib/health/v1/health.proto
python3 -m grpc_tools.protoc -I. --python_out=. --python_grpc_out=. grpclib/reflection/v1/reflection.proto
python3 -m grpc_tools.protoc -I. --python_out=. --python_grpc_out=. grpclib/reflection/v1alpha/reflection.proto
python3 -m grpc_tools.protoc -Iexample --python_out=example --python_grpc_out=example --grpc_python_out=example example/helloworld/helloworld.proto
python3 -m grpc_tools.protoc -Iexample --python_out=example --python_grpc_out=example example/streaming/helloworld.proto
cd tests; python3 -m grpc_tools.protoc -I. --python_out=. --python_grpc_out=. dummy.proto
python3 -m grpc_tools.protoc -I. --python_out=. --mypy_out=. --python_grpc_out=. grpclib/health/v1/health.proto
python3 -m grpc_tools.protoc -I. --python_out=. --mypy_out=. --python_grpc_out=. grpclib/reflection/v1/reflection.proto
python3 -m grpc_tools.protoc -I. --python_out=. --mypy_out=. --python_grpc_out=. grpclib/reflection/v1alpha/reflection.proto
python3 -m grpc_tools.protoc -Iexample --python_out=example --mypy_out=example --python_grpc_out=example --grpc_python_out=example example/helloworld/helloworld.proto
python3 -m grpc_tools.protoc -Iexample --python_out=example --mypy_out=example --python_grpc_out=example example/streaming/helloworld.proto
cd tests; python3 -m grpc_tools.protoc -I. --python_out=. --mypy_out=. --python_grpc_out=. dummy.proto

release: proto
./scripts/release_check.sh
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Bug fixes and new features are frequently published via release candidates:

.. code-block:: shell

$ pip3 install --upgrade --pre grpclib
$ pip3 install --upgrade --pre grpclib mypy-protobuf

For the code generation you will also need a ``protoc`` compiler, which can be
installed with ``protobuf`` system package:
Expand Down
6 changes: 3 additions & 3 deletions example/_reference/bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from helloworld import helloworld_pb2_grpc


def main(iterations=10, count=1000):
def main(iterations: int = 10, count: int = 1000) -> None:
channel = grpc.insecure_channel('127.0.0.1:50051')
stub = helloworld_pb2_grpc.GreeterStub(channel)

for j in range(iterations):
for _ in range(iterations):
t1 = time.time()
for i in range(count):
for _ in range(count):
stub.SayHello(helloworld_pb2.HelloRequest(name='World'))
t2 = time.time()
secs = (t2 - t1)
Expand Down
2 changes: 1 addition & 1 deletion example/_reference/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from helloworld import helloworld_pb2_grpc


def main():
def main() -> None:
channel = grpc.insecure_channel('127.0.0.1:50051')
stub = helloworld_pb2_grpc.GreeterStub(channel)

Expand Down
8 changes: 6 additions & 2 deletions example/_reference/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@

class Greeter(helloworld_pb2_grpc.GreeterServicer):

def SayHello(self, request, context):
def SayHello(
self,
request: helloworld_pb2.HelloRequest,
context: grpc.ServicerContext,
) -> helloworld_pb2.HelloReply:
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)


def serve(host='127.0.0.1', port=50051):
def serve(host: str = '127.0.0.1', port: int = 50051) -> None:
server = grpc.server(concurrent.futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('{}:{}'.format(host, port))
Expand Down
5 changes: 3 additions & 2 deletions example/helloworld/client.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import asyncio

from grpclib.client import Channel
from grpclib.utils import none_throws

from .helloworld_pb2 import HelloRequest
from .helloworld_grpc import GreeterStub


async def main():
async def main() -> None:
loop = asyncio.get_event_loop()
channel = Channel('127.0.0.1', 50051, loop=loop)
stub = GreeterStub(channel)

response = await stub.SayHello(HelloRequest(name='World'))
response = none_throws(await stub.SayHello(HelloRequest(name='World')))
print(response.message)

channel.close()
Expand Down
6 changes: 4 additions & 2 deletions example/helloworld/helloworld_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@
# source: helloworld/helloworld.proto
# plugin: grpclib.plugin.main
import abc
import typing

import grpclib.const
import grpclib.client
import grpclib.server

import helloworld.helloworld_pb2


class GreeterBase(abc.ABC):

@abc.abstractmethod
async def SayHello(self, stream):
async def SayHello(self, stream: grpclib.server.Stream[helloworld.helloworld_pb2.HelloRequest, helloworld.helloworld_pb2.HelloReply]) -> None:
pass

def __mapping__(self):
def __mapping__(self) -> typing.Dict[str, grpclib.const.Handler]:
return {
'/helloworld.Greeter/SayHello': grpclib.const.Handler(
self.SayHello,
Expand Down
45 changes: 45 additions & 0 deletions example/helloworld/helloworld_pb2.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# @generated by generate_proto_mypy_stubs.py. Do not edit!
import sys
from google.protobuf.message import (
Message as google___protobuf___message___Message,
)

from typing import (
Optional as typing___Optional,
Text as typing___Text,
)

from typing_extensions import (
Literal as typing_extensions___Literal,
)


class HelloRequest(google___protobuf___message___Message):
name = ... # type: typing___Text

def __init__(self,
name : typing___Optional[typing___Text] = None,
) -> None: ...
@classmethod
def FromString(cls, s: bytes) -> HelloRequest: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def ClearField(self, field_name: typing_extensions___Literal[u"name"]) -> None: ...
else:
def ClearField(self, field_name: typing_extensions___Literal[b"name"]) -> None: ...

class HelloReply(google___protobuf___message___Message):
message = ... # type: typing___Text

def __init__(self,
message : typing___Optional[typing___Text] = None,
) -> None: ...
@classmethod
def FromString(cls, s: bytes) -> HelloReply: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def ClearField(self, field_name: typing_extensions___Literal[u"message"]) -> None: ...
else:
def ClearField(self, field_name: typing_extensions___Literal[b"message"]) -> None: ...
11 changes: 6 additions & 5 deletions example/helloworld/server.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import asyncio

from grpclib.utils import graceful_exit
from grpclib.utils import graceful_exit, none_throws
from grpclib.server import Server
from grpclib.server import Stream

from .helloworld_pb2 import HelloReply
from .helloworld_pb2 import HelloReply, HelloRequest
from .helloworld_grpc import GreeterBase


class Greeter(GreeterBase):

async def SayHello(self, stream):
request = await stream.recv_message()
async def SayHello(self, stream: Stream[HelloRequest, HelloReply]) -> None:
request = none_throws(await stream.recv_message())
message = 'Hello, {}!'.format(request.name)
await stream.send_message(HelloReply(message=message))


async def main(*, host='127.0.0.1', port=50051):
async def main(*, host: str = '127.0.0.1', port: int = 50051) -> None:
loop = asyncio.get_running_loop()
server = Server([Greeter()], loop=loop)
with graceful_exit([server], loop=loop):
Expand Down
2 changes: 1 addition & 1 deletion example/reflection/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from helloworld.server import Greeter


async def main(*, host='127.0.0.1', port=50051):
async def main(*, host: str = '127.0.0.1', port: int = 50051) -> None:
loop = asyncio.get_running_loop()

services = [Greeter()]
Expand Down
2 changes: 1 addition & 1 deletion example/streaming/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .helloworld_grpc import GreeterStub


async def main():
async def main() -> None:
channel = Channel(loop=asyncio.get_event_loop())
stub = GreeterStub(channel)

Expand Down
12 changes: 7 additions & 5 deletions example/streaming/helloworld_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,34 @@
# source: streaming/helloworld.proto
# plugin: grpclib.plugin.main
import abc
import typing

import grpclib.const
import grpclib.client
import grpclib.server

import streaming.helloworld_pb2


class GreeterBase(abc.ABC):

@abc.abstractmethod
async def UnaryUnaryGreeting(self, stream):
async def UnaryUnaryGreeting(self, stream: grpclib.server.Stream[streaming.helloworld_pb2.HelloRequest, streaming.helloworld_pb2.HelloReply]) -> None:
pass

@abc.abstractmethod
async def UnaryStreamGreeting(self, stream):
async def UnaryStreamGreeting(self, stream: grpclib.server.Stream[streaming.helloworld_pb2.HelloRequest, streaming.helloworld_pb2.HelloReply]) -> None:
pass

@abc.abstractmethod
async def StreamUnaryGreeting(self, stream):
async def StreamUnaryGreeting(self, stream: grpclib.server.Stream[streaming.helloworld_pb2.HelloRequest, streaming.helloworld_pb2.HelloReply]) -> None:
pass

@abc.abstractmethod
async def StreamStreamGreeting(self, stream):
async def StreamStreamGreeting(self, stream: grpclib.server.Stream[streaming.helloworld_pb2.HelloRequest, streaming.helloworld_pb2.HelloReply]) -> None:
pass

def __mapping__(self):
def __mapping__(self) -> typing.Dict[str, grpclib.const.Handler]:
return {
'/helloworld.Greeter/UnaryUnaryGreeting': grpclib.const.Handler(
self.UnaryUnaryGreeting,
Expand Down
45 changes: 45 additions & 0 deletions example/streaming/helloworld_pb2.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# @generated by generate_proto_mypy_stubs.py. Do not edit!
import sys
from google.protobuf.message import (
Message as google___protobuf___message___Message,
)

from typing import (
Optional as typing___Optional,
Text as typing___Text,
)

from typing_extensions import (
Literal as typing_extensions___Literal,
)


class HelloRequest(google___protobuf___message___Message):
name = ... # type: typing___Text

def __init__(self,
name : typing___Optional[typing___Text] = None,
) -> None: ...
@classmethod
def FromString(cls, s: bytes) -> HelloRequest: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def ClearField(self, field_name: typing_extensions___Literal[u"name"]) -> None: ...
else:
def ClearField(self, field_name: typing_extensions___Literal[b"name"]) -> None: ...

class HelloReply(google___protobuf___message___Message):
message = ... # type: typing___Text

def __init__(self,
message : typing___Optional[typing___Text] = None,
) -> None: ...
@classmethod
def FromString(cls, s: bytes) -> HelloReply: ...
def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ...
if sys.version_info >= (3,):
def ClearField(self, field_name: typing_extensions___Literal[u"message"]) -> None: ...
else:
def ClearField(self, field_name: typing_extensions___Literal[b"message"]) -> None: ...
31 changes: 22 additions & 9 deletions example/streaming/server.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
import asyncio

from grpclib.utils import graceful_exit
from grpclib.utils import graceful_exit, none_throws
from grpclib.server import Server
from grpclib.server import Stream

from .helloworld_pb2 import HelloReply
from .helloworld_pb2 import HelloReply, HelloRequest
from .helloworld_grpc import GreeterBase


class Greeter(GreeterBase):

# UNARY_UNARY - simple RPC
async def UnaryUnaryGreeting(self, stream):
request = await stream.recv_message()
async def UnaryUnaryGreeting(
self,
stream: Stream[HelloRequest, HelloReply],
) -> None:
request = none_throws(await stream.recv_message())
message = 'Hello, {}!'.format(request.name)
await stream.send_message(HelloReply(message=message))

# UNARY_STREAM - response streaming RPC
async def UnaryStreamGreeting(self, stream):
request = await stream.recv_message()
async def UnaryStreamGreeting(
self,
stream: Stream[HelloRequest, HelloReply],
) -> None:
request = none_throws(await stream.recv_message())
await stream.send_message(
HelloReply(message='Hello, {}!'.format(request.name)))
await stream.send_message(
HelloReply(message='Goodbye, {}!'.format(request.name)))

# STREAM_UNARY - request streaming RPC
async def StreamUnaryGreeting(self, stream):
async def StreamUnaryGreeting(
self,
stream: Stream[HelloRequest, HelloReply],
) -> None:
names = []
async for request in stream:
names.append(request.name)
message = 'Hello, {}!'.format(' and '.join(names))
await stream.send_message(HelloReply(message=message))

# STREAM_STREAM - bidirectional streaming RPC
async def StreamStreamGreeting(self, stream):
async def StreamStreamGreeting(
self,
stream: Stream[HelloRequest, HelloReply],
) -> None:
async for request in stream:
message = 'Hello, {}!'.format(request.name)
await stream.send_message(HelloReply(message=message))
Expand All @@ -42,7 +55,7 @@ async def StreamStreamGreeting(self, stream):
await stream.send_message(HelloReply(message=message))


async def main(*, host='127.0.0.1', port=50051):
async def main(*, host: str = '127.0.0.1', port: int = 50051) -> None:
loop = asyncio.get_running_loop()
server = Server([Greeter()], loop=loop)
with graceful_exit([server], loop=loop):
Expand Down
Loading