aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstuppie2026-09-07 10:32:10 -0600
committerstuppie2026-09-07 10:32:10 -0600
commitc25a7351eeb6be4a998348a8cfc96bc4f965b96c (patch)
tree301ce11ccd62dec5ab8485ff4b6859b2bea119e6
parente1b1484c1b33708154a21dff095bd56c498115f4 (diff)
downloadgeneralresearch-c25a7351eeb6be4a998348a8cfc96bc4f965b96c.tar.gz
generalresearch-c25a7351eeb6be4a998348a8cfc96bc4f965b96c.zip
Fix Leaderboard optional fields were made not-optional
-rw-r--r--generalresearch/models/thl/leaderboard.py9
-rw-r--r--tests/managers/thl/test_contest/test_leaderboard.py10
-rw-r--r--tests/managers/thl/test_contest/test_milestone.py37
-rw-r--r--tests/managers/thl/test_contest/test_raffle.py49
-rw-r--r--tests/managers/thl/test_product.py6
-rw-r--r--tests/managers/thl/test_session_manager.py10
6 files changed, 64 insertions, 57 deletions
diff --git a/generalresearch/models/thl/leaderboard.py b/generalresearch/models/thl/leaderboard.py
index 523c696..6e49af2 100644
--- a/generalresearch/models/thl/leaderboard.py
+++ b/generalresearch/models/thl/leaderboard.py
@@ -78,6 +78,9 @@ class Leaderboard(BaseModel):
weekly, and monthly leaderboard.
"""
+ # Note: id and name get auto-generated by the model_validators, but the fields need
+ # to be optional with a default or the model can't be inited.
+ # todo: these should really be computed_fields instead
id: UUIDStr | None = Field(
description="Unique ID for this leaderboard",
examples=["845b0074ad533df580ebb9c80cc3bce1"],
@@ -108,9 +111,10 @@ class Leaderboard(BaseModel):
examples=[LeaderboardFrequency.DAILY],
)
- timezone_name: str = Field(
+ timezone_name: str | None = Field(
description="The timezone for the requested country",
examples=["America/New_York"],
+ default=None,
)
sort_order: Literal["ascending", "descending"] = Field(default="descending")
@@ -139,7 +143,7 @@ class Leaderboard(BaseModel):
# exclude=True,
)
- period_end_local: AwareDatetime = Field(
+ period_end_local: AwareDatetime | None = Field(
description="The end of the time period covered by this board in local time, tz-aware",
examples=[
datetime(
@@ -153,6 +157,7 @@ class Leaderboard(BaseModel):
tzinfo=ZoneInfo("America/New_York"),
)
],
+ default=None,
# exclude=True,
)
diff --git a/tests/managers/thl/test_contest/test_leaderboard.py b/tests/managers/thl/test_contest/test_leaderboard.py
index 9fd4428..8aa0780 100644
--- a/tests/managers/thl/test_contest/test_leaderboard.py
+++ b/tests/managers/thl/test_contest/test_leaderboard.py
@@ -26,7 +26,6 @@ if TYPE_CHECKING:
class TestLeaderboardContestCRUD:
-
def test_create(
self,
leaderboard_contest_create: LeaderboardContestCreate,
@@ -35,7 +34,8 @@ class TestLeaderboardContestCRUD:
contest_manager: ContestManager,
):
c = contest_manager.create(
- product_id=product_user_wallet_yes.uuid, contest_create=leaderboard_contest_create
+ product_id=product_user_wallet_yes.uuid,
+ contest_create=leaderboard_contest_create,
)
c_out = contest_manager.get(c.uuid)
assert c == c_out
@@ -55,8 +55,9 @@ class TestLeaderboardContestCRUD:
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
user_manager: UserManager,
- thl_redis: RedisConfig,
+ thl_redis_config: RedisConfig,
):
+ thl_redis = thl_redis_config.create_redis_client()
contest = leaderboard_contest_in_db
user = user_with_wallet
@@ -88,8 +89,9 @@ class TestLeaderboardContestCRUD:
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
user_manager: UserManager,
- thl_redis: RedisConfig,
+ thl_redis_config: RedisConfig,
):
+ thl_redis = thl_redis_config.create_redis_client()
# The contest should be over. We need to trigger it.
contest = leaderboard_contest_in_db
contest._redis_client = thl_redis
diff --git a/tests/managers/thl/test_contest/test_milestone.py b/tests/managers/thl/test_contest/test_milestone.py
index dab02e7..f26819b 100644
--- a/tests/managers/thl/test_contest/test_milestone.py
+++ b/tests/managers/thl/test_contest/test_milestone.py
@@ -20,17 +20,16 @@ if TYPE_CHECKING:
from generalresearch.models.thl.contest.milestone import (
MilestoneContestCreate,
)
- from generalresearch.models.thl.contest.raffle import RaffleContest
from generalresearch.models.thl.product import Product
from generalresearch.models.thl.user import User
class TestMilestoneContest:
-
def test_should_end(
self,
- contest: MilestoneContest,
+ milestone_contest: MilestoneContest,
):
+ contest = milestone_contest
# contest is active and has no entries
should, msg = contest.should_end()
assert not should, msg
@@ -51,15 +50,15 @@ class TestMilestoneContest:
class TestMilestoneContestCRUD:
-
def test_create(
self,
- contest_create: MilestoneContestCreate,
+ milestone_contest_create: MilestoneContestCreate,
product_user_wallet_yes: Product,
contest_manager: ContestManager,
):
c = contest_manager.create(
- product_id=product_user_wallet_yes.uuid, contest_create=contest_create
+ product_id=product_user_wallet_yes.uuid,
+ contest_create=milestone_contest_create,
)
c_out = contest_manager.get(c.uuid)
assert c == c_out
@@ -75,13 +74,13 @@ class TestMilestoneContestCRUD:
def test_enter(
self,
user_with_wallet: User,
- contest_in_db: MilestoneContest,
+ milestone_contest_in_db: MilestoneContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# Users CANNOT directly enter a milestone contest through the api,
# but we'll call this manager method when a trigger is hit.
- contest = contest_in_db
+ contest = milestone_contest_in_db
user = user_with_wallet
contest_manager.enter_milestone_contest(
@@ -131,13 +130,13 @@ class TestMilestoneContestCRUD:
def test_enter_win(
self,
user_with_wallet: User,
- contest_in_db: MilestoneContest,
+ milestone_contest_in_db: MilestoneContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# User enters contest, which brings the USER'S total amount above the limit,
# and the user reaches the milestone
- contest = contest_in_db
+ contest = milestone_contest_in_db
user = user_with_wallet
user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
@@ -196,13 +195,13 @@ class TestMilestoneContestCRUD:
self,
user_factory: Callable[..., User],
product_user_wallet_yes: Product,
- contest_in_db: MilestoneContest,
+ milestone_contest_in_db: MilestoneContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# Multiple users reach the milestone. Contest ends after 5 wins.
users = [user_factory(product=product_user_wallet_yes) for _ in range(5)]
- contest = contest_in_db
+ contest = milestone_contest_in_db
for u in users:
contest_manager.enter_milestone_contest(
@@ -220,7 +219,7 @@ class TestMilestoneContestCRUD:
def test_trigger(
self,
user_with_wallet: User,
- contest_in_db: MilestoneContest,
+ milestone_contest_in_db: MilestoneContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
@@ -235,7 +234,7 @@ class TestMilestoneContestCRUD:
# Assert this contest got entered
c: MilestoneUserView = contest_manager.get_milestone_user_view(
- contest_uuid=contest_in_db.uuid, user=user_with_wallet
+ contest_uuid=milestone_contest_in_db.uuid, user=user_with_wallet
)
assert c.user_amount == 1
@@ -244,7 +243,7 @@ class TestMilestoneContestUserViews:
def test_list_user_eligible_country(
self,
user_with_wallet: User,
- raffle_contest_factory: Callable[..., RaffleContest],
+ milestone_contest_factory: Callable[..., MilestoneContest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
@@ -255,7 +254,7 @@ class TestMilestoneContestUserViews:
assert len(cs) == 0
# Create a contest. It'll be in the US/CA
- raffle_contest_factory(country_isos={"us", "ca"})
+ milestone_contest_factory(country_isos={"us", "ca"})
# Not eligible in mexico
cs = contest_manager.get_many_by_user_eligible(
@@ -268,7 +267,7 @@ class TestMilestoneContestUserViews:
assert len(cs) == 1
# Create another, any country
- raffle_contest_factory(country_isos=None)
+ milestone_contest_factory(country_isos=None)
cs = contest_manager.get_many_by_user_eligible(
user=user_with_wallet, country_iso="mx"
)
@@ -281,12 +280,12 @@ class TestMilestoneContestUserViews:
def test_list_user_eligible(
self,
user_with_money: User,
- raffle_contest_factory: Callable[..., RaffleContest],
+ milestone_contest_factory: Callable[..., MilestoneContest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# User reaches milestone after 1 complete
- c = raffle_contest_factory(target_amount=1)
+ c = milestone_contest_factory(target_amount=1)
user = user_with_money
cs = contest_manager.get_many_by_user_eligible(
diff --git a/tests/managers/thl/test_contest/test_raffle.py b/tests/managers/thl/test_contest/test_raffle.py
index 0b2b852..7388991 100644
--- a/tests/managers/thl/test_contest/test_raffle.py
+++ b/tests/managers/thl/test_contest/test_raffle.py
@@ -47,8 +47,9 @@ class TestRaffleContest:
def test_should_end(
self,
- contest: RaffleContest,
+ raffle_contest: RaffleContest,
):
+ contest = raffle_contest
# contest is active and has no entries
should, msg = contest.should_end()
assert not should, msg
@@ -71,12 +72,12 @@ class TestRaffleContestCRUD:
def test_create(
self,
- contest_create: RaffleContestCreate,
+ raffle_contest_create: RaffleContestCreate,
product_user_wallet_yes: Product,
contest_manager: ContestManager,
):
c = contest_manager.create(
- product_id=product_user_wallet_yes.uuid, contest_create=contest_create
+ product_id=product_user_wallet_yes.uuid, contest_create=raffle_contest_create
)
c_out = contest_manager.get(c.uuid)
assert c == c_out
@@ -92,15 +93,15 @@ class TestRaffleContestCRUD:
def test_enter(
self,
user_with_money: User,
- contest_in_db: RaffleContest,
+ raffle_contest_in_db: RaffleContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# Raffle ends at $1.00. User enters for $0.60
print(user_with_money.product_id)
- print(contest_in_db.product_id)
- print(contest_in_db.uuid)
- contest = contest_in_db
+ print(raffle_contest_in_db.product_id)
+ print(raffle_contest_in_db.uuid)
+ contest = raffle_contest_in_db
user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(
user=user_with_money
@@ -145,13 +146,13 @@ class TestRaffleContestCRUD:
def test_enter_ends(
self,
user_with_money: User,
- contest_in_db: RaffleContest,
+ raffle_contest_in_db: RaffleContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# User enters contest, which brings the total amount above the limit,
# and the contest should end, with a winner selected
- contest = contest_in_db
+ contest = raffle_contest_in_db
bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet_by_uuid(
user_with_money.product_id
@@ -209,13 +210,13 @@ class TestRaffleContestCRUD:
def test_enter_ends_cash_prize(
self,
user_with_money: User,
- contest_factory: Callable[..., Contest],
+ raffle_contest_factory: Callable[..., Contest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# Same as test_enter_ends, but the prize is cash. Just
# testing the ledger methods
- c = contest_factory(
+ c = raffle_contest_factory(
prizes=[
ContestPrize(
name="$1.00 bonus",
@@ -268,11 +269,11 @@ class TestRaffleContestCRUD:
def test_enter_failure(
self,
user_with_wallet: User,
- contest_in_db: RaffleContest,
+ raffle_contest_in_db: RaffleContest,
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
- c = contest_in_db
+ c = raffle_contest_in_db
user = user_with_wallet
# Tries to enter $0
@@ -310,12 +311,12 @@ class TestRaffleContestCRUD:
def test_enter_not_eligible(
self,
user_with_money: User,
- contest_factory: Callable[..., Contest],
+ raffle_contest_factory: Callable[..., Contest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
# Max entry amount per user $0.10. Contest still ends at $1.00
- c = contest_factory(
+ c = raffle_contest_factory(
entry_rule=ContestEntryRule(
max_entry_amount_per_user=USDCent(10),
max_daily_entries_per_user=USDCent(8),
@@ -380,7 +381,7 @@ class TestRaffleContestUserViews:
def test_list_user_eligible_country(
self,
user_with_wallet: User,
- contest_factory: Callable[..., Contest],
+ raffle_contest_factory: Callable[..., Contest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
@@ -391,7 +392,7 @@ class TestRaffleContestUserViews:
assert len(cs) == 0
# Create a contest. It'll be in the US/CA
- contest_factory(country_isos={"us", "ca"})
+ raffle_contest_factory(country_isos={"us", "ca"})
# Not eligible in mexico
cs = contest_manager.get_many_by_user_eligible(
@@ -404,7 +405,7 @@ class TestRaffleContestUserViews:
assert len(cs) == 1
# Create another, any country
- contest_factory(country_isos=None)
+ raffle_contest_factory(country_isos=None)
cs = contest_manager.get_many_by_user_eligible(
user=user_with_wallet, country_iso="mx"
)
@@ -417,11 +418,11 @@ class TestRaffleContestUserViews:
def test_list_user_eligible(
self,
user_with_money: User,
- contest_factory: Callable[..., Contest],
+ raffle_contest_factory: Callable[..., Contest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
- c = contest_factory(
+ c = raffle_contest_factory(
end_condition=ContestEndCondition(target_entry_amount=USDCent(10)),
entry_rule=ContestEntryRule(
max_entry_amount_per_user=USDCent(1),
@@ -467,11 +468,11 @@ class TestRaffleContestUserViews:
def test_list_user_winnings(
self,
user_with_money: User,
- contest_factory: Callable[..., Contest],
+ raffle_contest_factory: Callable[..., Contest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
- c = contest_factory(
+ c = raffle_contest_factory(
end_condition=ContestEndCondition(target_entry_amount=USDCent(100)),
)
entry = ContestEntry(
@@ -507,11 +508,11 @@ class TestRaffleContestCRUDCount:
def test_enter(
self,
user_with_wallet: User,
- contest_factory: Callable[..., Contest],
+ raffle_contest_factory: Callable[..., Contest],
thl_ledger_manager: ThlLedgerManager,
contest_manager: ContestManager,
):
- c = contest_factory(entry_type=ContestEntryType.COUNT)
+ c = raffle_contest_factory(entry_type=ContestEntryType.COUNT)
entry = ContestEntry(
entry_type=ContestEntryType.COUNT,
user=user_with_wallet,
diff --git a/tests/managers/thl/test_product.py b/tests/managers/thl/test_product.py
index 81e0122..8d72fa5 100644
--- a/tests/managers/thl/test_product.py
+++ b/tests/managers/thl/test_product.py
@@ -203,16 +203,16 @@ class TestProductManager:
def test_get_by_uuid1(
self,
product_manager: ProductManager,
- team: Team,
+ gr_team: Team,
product: Product,
product_factory: Callable[..., Product],
):
- p1 = product_factory(team=team)
+ p1 = product_factory(team=gr_team)
instance = product_manager.get_by_uuid(product_uuid=p1.uuid)
assert instance.id == p1.id
# No Team and no user_create_config
- assert instance.team_id == team.uuid
+ assert instance.team_id == gr_team.uuid
# user_create_config can't be None, so ensure the default was set.
assert isinstance(instance.user_create_config, UserCreateConfig)
diff --git a/tests/managers/thl/test_session_manager.py b/tests/managers/thl/test_session_manager.py
index 67a802e..60edcb9 100644
--- a/tests/managers/thl/test_session_manager.py
+++ b/tests/managers/thl/test_session_manager.py
@@ -118,20 +118,20 @@ class TestSessionManagerFilter:
self,
product_factory: Callable[..., Product],
user_factory: Callable[..., User],
- team: Team,
+ gr_team: Team,
session_manager: SessionManager,
utc_hour_ago: datetime,
thl_web_rr: PostgresConfig,
):
- p1 = product_factory(team=team)
+ p1 = product_factory(team=gr_team)
for _ in range(5):
u = user_factory(product=p1)
session_manager.create(started=utc_hour_ago, user=u, uuid_id=uuid4().hex)
- team.prefetch_products(thl_pg_config=thl_web_rr)
- assert len(team.product_uuids) == 1
- res = session_manager.filter(product_uuids=team.product_uuids)
+ gr_team.prefetch_products(thl_pg_config=thl_web_rr)
+ assert len(gr_team.product_uuids) == 1
+ res = session_manager.filter(product_uuids=gr_team.product_uuids)
assert len(res) == 5
def test_business(