• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2020 The gRPC Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""The Python AsyncIO implementation of the gRPC route guide client."""
15
16import asyncio
17import logging
18import random
19from typing import Iterable, List
20
21import grpc
22import route_guide_pb2
23import route_guide_pb2_grpc
24import route_guide_resources
25
26
27def make_route_note(
28    message: str, latitude: int, longitude: int
29) -> route_guide_pb2.RouteNote:
30    return route_guide_pb2.RouteNote(
31        message=message,
32        location=route_guide_pb2.Point(latitude=latitude, longitude=longitude),
33    )
34
35
36# Performs a unary call
37async def guide_get_one_feature(
38    stub: route_guide_pb2_grpc.RouteGuideStub, point: route_guide_pb2.Point
39) -> None:
40    feature = await stub.GetFeature(point)
41    if not feature.location:
42        print("Server returned incomplete feature")
43        return
44
45    if feature.name:
46        print(f"Feature called {feature.name} at {feature.location}")
47    else:
48        print(f"Found no feature at {feature.location}")
49
50
51async def guide_get_feature(stub: route_guide_pb2_grpc.RouteGuideStub) -> None:
52    # The following two coroutines will be wrapped in a Future object
53    # and scheduled in the event loop so that they can run concurrently
54    task_group = asyncio.gather(
55        guide_get_one_feature(
56            stub,
57            route_guide_pb2.Point(latitude=409146138, longitude=-746188906),
58        ),
59        guide_get_one_feature(
60            stub, route_guide_pb2.Point(latitude=0, longitude=0)
61        ),
62    )
63    # Wait until the Future is resolved
64    await task_group
65
66
67# Performs a server-streaming call
68async def guide_list_features(
69    stub: route_guide_pb2_grpc.RouteGuideStub,
70) -> None:
71    rectangle = route_guide_pb2.Rectangle(
72        lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000),
73        hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000),
74    )
75    print("Looking for features between 40, -75 and 42, -73")
76
77    features = stub.ListFeatures(rectangle)
78
79    async for feature in features:
80        print(f"Feature called {feature.name} at {feature.location}")
81
82
83def generate_route(
84    feature_list: List[route_guide_pb2.Feature],
85) -> Iterable[route_guide_pb2.Point]:
86    for _ in range(0, 10):
87        random_feature = random.choice(feature_list)
88        print(f"Visiting point {random_feature.location}")
89        yield random_feature.location
90
91
92# Performs a client-streaming call
93async def guide_record_route(stub: route_guide_pb2_grpc.RouteGuideStub) -> None:
94    feature_list = route_guide_resources.read_route_guide_database()
95    route_iterator = generate_route(feature_list)
96
97    # gRPC AsyncIO client-streaming RPC API accepts both synchronous iterables
98    # and async iterables.
99    route_summary = await stub.RecordRoute(route_iterator)
100    print(f"Finished trip with {route_summary.point_count} points")
101    print(f"Passed {route_summary.feature_count} features")
102    print(f"Travelled {route_summary.distance} meters")
103    print(f"It took {route_summary.elapsed_time} seconds")
104
105
106def generate_messages() -> Iterable[route_guide_pb2.RouteNote]:
107    messages = [
108        make_route_note("First message", 0, 0),
109        make_route_note("Second message", 0, 1),
110        make_route_note("Third message", 1, 0),
111        make_route_note("Fourth message", 0, 0),
112        make_route_note("Fifth message", 1, 0),
113    ]
114    for msg in messages:
115        print(f"Sending {msg.message} at {msg.location}")
116        yield msg
117
118
119# Performs a bidi-streaming call
120async def guide_route_chat(stub: route_guide_pb2_grpc.RouteGuideStub) -> None:
121    # gRPC AsyncIO bidi-streaming RPC API accepts both synchronous iterables
122    # and async iterables.
123    call = stub.RouteChat(generate_messages())
124    async for response in call:
125        print(f"Received message {response.message} at {response.location}")
126
127
128async def main() -> None:
129    async with grpc.aio.insecure_channel("localhost:50051") as channel:
130        stub = route_guide_pb2_grpc.RouteGuideStub(channel)
131        print("-------------- GetFeature --------------")
132        await guide_get_feature(stub)
133        print("-------------- ListFeatures --------------")
134        await guide_list_features(stub)
135        print("-------------- RecordRoute --------------")
136        await guide_record_route(stub)
137        print("-------------- RouteChat --------------")
138        await guide_route_chat(stub)
139
140
141if __name__ == "__main__":
142    logging.basicConfig(level=logging.INFO)
143    asyncio.get_event_loop().run_until_complete(main())
144