summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-11-13 14:47:07 -0500
committerBen Sima <ben@bsima.me>2025-11-13 14:53:55 -0500
commit7884d54baa5387ceb89071c831245273cf42521a (patch)
treebe92ae097a8b545699c2838565043e2a01c1a8de
parentbbb1e56e97ee5e899fc6deae497f06b3f13595d3 (diff)
Improve type safety in Billing module
- Add explicit type annotations to TIER_LIMITS dict - Add type annotation to tier_info dict in get_tier_info - Remove unnecessary type: ignore comments - Use .get() consistently for dict access Improves type safety and removes 3 type: ignore suppressions. Amp-Thread-ID: https://ampcode.com/threads/T-8edacbeb-b343-49ca-b524-1c999272acb6 Co-authored-by: Amp <amp@ampcode.com>
-rw-r--r--.tasks/tasks.jsonl8
-rw-r--r--Biz/PodcastItLater/Billing.py16
2 files changed, 13 insertions, 11 deletions
diff --git a/.tasks/tasks.jsonl b/.tasks/tasks.jsonl
index f2e2f4a..338188a 100644
--- a/.tasks/tasks.jsonl
+++ b/.tasks/tasks.jsonl
@@ -51,10 +51,10 @@
{"taskCreatedAt":"2025-11-13T19:38:08.37344762Z","taskDependencies":[],"taskId":"t-1f9Td4U","taskNamespace":null,"taskParent":null,"taskStatus":"Open","taskTitle":"Navbar Styling Cleanup","taskType":"Epic","taskUpdatedAt":"2025-11-13T19:38:08.37344762Z"}
{"taskCreatedAt":"2025-11-13T19:38:32.95559213Z","taskDependencies":[],"taskId":"t-1fbym1M","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Remove BLE001 noqa for bare Exception catches - use specific exceptions","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:43:29.049855419Z"}
{"taskCreatedAt":"2025-11-13T19:38:33.139120541Z","taskDependencies":[],"taskId":"t-1fbz7LV","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Fix PLR0913 violations - refactor functions with too many parameters","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:44:09.820023426Z"}
-{"taskCreatedAt":"2025-11-13T19:38:33.309222802Z","taskDependencies":[],"taskId":"t-1fbzQ1v","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"InProgress","taskTitle":"Extract format_duration utility to shared UI or Core module (used only in Web.py)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:44:13.950088651Z"}
-{"taskCreatedAt":"2025-11-13T19:38:33.491331064Z","taskDependencies":[],"taskId":"t-1fbABoD","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Extract extract_og_metadata and send_magic_link to Core module for reusability","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.491331064Z"}
-{"taskCreatedAt":"2025-11-13T19:38:33.674140035Z","taskDependencies":[],"taskId":"t-1fbBmXa","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Review and fix type: ignore comments - improve type safety","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.674140035Z"}
-{"taskCreatedAt":"2025-11-13T19:38:33.85804778Z","taskDependencies":[],"taskId":"t-1fbC8Nq","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Remove PLR2004 magic number - use constant for month check","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.85804778Z"}
+{"taskCreatedAt":"2025-11-13T19:38:33.309222802Z","taskDependencies":[],"taskId":"t-1fbzQ1v","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Extract format_duration utility to shared UI or Core module (used only in Web.py)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:45:49.402934404Z"}
+{"taskCreatedAt":"2025-11-13T19:38:33.491331064Z","taskDependencies":[],"taskId":"t-1fbABoD","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Extract extract_og_metadata and send_magic_link to Core module for reusability","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:46:04.679290775Z"}
+{"taskCreatedAt":"2025-11-13T19:38:33.674140035Z","taskDependencies":[],"taskId":"t-1fbBmXa","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Review and fix type: ignore comments - improve type safety","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:47:09.583640045Z"}
+{"taskCreatedAt":"2025-11-13T19:38:33.85804778Z","taskDependencies":[],"taskId":"t-1fbC8Nq","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Remove PLR2004 magic number - use constant for month check","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:47:45.120428021Z"}
{"taskCreatedAt":"2025-11-13T19:38:34.035597081Z","taskDependencies":[],"taskId":"t-1fbCSZd","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Implement cancel subscription functionality","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.035597081Z"}
{"taskCreatedAt":"2025-11-13T19:38:34.194926176Z","taskDependencies":[],"taskId":"t-1fbDyr2","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Implement delete account functionality","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.194926176Z"}
{"taskCreatedAt":"2025-11-13T19:38:34.384489707Z","taskDependencies":[],"taskId":"t-1fbElKv","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Implement change email address functionality","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.384489707Z"}
diff --git a/Biz/PodcastItLater/Billing.py b/Biz/PodcastItLater/Billing.py
index 4996607..0e2537a 100644
--- a/Biz/PodcastItLater/Billing.py
+++ b/Biz/PodcastItLater/Billing.py
@@ -37,7 +37,7 @@ PRICE_TO_TIER = {
}
# Tier limits (None = unlimited)
-TIER_LIMITS = {
+TIER_LIMITS: dict[str, dict[str, int | None]] = {
"free": {
"articles_per_period": 10,
"minutes_per_period": None,
@@ -112,7 +112,7 @@ def can_submit(user_id: int) -> tuple[bool, str, dict[str, int]]:
usage = get_usage(user_id, period_start, period_end)
# Check article limit
- article_limit = limits["articles_per_period"] # type: ignore[index]
+ article_limit = limits.get("articles_per_period")
if article_limit is not None and usage["articles"] >= article_limit:
msg = (
f"You've reached your limit of {article_limit} articles "
@@ -121,7 +121,7 @@ def can_submit(user_id: int) -> tuple[bool, str, dict[str, int]]:
return (False, msg, usage)
# Check minutes limit (if implemented)
- minute_limit = limits.get("minutes_per_period") # type: ignore[attr-defined]
+ minute_limit = limits.get("minutes_per_period")
if minute_limit is not None and usage.get("minutes", 0) >= minute_limit:
return (
False,
@@ -391,11 +391,13 @@ def _update_subscription_state(subscription: dict[str, typing.Any]) -> None:
period_start = datetime.fromtimestamp(period_start_ts, tz=timezone.utc)
# Calculate period end if not provided (assume monthly)
+ december = 12
+ january = 1
if not period_end_ts:
- if period_start.month == 12: # noqa: PLR2004
+ if period_start.month == december:
period_end = period_start.replace(
year=period_start.year + 1,
- month=1,
+ month=january,
)
else:
period_end = period_start.replace(month=period_start.month + 1)
@@ -447,7 +449,7 @@ def get_tier_info(tier: str) -> dict[str, typing.Any]:
Returns:
dict with keys: name, articles_limit, price, description
"""
- tier_info = {
+ tier_info: dict[str, dict[str, typing.Any]] = {
"free": {
"name": "Free",
"articles_limit": 10,
@@ -461,7 +463,7 @@ def get_tier_info(tier: str) -> dict[str, typing.Any]:
"description": "Unlimited articles",
},
}
- return tier_info.get(tier, tier_info["free"]) # type: ignore[return-value]
+ return tier_info.get(tier, tier_info["free"])
# Tests