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

Improvements to simplified demos #44

Merged
merged 3 commits into from
Mar 14, 2024
Merged
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
34 changes: 22 additions & 12 deletions src/tqdm_publisher/_demos/_multiple_bars/_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,56 @@
async def handler(websocket: websockets.WebSocketServerProtocol) -> None:
"""Handle messages from the client and manage the client connections."""

class WebSocketProgressBar(threading.Thread):
class WebSocketProgressBar:
"""
This is similar to the `send_progress_update_to_client` function from the single bar demo server.

The translation of this approach into a scoped class definition is merely to showcase an alternative approach
of the execution.
"""

def __init__(self, request_id: str):
super().__init__()
self.request_id = request_id

def update(self, format_dict) -> None:
def update(self, format_dict: dict) -> None:
"""
This is the function that will run on every update of the TQDM object.

It will forward the progress to the client.
"""
asyncio.run(
websocket.send(message=json.dumps(obj=dict(request_id=self.request_id, format_dict=format_dict)))
websocket.send(message=json.dumps(obj=dict(format_dict=format_dict, request_id=self.request_id)))
)

def run(self):
"""
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.
Defaults are chosen for a deterministic and regular update period of one second for a total time of
seconds per bar.

This is similar to the `start_progress_bar` function from the single bar demo server. This is simply a
showcase of an alternative approach to defining and scoping the execution.
"""
all_task_durations_in_seconds = [1.0 for _ in range(10)] # Ten seconds at one task per second
progress_bar = self.progress_bar = tqdm_publisher.TQDMPublisher(iterable=all_task_durations_in_seconds)
progress_bar.subscribe(callback=self.update)
self.progress_bar = tqdm_publisher.TQDMPublisher(iterable=all_task_durations_in_seconds)
self.progress_bar.subscribe(callback=self.update)

for task_duration in progress_bar:
for task_duration in self.progress_bar:
time.sleep(task_duration)

# def start(self):
# thread = threading.Thread(target=self.run_progress_bar)
# thread.start()
def start(self):
thread = threading.Thread(target=self.run)
thread.start()

# Wait for messages from the client
async for message in websocket:
message_from_client = json.loads(message)

if message_from_client["command"] == "start":
progress_bar = WebSocketProgressBar(request_id=message_from_client["request_id"])
progress_bar.start()
web_socket_progress_bar = WebSocketProgressBar(request_id=message_from_client["request_id"])
web_socket_progress_bar.start()


async def spawn_server() -> None:
Expand Down
32 changes: 12 additions & 20 deletions src/tqdm_publisher/_demos/_single_bar/_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def start_progress_bar(*, progress_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.
Defaults are chosen for a deterministic and regular update period of one second for a total time of 10 seconds.
"""
all_task_durations_in_seconds = [1.0 for _ in range(10)] # Ten seconds at one second per task
progress_bar = tqdm_publisher.TQDMPublisher(iterable=all_task_durations_in_seconds)
Expand All @@ -29,42 +29,34 @@ def run_function_on_progress_update(format_dict: dict) -> None:

This specifically requires the `id` of the progress bar and the `format_dict` of the TQDM instance.
"""
progress_callback(id=progress_bar.id, format_dict=format_dict)
progress_callback(format_dict=format_dict, progress_bar_id=progress_bar.id)

progress_bar.subscribe(callback=run_function_on_progress_update)

for task_duration in progress_bar:
time.sleep(task_duration)


def send_message_to_client(*, websocket: websockets.WebSocketServerProtocol, message: dict) -> None:
"""
Send a message to a specific client.

This expects a WebSocket connection and a message (dict) to send.
"""

asyncio.run(websocket.send(message=json.dumps(obj=message)))


async def handler(websocket: websockets.WebSocketServerProtocol) -> None:
"""Handle messages from the client and manage the client connections."""

def send_progress_update_to_client(*, format_dict: dict, progress_bar_id: str) -> None:
"""
This is the callback that actually sends the updated `format_dict` to the front end webpage.

It must be defined within the scope of the handler so that the `websocket` is inherited from the higher level.
"""
message = json.dumps(obj=dict(format_dict=format_dict, progress_bar_id=progress_bar_id))
asyncio.run(websocket.send(message=message))

# Wait for messages from the client
async for message in websocket:
message_from_client = json.loads(message)

if message_from_client["command"] == "start":

# Start the progress bar in a separate thread
thread = threading.Thread(
target=start_progress_bar,
# On each update of the progress bar, send this update to the requesting client
kwargs=dict(
progress_callback=lambda id, format_dict: send_message_to_client(
websocket=websocket, message=dict(id=id, format_dict=format_dict)
)
),
target=start_progress_bar, kwargs=dict(progress_callback=send_progress_update_to_client)
)
thread.start()

Expand Down
2 changes: 1 addition & 1 deletion src/tqdm_publisher/_publisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class TQDMPublisher(base_tqdm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.id = str(uuid4())
self.callbacks = {}
self.callbacks = dict()

# Override the update method to run callbacks
def update(self, n: int = 1) -> Union[bool, None]:
Expand Down
Loading