22"""Example script that uses the athena client."""
33
44import asyncio
5- import io
65import logging
76import os
8- import random
9- from collections .abc import AsyncIterator
10- from pathlib import Path
7+ import sys
8+ import time
119
10+ from create_image import iter_images
1211from dotenv import load_dotenv
13- from PIL import Image , ImageDraw
1412
1513from athena_client .client .athena_client import AthenaClient
1614from athena_client .client .athena_options import AthenaOptions
1715from athena_client .client .channel import create_channel
18-
19- EXAMPLE_IMAGES_DIR = Path (__file__ ).parent / "example_images"
20-
21-
22- def create_random_image (width : int = 640 , height : int = 480 ) -> bytes :
23- """Create a random test image with random shapes and colors.
24-
25- Args:
26- width: Width of the test image in pixels
27- height: Height of the test image in pixels
28-
29- Returns:
30- JPEG image bytes
31-
32- """
33- # Create a new image with random background color
34- image = Image .new (
35- "RGB" ,
36- (width , height ),
37- (
38- random .randint (0 , 255 ),
39- random .randint (0 , 255 ),
40- random .randint (0 , 255 ),
41- ),
42- )
43-
44- draw = ImageDraw .Draw (image )
45-
46- # Draw some random shapes
47- for _ in range (3 ):
48- # Random coordinates
49- x0 = random .randint (0 , width - 1 )
50- y0 = random .randint (0 , height - 1 )
51- x1 = random .randint (0 , width - 1 )
52- y1 = random .randint (0 , height - 1 )
53-
54- # Random color
55- color = (
56- random .randint (0 , 255 ),
57- random .randint (0 , 255 ),
58- random .randint (0 , 255 ),
59- )
60-
61- draw .rectangle (
62- [min (x0 , x1 ), min (y0 , y1 ), max (x0 , x1 ), max (y0 , y1 )], fill = color
63- )
64-
65- # Convert to JPEG bytes
66- img_byte_arr = io .BytesIO ()
67- image .save (img_byte_arr , format = "JPEG" )
68- return img_byte_arr .getvalue ()
69-
70-
71- async def iter_images (max_images : int | None = None ) -> AsyncIterator [bytes ]:
72- """Generate random test images.
73-
74- Args:
75- max_images: Maximum number of images to generate. If None, generates
76- infinitely.
77-
78- Yields:
79- JPEG image bytes with random content
80-
81- """
82- count = 0
83- while max_images is None or count < max_images :
84- yield create_random_image ()
85- count += 1
16+ from athena_client .client .deployment_selector import DeploymentSelector
8617
8718
8819async def run_example (
@@ -104,37 +35,91 @@ async def run_example(
10435 channel = create_channel (options .host , auth_token )
10536
10637 async with AthenaClient (channel , options ) as client :
38+ # Start image classification
10739 results = client .classify_images (iter_images (max_test_images ))
108- logger .info ("Classifying images in image iter" )
109- async for result in results :
110- result_msg = f"Get result { result = } "
111- logger .info (result_msg )
112-
113-
114- async def main () -> None :
40+ logger .info ("Starting classification..." )
41+
42+ # Initialize rate tracking
43+ start_time = time .time ()
44+ response_count = 0
45+
46+ try :
47+ async for result in results :
48+ response_count += 1
49+ current_time = time .time ()
50+ elapsed = current_time - start_time
51+
52+ if response_count % 10 == 0 :
53+ rate = response_count / elapsed
54+ logger .info (
55+ "Processed %d responses (%.1f/sec)" ,
56+ response_count ,
57+ rate ,
58+ )
59+
60+ logger .debug ("Got result: %s" , result )
61+ except Exception :
62+ logger .exception ("Error during classification" )
63+ if response_count == 0 :
64+ # Re-raise if we didn't process any responses
65+ raise
66+ finally :
67+ # Calculate final statistics after loop completes
68+ if response_count > 0 :
69+ duration = time .time () - start_time
70+ avg_rate = response_count / duration
71+ logger .info (
72+ "\n Final: %d responses in %.1f seconds (%.1f/sec)" ,
73+ response_count ,
74+ duration ,
75+ avg_rate ,
76+ )
77+
78+
79+ async def main () -> int :
11580 """Run examples showing both authenticated and unauthenticated usage."""
11681 logger = logging .getLogger (__name__ )
11782 load_dotenv ()
11883
11984 # Set maximum number of test images to generate (None for infinite)
120- max_test_images = 5
85+ max_test_images = None
12186
12287 # Example with authenticated channel
12388 auth_token = os .getenv ("ATHENA_AUTH_TOKEN" )
124- if auth_token :
125- logger .info ("Running example with secure authenticated channel..." )
126- auth_options = AthenaOptions (
127- host = os .getenv ("ATHENA_HOST" , "localhost" ),
128- resize_images = True ,
129- deployment_id = "argh" ,
130- )
131- await run_example (logger , auth_options , auth_token , max_test_images )
132- else :
133- logger .info (
134- "Skipping authenticated example - ATHENA_AUTH_TOKEN not set"
135- )
89+ if not auth_token :
90+ logger .error ("ATHENA_AUTH_TOKEN not set." )
91+ return 1
92+
93+ logger .info ("Running example with secure authenticated channel" )
94+ host = os .getenv ("ATHENA_HOST" , "localhost" )
95+ channel = create_channel (host , auth_token )
96+
97+ # Get the first available deployment using context manager
98+ async with DeploymentSelector (channel ) as deployment_selector :
99+ deployments = await deployment_selector .list_deployments ()
100+
101+ if not deployments .deployments :
102+ logger .error ("No deployments available" )
103+ return 1
104+
105+ deployment_id = deployments .deployments [0 ].deployment_id
106+ logger .info ("Using deployment: %s" , deployment_id )
107+
108+ athena_options = AthenaOptions (
109+ host = host ,
110+ resize_images = True ,
111+ deployment_id = deployment_id ,
112+ compress_images = True ,
113+ )
114+ await run_example (logger , athena_options , auth_token , max_test_images )
115+
116+ return 0
136117
137118
138119if __name__ == "__main__" :
139- logging .basicConfig (level = logging .INFO )
140- asyncio .run (main ())
120+ logging .basicConfig (
121+ level = logging .DEBUG ,
122+ format = "%(asctime)s.%(msecs)03d %(levelname)s: %(message)s" ,
123+ datefmt = "%H:%M:%S" ,
124+ )
125+ sys .exit (asyncio .run (main ()))
0 commit comments