Skip to content

Commit

Permalink
Improvements to simplified demos (#44)
Browse files Browse the repository at this point in the history
* enhance documentation; remove remaining anonymous callables; better variable names

* finish docstring
  • Loading branch information
CodyCBakerPhD authored Mar 14, 2024
1 parent e56fc6a commit 85e7a6f
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 33 deletions.
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

0 comments on commit 85e7a6f

Please sign in to comment.