Skip to content

Commit ba87407

Browse files
committed
- ruff/mypy fixes
- added example users in db - test/alice, location - test_data.py
1 parent f5e72b3 commit ba87407

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1129
-856
lines changed

chat/api_client.py

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import queue
55
import threading
66
import time
7-
from datetime import datetime, timedelta, timezone
7+
from contextlib import suppress
8+
from datetime import UTC, datetime, timedelta
89

910
import keyring
1011
import pytz
@@ -40,7 +41,7 @@ def __init__(self, base_url):
4041
self.logger.addHandler(handler)
4142

4243
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
43-
REDIS_PORT = int(os.environ.get("REDIS_PORT", 6379))
44+
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
4445

4546
# Initialize Redis client with error handling
4647
try:
@@ -68,7 +69,7 @@ def __init__(self, base_url):
6869
)
6970
except redis.ConnectionError as e:
7071
self.logger.error(
71-
f"Unable to connect to Redis at {REDIS_HOST}:{REDIS_PORT}.\nERROR: {str(e)}"
72+
f"Unable to connect to Redis at {REDIS_HOST}:{REDIS_PORT}.\nERROR: {e!s}"
7273
)
7374
self.redis_client = None
7475
self.pubsub = None
@@ -104,7 +105,7 @@ def _load_stored_tokens(self):
104105
self.token_expiry = None
105106

106107
except Exception as e:
107-
self.logger.error(f"Error loading stored tokens: {str(e)}")
108+
self.logger.error(f"Error loading stored tokens: {e!s}")
108109
# If there's an error, start with clean slate
109110
self.access_token = None
110111
self.refresh_token = None
@@ -142,26 +143,20 @@ def _store_tokens(self, access_token=None, refresh_token=None, token_expiry=None
142143
self.logger.info("Removed stored token expiry")
143144

144145
except Exception as e:
145-
self.logger.error(f"Error storing tokens: {str(e)}")
146+
self.logger.error(f"Error storing tokens: {e!s}")
146147

147148
def _clear_stored_tokens(self):
148149
"""
149150
Clears all stored tokens from secure storage.
150151
"""
151-
try:
152+
with suppress(keyring.errors.PasswordDeleteError):
152153
keyring.delete_password("flet-chat", "access_token")
153-
except keyring.errors.PasswordDeleteError:
154-
pass # Token doesn't exist
155154

156-
try:
155+
with suppress(keyring.errors.PasswordDeleteError):
157156
keyring.delete_password("flet-chat", "refresh_token")
158-
except keyring.errors.PasswordDeleteError:
159-
pass # Token doesn't exist
160157

161-
try:
158+
with suppress(keyring.errors.PasswordDeleteError):
162159
keyring.delete_password("flet-chat", "token_expiry")
163-
except keyring.errors.PasswordDeleteError:
164-
pass # Token doesn't exist
165160

166161
self.logger.info("Cleared all stored tokens")
167162

@@ -175,7 +170,7 @@ def is_authenticated(self):
175170

176171
# Check if token is expired (with 5 minute buffer)
177172
if self.token_expiry:
178-
current_time = datetime.now(timezone.utc)
173+
current_time = datetime.now(UTC)
179174
if current_time >= self.token_expiry - timedelta(minutes=5):
180175
return False
181176

@@ -197,13 +192,13 @@ def _listen_to_pubsub(self):
197192
self.message_queue.put({"channel": channel, "data": data})
198193
except redis.ConnectionError as e:
199194
self.logger.error(
200-
f"Redis connection error: {str(e)}. Attempting to reconnect in 5 seconds..."
195+
f"Redis connection error: {e!s}. Attempting to reconnect in 5 seconds..."
201196
)
202197
time.sleep(5) # Wait before reconnecting
203198
self._reconnect_redis()
204199
except Exception as e:
205200
self.logger.error(
206-
f"Unexpected error in pubsub listener: {str(e)}. Continuing..."
201+
f"Unexpected error in pubsub listener: {e!s}. Continuing..."
207202
)
208203

209204
def _process_messages(self):
@@ -221,7 +216,7 @@ def _process_messages(self):
221216
callback(data)
222217
except Exception as e:
223218
self.logger.error(
224-
f"Error in callback for channel '{channel}': {str(e)}"
219+
f"Error in callback for channel '{channel}': {e!s}"
225220
)
226221

227222
def _handle_response(self, response):
@@ -278,7 +273,7 @@ def _refresh_token(self):
278273
self._clear_stored_tokens()
279274
return False
280275
except Exception as e:
281-
self.logger.error(f"Exception during token refresh: {str(e)}")
276+
self.logger.error(f"Exception during token refresh: {e!s}")
282277
return False
283278

284279
def _request(self, method, endpoint, auth_required=True, **kwargs):
@@ -289,15 +284,17 @@ def _request(self, method, endpoint, auth_required=True, **kwargs):
289284
headers = kwargs.get("headers", {})
290285

291286
if auth_required:
292-
current_time = datetime.now(timezone.utc)
293-
if not self.access_token or (
294-
self.token_expiry
295-
and current_time >= self.token_expiry - timedelta(minutes=5)
296-
):
297-
if not self._refresh_token():
298-
return ApiResponse(
299-
False, error="Failed to refresh token. Please log in again."
287+
current_time = datetime.now(UTC)
288+
if (
289+
not self.access_token
290+
or (
291+
self.token_expiry
292+
and current_time >= self.token_expiry - timedelta(minutes=5)
300293
)
294+
) and not self._refresh_token():
295+
return ApiResponse(
296+
False, error="Failed to refresh token. Please log in again."
297+
)
301298

302299
headers["Authorization"] = f"Bearer {self.access_token}"
303300
kwargs["headers"] = headers
@@ -307,9 +304,9 @@ def _request(self, method, endpoint, auth_required=True, **kwargs):
307304
api_response = self._handle_response(response)
308305

309306
if (
310-
not api_response.success
311-
and api_response.status_code == 401
312-
and "Could not validate credentials" in (api_response.error or "")
307+
not api_response.success
308+
and api_response.status_code == 401
309+
and "Could not validate credentials" in (api_response.error or "")
313310
):
314311
self.logger.warning(
315312
"Received 401 Unauthorized. Attempting to refresh token."
@@ -322,7 +319,7 @@ def _request(self, method, endpoint, auth_required=True, **kwargs):
322319

323320
return api_response
324321
except Exception as e:
325-
self.logger.error(f"HTTP request exception: {str(e)}")
322+
self.logger.error(f"HTTP request exception: {e!s}")
326323
return ApiResponse(False, error=str(e))
327324

328325
def subscribe_to_channel(self, channel_name, callback):
@@ -372,15 +369,15 @@ def _handle_redis_message(self, message):
372369
self.subscriptions[channel](data)
373370
except Exception as e:
374371
self.logger.error(
375-
f"Error in callback for channel '{channel}': {str(e)}"
372+
f"Error in callback for channel '{channel}': {e!s}"
376373
)
377374

378375
def _reconnect_redis(self):
379376
"""
380377
Attempts to reconnect to Redis and resubscribe to channels.
381378
"""
382379
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
383-
REDIS_PORT = int(os.environ.get("REDIS_PORT", 6379))
380+
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
384381
try:
385382
self.redis_client = redis.Redis(
386383
host=REDIS_HOST,
@@ -392,13 +389,13 @@ def _reconnect_redis(self):
392389
self.redis_client.ping()
393390
self.pubsub = self.redis_client.pubsub()
394391
# Resubscribe to existing channels
395-
for channel in self.subscriptions.keys():
392+
for channel in self.subscriptions:
396393
self.pubsub.subscribe(**{channel: self._handle_redis_message})
397394
self.logger.info(f"Resubscribed to Redis channel '{channel}'")
398395
self.logger.info(f"Reconnected to Redis at {REDIS_HOST}:{REDIS_PORT}")
399396
except redis.ConnectionError as e:
400397
self.logger.error(
401-
f"Failed to reconnect to Redis: {str(e)}. Will retry in 5 seconds."
398+
f"Failed to reconnect to Redis: {e!s}. Will retry in 5 seconds."
402399
)
403400
time.sleep(5)
404401
self._reconnect_redis()

chat/app.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import json
21
import logging
32
import os
4-
from typing import Dict, Any, Union
3+
from typing import Any
54

65
import flet as ft
76

@@ -10,7 +9,7 @@
109
from .chat_screen import ChatScreen
1110
from .login_screen import LoginScreen
1211
from .register_screen import RegisterScreen
13-
from .state_manager import StateManager, AppState, StateEvent
12+
from .state_manager import AppState, StateEvent, StateManager
1413
from .user_profile_screen import UserProfileScreen
1514

1615

@@ -48,11 +47,11 @@ def __init__(self, page: ft.Page) -> None:
4847
else:
4948
self.show_login()
5049

51-
def _on_user_logged_in(self, data: Dict[str, Any]) -> None:
50+
def _on_user_logged_in(self, data: dict[str, Any]) -> None:
5251
self.logger.info("User logged in, updating UI")
5352
# UI will be updated by screens subscribing to state changes
5453

55-
def _on_user_logged_out(self, data: Dict[str, Any]) -> None:
54+
def _on_user_logged_out(self, data: dict[str, Any]) -> None:
5655
self.logger.info("User logged out, showing login screen")
5756
self.show_login()
5857

@@ -88,7 +87,7 @@ def show_user_profile(self) -> None:
8887
screen.build()
8988
self.switch_screen(screen)
9089

91-
def handle_successful_login(self, user_data: Dict[str, Any]) -> None:
90+
def handle_successful_login(self, user_data: dict[str, Any]) -> None:
9291
self.logger.info(
9392
f"Handling successful login for user: {user_data.get('username', 'Unknown')}"
9493
)
@@ -106,7 +105,7 @@ def refresh_chats(self) -> bool:
106105
def show_error_dialog(self, title: str, error: Any) -> None:
107106
"""Display an error dialog, converting any error to string."""
108107

109-
def close_dlg(e: ft.ControlEvent) -> None:
108+
def close_dlg(_: ft.ControlEvent) -> None:
110109
self.page.close(dlg)
111110

112111
dlg = ft.AlertDialog(

chat/chat_screen.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -425,18 +425,17 @@ def process_new_message(self, data):
425425
# Update existing message (e.g., edited or status changed)
426426
self.update_message_in_list(existing_message_row, message)
427427
self.logger.info(f"Updated existing message {message['id']} in UI")
428-
else:
428+
elif message["user"]["id"] != self.current_user_id:
429429
# Add new message only if it's not from the current user
430430
# (current user's messages are added immediately in send_message)
431-
if message["user"]["id"] != self.current_user_id:
432-
self.add_message_to_list(message)
433-
self.logger.info(
434-
f"Added new message {message['id']} from other user to UI"
435-
)
436-
else:
437-
self.logger.info(
438-
f"Skipping message {message['id']} from current user (already added)"
439-
)
431+
self.add_message_to_list(message)
432+
self.logger.info(
433+
f"Added new message {message['id']} from other user to UI"
434+
)
435+
else:
436+
self.logger.info(
437+
f"Skipping message {message['id']} from current user (already added)"
438+
)
440439

441440
# Only auto-scroll if user is at bottom
442441
if self._should_auto_scroll():
@@ -452,7 +451,7 @@ def process_new_message(self, data):
452451
except json.JSONDecodeError:
453452
self.logger.error(f"Failed to decode message: {data}")
454453
except Exception as e:
455-
self.logger.error(f"Error processing new message: {str(e)}")
454+
self.logger.error(f"Error processing new message: {e!s}")
456455

457456
def update_message_in_list(self, existing_message_row, updated_message):
458457
"""
@@ -479,8 +478,6 @@ def update_message_in_list(self, existing_message_row, updated_message):
479478
):
480479
return
481480

482-
# [ Text(username), Text(message_content), time_info_row ]
483-
# user_text = column_content.controls[0] # ft.Text(username)
484481
message_text = column_content.controls[1] # ft.Text(content or <deleted>)
485482
time_info = column_content.controls[2] # ft.Row([... time info ...])
486483

chat/login_screen.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
import re
3+
34
import flet as ft
45

56

chat/register_screen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def show_success_dialog(self):
261261
"""
262262
self.logger.info("Showing registration success dialog")
263263

264-
def close_dlg(e):
264+
def close_dlg(_):
265265
self.chat_app.page.close(dlg)
266266
self.chat_app.show_login()
267267

0 commit comments

Comments
 (0)