-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ed1422a
commit 74a0a05
Showing
8 changed files
with
136 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import os | ||
import subprocess | ||
import sys | ||
from pathlib import Path | ||
|
||
from ._server import run_demo | ||
|
||
DEMO_BASE_FOLDER_PATH = Path(__file__).parent | ||
|
||
CLIENT_FILE_PATH = DEMO_BASE_FOLDER_PATH / "_client.html" | ||
SERVER_FILE_PATH = DEMO_BASE_FOLDER_PATH / "_server.py" | ||
|
||
|
||
def _command_line_interface(): | ||
"""A simple command line interface for running the demo for TQDM Publisher.""" | ||
if len(sys.argv) <= 1: | ||
print("No input provided. Please specify a command (e.g. 'demo').") | ||
return | ||
|
||
command = sys.argv[1] | ||
if "-" in command: | ||
print( | ||
f"No command provided, but flag {command} was received. " | ||
"Please specify a command before the flag (e.g. 'demo')." | ||
) | ||
return | ||
|
||
flags_list = sys.argv[2:] | ||
if len(flags_list) > 0: | ||
print(f"No flags are accepted at this time, but flags {flags_list} were received.") | ||
return | ||
|
||
if command == "demo": | ||
# For convenience - automatically pop-up a browser window on the locally hosted HTML page | ||
if sys.platform == "win32": | ||
os.system(f'start "" "{CLIENT_FILE_PATH}"') | ||
else: | ||
subprocess.run(["open", CLIENT_FILE_PATH]) | ||
|
||
run_demo() | ||
|
||
else: | ||
print(f"{command} is an invalid command.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import asyncio | ||
import json | ||
import threading | ||
import time | ||
from typing import Dict, Any, List | ||
from uuid import uuid4 | ||
|
||
import websockets | ||
|
||
from tqdm_publisher import TQDMPublisher | ||
|
||
|
||
def start_progress_bar(*, client_id: str, progress_bar_id: str, client_callback: callable) -> None: | ||
""" | ||
Emulate running the specified number of tasks by sleeping the specified amount of time on each iteration. | ||
Defaults are chosen for a deterministic and regular update period of one second for a total time of one minute. | ||
""" | ||
all_task_durations_in_seconds = [1.0 for _ in range(60)] # One minute at one second per update | ||
progress_bar = TQDMPublisher(iterable=all_task_durations_in_seconds) | ||
|
||
def run_function_on_progress_update(format_dict: dict) -> None: | ||
""" | ||
This is the injected callback that will be run on each update of the TQDM object. | ||
Its first and only positional argument must be the `format_dict` of the TQDM instance. Additional customization | ||
on outside parameters must be achieved by defining those fields at an outer scope and defining this | ||
server-specific callback inside the local scope. | ||
In this demo, we will execute the `client_callback` whose protocol is known only to the WebSocketHandler. | ||
It has | ||
""" | ||
client_callback(client_id=client_id, progress_bar_id=progress_bar_id, format_dict=format_dict) | ||
|
||
progress_bar.subscribe(callback=run_function_on_progress_update) | ||
|
||
for task_duration in progress_bar: | ||
time.sleep(task_duration) | ||
|
||
|
||
class WebSocketHandler: | ||
"""Describe this class.""" | ||
|
||
def __init__(self) -> None: | ||
"""Initialize the mapping of client IDs to .""" | ||
self.clients: Dict[str, Any] = dict() | ||
|
||
def function_to_run_on_progress_update(self, *, client_id: str, progress_bar_id: str, format_dict: dict) -> None: | ||
"""This is...""" | ||
asyncio.run(self.send(client_id=client_id, data=dict(progress_bar_id=progress_bar_id, format_dict=format_dict))) | ||
|
||
async def send(self, client_id: str, data: dict) -> None: | ||
"""Send an arbitrary JSON object `data` to the client identifier by `client_id`.""" | ||
await self.clients[client_id].send(json.dumps(obj=data)) | ||
|
||
async def handler(self, websocket) -> None: | ||
"""Describe what the handler does.""" | ||
client_id = str(uuid4()) | ||
self.clients[client_id] = websocket # Register client connection | ||
|
||
try: | ||
async for message in websocket: | ||
message_from_client = json.loads(message) | ||
|
||
if message_from_client["command"] == "start": | ||
thread = threading.Thread( | ||
target=start_progress_bar, | ||
kwargs=dict( | ||
client_id=client_id, | ||
progress_bar_id=message_from_client["progress_bar_id"], | ||
client_callback=self.function_to_run_on_progress_update, | ||
), | ||
) | ||
thread.start() | ||
finally: # This is called when the connection is closed | ||
if client_id in self.clients: | ||
del self.clients[client_id] | ||
|
||
|
||
async def spawn_server() -> None: | ||
"""Spawn the server asynchronously.""" | ||
handler = WebSocketHandler().handler | ||
async with websockets.serve(handler, "", 8000): | ||
await asyncio.Future() | ||
|
||
|
||
def run_demo() -> None: | ||
"""Trigger the execution of the asynchronous spawn.""" | ||
asyncio.run(spawn_server()) |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.