diff options
author | mustiikhalil <mustii@mmk.one> | 2021-02-26 01:38:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-25 14:38:12 -0800 |
commit | 8142fedd196e20d24c48485396821b12034e7eb9 (patch) | |
tree | efc31d19a822e6fa11e69d31c3b16ccce4aa6a18 /grpc/examples | |
parent | c0be1cb7a51f1c50e057469de94f3a3bb7dfcb64 (diff) | |
download | flatbuffers-8142fedd196e20d24c48485396821b12034e7eb9.tar.gz flatbuffers-8142fedd196e20d24c48485396821b12034e7eb9.tar.bz2 flatbuffers-8142fedd196e20d24c48485396821b12034e7eb9.zip |
Working on a python example plus fixing python grpc code (#6456)
Refactored python grpc code gen
Adds example server & client + fixes ci
Fixes generated code
Making sure we encode the reply string as utf8
Adds Readme details to clarify issue regarding encoding when python is sending/receiving
Diffstat (limited to 'grpc/examples')
-rw-r--r-- | grpc/examples/README.md | 28 | ||||
-rw-r--r-- | grpc/examples/generate.sh | 19 | ||||
-rw-r--r-- | grpc/examples/python/greeter/README.md | 12 | ||||
-rw-r--r-- | grpc/examples/python/greeter/client.py | 40 | ||||
-rw-r--r-- | grpc/examples/python/greeter/models/HelloReply.py | 45 | ||||
-rw-r--r-- | grpc/examples/python/greeter/models/HelloRequest.py | 45 | ||||
-rw-r--r-- | grpc/examples/python/greeter/models/__init__.py | 0 | ||||
-rw-r--r-- | grpc/examples/python/greeter/models/greeter_grpc_fb.py | 52 | ||||
-rw-r--r-- | grpc/examples/python/greeter/server.py | 57 |
9 files changed, 294 insertions, 4 deletions
diff --git a/grpc/examples/README.md b/grpc/examples/README.md index f5694a84..c821218b 100644 --- a/grpc/examples/README.md +++ b/grpc/examples/README.md @@ -1,5 +1,33 @@ ## Languages known issues +### Python + +- Assert the type required in your server/client since python is able to receive `Bytes array` or `utf8 strings`. + +```python +def SayHello(self, request, context): + # request might be a byte array or a utf8 string + + r = HelloRequest.HelloRequest().GetRootAs(request, 0) + reply = "Unknown" + if r.Name(): + reply = r.Name() + # Issues might happen if type checking isnt present. + # thus encoding it as a `reply.decode('UTF-8')` + return build_reply("welcome " + reply.decode('UTF-8')) + +``` + +This can be prevented by making sure all the requests coming to/from python are `Bytes array` + +```python +def say_hello(stub, builder): + hello_request = bytes(builder.Output()) + reply = stub.SayHello(hello_request) + r = HelloReply.HelloReply.GetRootAs(reply) + print(r.Message()) +``` + ### Go - Always requires the `content-type` of the payload to be set to `application/grpc+flatbuffers` diff --git a/grpc/examples/generate.sh b/grpc/examples/generate.sh index 0ac2818a..b0740d8a 100644 --- a/grpc/examples/generate.sh +++ b/grpc/examples/generate.sh @@ -38,23 +38,34 @@ fi generator="--grpc $current_dir/greeter.fbs" # Regenerate Go lang code -cd go/ +cd go cd greeter fbc --go ${generator} cd ${current_dir} -cd swift/ +# Regenerate Python code +cd python + +cd greeter + +fbc --python ${generator} + +cd ${current_dir} + +# Regenerate Swift code +cd swift cd Greeter/Sources/Model fbc --swift ${generator} cd ${current_dir} -cd ts/ +# Regenerate Typescript code +cd ts cd greeter/src fbc --ts ${generator} -cd ${current_dir}
\ No newline at end of file +cd ${current_dir} diff --git a/grpc/examples/python/greeter/README.md b/grpc/examples/python/greeter/README.md new file mode 100644 index 00000000..fcf310c0 --- /dev/null +++ b/grpc/examples/python/greeter/README.md @@ -0,0 +1,12 @@ +# Python Greeter example + +## Prerequisite + +- You need to have grpc python installed on your device `pip install grpcio` +## How to run Server: + +- `python server.py ${PORT}` + +## How to run Client: + +- `python client.py ${PORT} ${NAME}`
\ No newline at end of file diff --git a/grpc/examples/python/greeter/client.py b/grpc/examples/python/greeter/client.py new file mode 100644 index 00000000..d2d71845 --- /dev/null +++ b/grpc/examples/python/greeter/client.py @@ -0,0 +1,40 @@ +import sys +import argparse +import grpc + +sys.path.insert(0, '../../../../../flatbuffers/python') + +import flatbuffers +from models import HelloReply, HelloRequest, greeter_grpc_fb + +parser = argparse.ArgumentParser() +parser.add_argument("port", help="server port to connect to", default=3000) +parser.add_argument("name", help="name to be sent to server", default="flatbuffers") + +def say_hello(stub, hello_request): + reply = stub.SayHello(hello_request) + r = HelloReply.HelloReply.GetRootAs(reply) + print(r.Message()) + +def say_many_hellos(stub, hello_request): + greetings = stub.SayManyHellos(hello_request) + for greeting in greetings: + r = HelloReply.HelloReply.GetRootAs(greeting) + print(r.Message()) + +def main(): + args = parser.parse_args() + + with grpc.insecure_channel('localhost:' + args.port) as channel: + builder = flatbuffers.Builder() + ind = builder.CreateString(args.name) + HelloRequest.HelloRequestStart(builder) + HelloRequest.HelloRequestAddName(builder, ind) + root = HelloRequest.HelloRequestEnd(builder) + builder.Finish(root) + output = bytes(builder.Output()) + stub = greeter_grpc_fb.GreeterStub(channel) + say_hello(stub, output) + say_many_hellos(stub, output) + +main()
\ No newline at end of file diff --git a/grpc/examples/python/greeter/models/HelloReply.py b/grpc/examples/python/greeter/models/HelloReply.py new file mode 100644 index 00000000..95434dcc --- /dev/null +++ b/grpc/examples/python/greeter/models/HelloReply.py @@ -0,0 +1,45 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: models + +import flatbuffers +from flatbuffers.compat import import_numpy +np = import_numpy() + +class HelloReply(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAs(cls, buf, offset=0): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = HelloReply() + x.Init(buf, n + offset) + return x + + @classmethod + def GetRootAsHelloReply(cls, buf, offset=0): + """This method is deprecated. Please switch to GetRootAs.""" + return cls.GetRootAs(buf, offset) + # HelloReply + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # HelloReply + def Message(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.String(o + self._tab.Pos) + return None + +def Start(builder): builder.StartObject(1) +def HelloReplyStart(builder): + """This method is deprecated. Please switch to Start.""" + return Start(builder) +def AddMessage(builder, message): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(message), 0) +def HelloReplyAddMessage(builder, message): + """This method is deprecated. Please switch to AddMessage.""" + return AddMessage(builder, message) +def End(builder): return builder.EndObject() +def HelloReplyEnd(builder): + """This method is deprecated. Please switch to End.""" + return End(builder)
\ No newline at end of file diff --git a/grpc/examples/python/greeter/models/HelloRequest.py b/grpc/examples/python/greeter/models/HelloRequest.py new file mode 100644 index 00000000..0263095e --- /dev/null +++ b/grpc/examples/python/greeter/models/HelloRequest.py @@ -0,0 +1,45 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: models + +import flatbuffers +from flatbuffers.compat import import_numpy +np = import_numpy() + +class HelloRequest(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAs(cls, buf, offset=0): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = HelloRequest() + x.Init(buf, n + offset) + return x + + @classmethod + def GetRootAsHelloRequest(cls, buf, offset=0): + """This method is deprecated. Please switch to GetRootAs.""" + return cls.GetRootAs(buf, offset) + # HelloRequest + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # HelloRequest + def Name(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.String(o + self._tab.Pos) + return None + +def Start(builder): builder.StartObject(1) +def HelloRequestStart(builder): + """This method is deprecated. Please switch to Start.""" + return Start(builder) +def AddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0) +def HelloRequestAddName(builder, name): + """This method is deprecated. Please switch to AddName.""" + return AddName(builder, name) +def End(builder): return builder.EndObject() +def HelloRequestEnd(builder): + """This method is deprecated. Please switch to End.""" + return End(builder)
\ No newline at end of file diff --git a/grpc/examples/python/greeter/models/__init__.py b/grpc/examples/python/greeter/models/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/grpc/examples/python/greeter/models/__init__.py diff --git a/grpc/examples/python/greeter/models/greeter_grpc_fb.py b/grpc/examples/python/greeter/models/greeter_grpc_fb.py new file mode 100644 index 00000000..b9f8a4ed --- /dev/null +++ b/grpc/examples/python/greeter/models/greeter_grpc_fb.py @@ -0,0 +1,52 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! + +import grpc + +class GreeterStub(object): + """ Interface exported by the server. """ + + def __init__(self, channel): + """ Constructor. + + Args: + channel: A grpc.Channel. + """ + + self.SayHello = channel.unary_unary( + "/models.Greeter/SayHello" + ) + + self.SayManyHellos = channel.unary_stream( + "/models.Greeter/SayManyHellos" + ) + + +class GreeterServicer(object): + """ Interface exported by the server. """ + + def SayHello(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + + def SayManyHellos(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler( + servicer.SayHello + ), + 'SayManyHellos': grpc.unary_stream_rpc_method_handler( + servicer.SayManyHellos + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'models.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + diff --git a/grpc/examples/python/greeter/server.py b/grpc/examples/python/greeter/server.py new file mode 100644 index 00000000..acca880b --- /dev/null +++ b/grpc/examples/python/greeter/server.py @@ -0,0 +1,57 @@ +from concurrent import futures +import sys +import argparse +import grpc + +sys.path.insert(0, '../../../../../flatbuffers/python') + +import flatbuffers +from models import HelloReply, HelloRequest, greeter_grpc_fb + +parser = argparse.ArgumentParser() +parser.add_argument("port", help="server on port", default=3000) + +def build_reply(message): + builder = flatbuffers.Builder() + ind = builder.CreateString(message) + HelloReply.HelloReplyStart(builder) + HelloReply.HelloReplyAddMessage(builder, ind) + root = HelloReply.HelloReplyEnd(builder) + builder.Finish(root) + return bytes(builder.Output()) + +class GreeterServicer(greeter_grpc_fb.GreeterServicer): + + def __init__(self): + self.greetings = ["Hi", "Hallo", "Ciao"] + + def SayHello(self, request, context): + r = HelloRequest.HelloRequest().GetRootAs(request, 0) + reply = "Unknown" + if r.Name(): + reply = r.Name() + return build_reply("welcome " + reply.decode('UTF-8')) + + def SayManyHellos(self, request, context): + r = HelloRequest.HelloRequest().GetRootAs(request, 0) + reply = "Unknown" + if r.Name(): + reply = r.Name() + + for greeting in self.greetings: + print(type(reply)) + yield build_reply(greeting + " " + reply.decode('UTF-8')) + + +def serve(): + args = parser.parse_args() + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + greeter_grpc_fb.add_GreeterServicer_to_server( + GreeterServicer(), server + ) + server.add_insecure_port('[::]:' + args.port) + server.start() + server.wait_for_termination() + +if __name__ == '__main__': + serve()
\ No newline at end of file |