From d19438ec4ccbbe4415c286c9ae89e3e5706ac553 Mon Sep 17 00:00:00 2001 From: Max Nanis Date: Mon, 31 Aug 2026 19:20:32 -0700 Subject: TYPE_CHECKING on models + managers --- generalresearch/config.py | 2 + generalresearch/grliq/managers/forensic_data.py | 10 +- generalresearch/grliq/models/forensic_data.py | 8 +- generalresearch/managers/base.py | 8 +- generalresearch/managers/cint/profiling.py | 5 +- generalresearch/managers/criteria.py | 5 +- generalresearch/managers/dynata/profiling.py | 5 +- generalresearch/managers/events.py | 10 +- generalresearch/managers/gr/authentication.py | 10 +- generalresearch/managers/gr/business.py | 24 +- generalresearch/managers/gr/team.py | 11 +- generalresearch/managers/innovate/profiling.py | 5 +- generalresearch/managers/leaderboard/tasks.py | 5 +- generalresearch/managers/lucid/profiling.py | 8 +- generalresearch/managers/marketplace/user_pid.py | 5 +- generalresearch/managers/morning/profiling.py | 5 +- generalresearch/managers/network/label.py | 11 +- generalresearch/managers/network/mtr.py | 6 +- generalresearch/managers/network/nmap.py | 6 +- generalresearch/managers/network/rdns.py | 6 +- generalresearch/managers/network/tool_run.py | 10 +- generalresearch/managers/pollfish/profiling.py | 5 +- generalresearch/managers/precision/profiling.py | 5 +- generalresearch/managers/prodege/profiling.py | 5 +- generalresearch/managers/repdata/profiling.py | 5 +- generalresearch/managers/repdata/survey.py | 5 +- generalresearch/managers/sago/profiling.py | 5 +- generalresearch/managers/spectrum/profiling.py | 5 +- generalresearch/managers/survey.py | 5 +- generalresearch/managers/thl/buyer.py | 7 +- generalresearch/managers/thl/cashout_method.py | 12 +- generalresearch/managers/thl/category.py | 10 +- generalresearch/managers/thl/contest_manager.py | 28 +- generalresearch/managers/thl/ipinfo.py | 13 +- .../managers/thl/ledger_manager/conditions.py | 17 +- .../managers/thl/ledger_manager/ledger.py | 13 +- .../managers/thl/ledger_manager/thl_ledger.py | 33 +- generalresearch/managers/thl/payout.py | 20 +- generalresearch/managers/thl/product.py | 13 +- generalresearch/managers/thl/profiling/uqa.py | 5 +- generalresearch/managers/thl/profiling/user_upk.py | 12 +- generalresearch/managers/thl/session.py | 29 +- generalresearch/managers/thl/survey.py | 8 +- generalresearch/managers/thl/survey_penalty.py | 23 +- generalresearch/managers/thl/task_adjustment.py | 11 +- generalresearch/managers/thl/user_compensate.py | 12 +- .../managers/thl/user_manager/__init__.py | 5 +- .../thl/user_manager/mysql_user_manager.py | 7 +- .../managers/thl/user_manager/rate_limit.py | 5 +- .../managers/thl/user_manager/user_manager.py | 7 +- generalresearch/managers/thl/userhealth.py | 13 +- generalresearch/managers/thl/wall.py | 21 +- generalresearch/managers/thl/wallet/__init__.py | 36 ++- generalresearch/managers/thl/wallet/approve.py | 18 +- generalresearch/managers/thl/wallet/tango.py | 21 +- generalresearch/models/admin/request.py | 5 +- generalresearch/models/cint/question.py | 4 +- generalresearch/models/cint/survey.py | 16 +- generalresearch/models/cint/task_collection.py | 6 +- generalresearch/models/dynata/question.py | 6 +- generalresearch/models/dynata/survey.py | 21 +- generalresearch/models/dynata/task_collection.py | 6 +- generalresearch/models/events.py | 27 +- generalresearch/models/gr/authentication.py | 6 +- generalresearch/models/gr/business.py | 53 ++-- generalresearch/models/gr/team.py | 67 ++-- generalresearch/models/innovate/question.py | 2 +- generalresearch/models/innovate/survey.py | 21 +- generalresearch/models/innovate/task_collection.py | 6 +- generalresearch/models/legacy/bucket.py | 14 +- generalresearch/models/legacy/offerwall.py | 38 ++- generalresearch/models/legacy/questions.py | 12 +- generalresearch/models/lucid/question.py | 2 +- generalresearch/models/lucid/survey.py | 18 +- generalresearch/models/morning/question.py | 6 +- generalresearch/models/morning/survey.py | 26 +- generalresearch/models/morning/task_collection.py | 6 +- generalresearch/models/network/label.py | 9 +- generalresearch/models/network/mtr/command.py | 2 +- generalresearch/models/network/mtr/execute.py | 12 +- generalresearch/models/network/mtr/parser.py | 5 +- generalresearch/models/network/mtr/result.py | 9 +- generalresearch/models/network/nmap/command.py | 2 +- generalresearch/models/network/nmap/execute.py | 12 +- generalresearch/models/network/nmap/result.py | 6 +- generalresearch/models/network/rdns/command.py | 2 +- generalresearch/models/network/rdns/execute.py | 5 +- generalresearch/models/network/rdns/parser.py | 5 +- generalresearch/models/network/rdns/result.py | 4 +- generalresearch/models/network/tool_run.py | 31 +- generalresearch/models/network/tool_run_command.py | 6 +- generalresearch/models/precision/question.py | 2 +- generalresearch/models/precision/survey.py | 21 +- .../models/precision/task_collection.py | 6 +- generalresearch/models/prodege/question.py | 4 +- generalresearch/models/prodege/survey.py | 24 +- generalresearch/models/prodege/task_collection.py | 6 +- generalresearch/models/repdata/question.py | 2 +- generalresearch/models/repdata/survey.py | 14 +- generalresearch/models/repdata/task_collection.py | 6 +- generalresearch/models/sago/question.py | 2 +- generalresearch/models/sago/survey.py | 20 +- generalresearch/models/sago/task_collection.py | 6 +- generalresearch/models/spectrum/question.py | 4 +- generalresearch/models/spectrum/survey.py | 18 +- generalresearch/models/spectrum/task_collection.py | 6 +- generalresearch/models/thl/category.py | 5 +- generalresearch/models/thl/contest/__init__.py | 10 +- generalresearch/models/thl/contest/contest.py | 12 +- .../models/thl/contest/contest_entry.py | 10 +- generalresearch/models/thl/contest/leaderboard.py | 10 +- generalresearch/models/thl/contest/milestone.py | 6 +- generalresearch/models/thl/contest/raffle.py | 12 +- generalresearch/models/thl/demographics.py | 3 +- generalresearch/models/thl/finance.py | 4 +- generalresearch/models/thl/ipinfo.py | 11 +- generalresearch/models/thl/leaderboard.py | 7 +- generalresearch/models/thl/ledger.py | 19 +- generalresearch/models/thl/offerwall/base.py | 26 +- generalresearch/models/thl/offerwall/cache.py | 19 +- generalresearch/models/thl/payout.py | 25 +- generalresearch/models/thl/product.py | 16 +- .../models/thl/profiling/marketplace.py | 21 +- generalresearch/models/thl/profiling/question.py | 17 +- .../models/thl/profiling/upk_property.py | 7 +- .../models/thl/profiling/upk_question.py | 6 +- .../models/thl/profiling/upk_question_answer.py | 14 +- generalresearch/models/thl/profiling/user_info.py | 15 +- .../models/thl/profiling/user_question_answer.py | 13 +- generalresearch/models/thl/report_task.py | 5 +- generalresearch/models/thl/session.py | 23 +- generalresearch/models/thl/soft_pair.py | 12 +- generalresearch/models/thl/survey/__init__.py | 21 +- generalresearch/models/thl/survey/buyer.py | 14 +- generalresearch/models/thl/survey/model.py | 25 +- generalresearch/models/thl/survey/penalty.py | 13 +- .../models/thl/survey/task_collection.py | 4 +- generalresearch/models/thl/task_adjustment.py | 8 +- generalresearch/models/thl/task_status.py | 33 +- generalresearch/models/thl/user.py | 12 +- generalresearch/models/thl/user_iphistory.py | 17 +- generalresearch/models/thl/user_profile.py | 10 +- generalresearch/models/thl/user_quality_event.py | 10 +- generalresearch/models/thl/user_streak.py | 5 +- .../models/thl/wallet/cashout_method.py | 23 +- generalresearch/models/thl/wallet/payout.py | 12 +- generalresearch/models/thl/wallet/user_wallet.py | 7 +- generalresearch/wall_status_codes/cint.py | 6 +- test_utils/conftest.py | 2 +- test_utils/managers/gr/conftest.py | 48 ++- test_utils/models/conftest.py | 37 --- test_utils/models/gr/conftest.py | 56 +++- tests/models/gr/test_business.py | 352 +++++++++++---------- 153 files changed, 1319 insertions(+), 947 deletions(-) diff --git a/generalresearch/config.py b/generalresearch/config.py index 73af565..2777aa4 100644 --- a/generalresearch/config.py +++ b/generalresearch/config.py @@ -53,6 +53,8 @@ class GRLBaseSettings(BaseSettings): testing_postgres_user: str | None = Field(default=None) testing_postgres_pass: str | None = Field(default=None) + testing_redis: InternalHostname | None = Field(default=None) + git_creds: str | None = Field(default=None) # --- diff --git a/generalresearch/grliq/managers/forensic_data.py b/generalresearch/grliq/managers/forensic_data.py index c1eac37..0f8534c 100644 --- a/generalresearch/grliq/managers/forensic_data.py +++ b/generalresearch/grliq/managers/forensic_data.py @@ -2,7 +2,7 @@ from __future__ import annotations from collections.abc import Collection from datetime import datetime -from typing import Any +from typing import TYPE_CHECKING, Any from psycopg import sql from pydantic import NonNegativeInt, PositiveInt @@ -14,9 +14,11 @@ from generalresearch.grliq.models.forensic_result import ( GrlIqForensicCategoryResult, Phase, ) -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.thl.user import User -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.user import User + from generalresearch.pg_helper import PostgresConfig class GrlIqDataManager: diff --git a/generalresearch/grliq/models/forensic_data.py b/generalresearch/grliq/models/forensic_data.py index 69b1760..6a07774 100644 --- a/generalresearch/grliq/models/forensic_data.py +++ b/generalresearch/grliq/models/forensic_data.py @@ -6,7 +6,7 @@ from collections import Counter from datetime import UTC, datetime, timedelta from enum import StrEnum from functools import cached_property -from typing import Annotated, Any, Literal, Self +from typing import TYPE_CHECKING, Annotated, Any, Literal, Self from uuid import uuid4 import pycountry @@ -53,8 +53,10 @@ from generalresearch.models.custom_types import ( IPvAnyAddressStr, UUIDStr, ) -from generalresearch.models.thl.ipinfo import GeoIPInformation -from generalresearch.models.thl.session import Session + +if TYPE_CHECKING: + from generalresearch.models.thl.ipinfo import GeoIPInformation + from generalresearch.models.thl.session import Session fake = Faker() diff --git a/generalresearch/managers/base.py b/generalresearch/managers/base.py index ba42e9e..2227d21 100644 --- a/generalresearch/managers/base.py +++ b/generalresearch/managers/base.py @@ -3,10 +3,12 @@ from __future__ import annotations from collections.abc import Collection from contextlib import nullcontext from enum import Enum +from typing import TYPE_CHECKING -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig -from generalresearch.sql_helper import SqlHelper +if TYPE_CHECKING: + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig + from generalresearch.sql_helper import SqlHelper class Permission(int, Enum): diff --git a/generalresearch/managers/cint/profiling.py b/generalresearch/managers/cint/profiling.py index 9216aa5..c550632 100644 --- a/generalresearch/managers/cint/profiling.py +++ b/generalresearch/managers/cint/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.cint.question import CintQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/criteria.py b/generalresearch/managers/criteria.py index b8ae6ac..760afd3 100644 --- a/generalresearch/managers/criteria.py +++ b/generalresearch/managers/criteria.py @@ -3,11 +3,14 @@ from __future__ import annotations from abc import ABC from collections.abc import Collection from datetime import UTC, datetime +from typing import TYPE_CHECKING from more_itertools import chunked from generalresearch.managers.base import SqlManager -from generalresearch.models.thl.survey import MarketplaceCondition + +if TYPE_CHECKING: + from generalresearch.models.thl.survey import MarketplaceCondition DB_FIELDS = [ "hash", diff --git a/generalresearch/managers/dynata/profiling.py b/generalresearch/managers/dynata/profiling.py index 661bdad..b76ecc7 100644 --- a/generalresearch/managers/dynata/profiling.py +++ b/generalresearch/managers/dynata/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.dynata.question import DynataQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/events.py b/generalresearch/managers/events.py index 6779104..c43a020 100644 --- a/generalresearch/managers/events.py +++ b/generalresearch/managers/events.py @@ -13,14 +13,12 @@ from redis.client import PubSub, Redis from generalresearch.incite.base import LOG from generalresearch.managers.base import RedisManager from generalresearch.models import Source -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.events import ( AggregateBySource, EventEnvelope, EventMessage, EventType, MaxGaugeBySource, - ServerToClientMessage, ServerToClientMessageAdapter, SessionEnterPayload, SessionFinishPayload, @@ -30,11 +28,15 @@ from generalresearch.models.events import ( TaskStatsSnapshot, ) from generalresearch.models.thl.definitions import Status -from generalresearch.models.thl.session import Session, Wall -from generalresearch.models.thl.user import User if TYPE_CHECKING: from influxdb import InfluxDBClient + + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.events import ServerToClientMessage + from generalresearch.models.thl.session import Session, Wall + from generalresearch.models.thl.user import User + else: InfluxDBClient = object diff --git a/generalresearch/managers/gr/authentication.py b/generalresearch/managers/gr/authentication.py index 851b88a..ca56467 100644 --- a/generalresearch/managers/gr/authentication.py +++ b/generalresearch/managers/gr/authentication.py @@ -10,14 +10,14 @@ from psycopg import sql from pydantic import AnyHttpUrl, PositiveInt from generalresearch.managers.base import PostgresManager, PostgresManagerWithRedis -from generalresearch.models.custom_types import UUIDStr -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig - -LOG = logging.getLogger("gr") if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr from generalresearch.models.gr.authentication import GRToken, GRUser + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig + +LOG = logging.getLogger("gr") class GRUserManager(PostgresManagerWithRedis): diff --git a/generalresearch/managers/gr/business.py b/generalresearch/managers/gr/business.py index 4da0e7f..ef26f30 100644 --- a/generalresearch/managers/gr/business.py +++ b/generalresearch/managers/gr/business.py @@ -11,14 +11,16 @@ from generalresearch.managers.base import ( PostgresManager, PostgresManagerWithRedis, ) -from generalresearch.models.custom_types import UUIDStr +from generalresearch.models.gr.business import ( + Business, + BusinessBankAccount, + BusinessType, +) if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr from generalresearch.models.gr.business import ( - Business, BusinessAddress, - BusinessBankAccount, - BusinessType, TransferMethod, ) from generalresearch.models.gr.team import Team @@ -36,8 +38,6 @@ class BusinessBankAccountManager(PostgresManager): iban: str | None = None, swift: str | None = None, ) -> BusinessBankAccount: - from generalresearch.models.gr.business import BusinessBankAccount - ba = BusinessBankAccount.model_validate( { "business_id": business_id, @@ -73,7 +73,6 @@ class BusinessBankAccountManager(PostgresManager): return ba def get_by_business_id(self, business_id: UUIDStr) -> list[BusinessBankAccount]: - from generalresearch.models.gr.business import BusinessBankAccount with self.pg_config.make_connection() as conn, conn.cursor() as c: c.execute( @@ -192,11 +191,7 @@ class BusinessManager(PostgresManagerWithRedis): """ Behavior: does this raise on duplicate? """ - from generalresearch.models.gr.business import ( - Business, - BusinessType, - ) - + # Business.model_rebuild() business = Business.model_validate( { "uuid": uuid or uuid4().hex, @@ -281,7 +276,6 @@ class BusinessManager(PostgresManagerWithRedis): res = c.fetchall() response = [] - from generalresearch.models.gr.business import Business for i in res: # i["contact"] = BusinessContact.model_validate(i) @@ -370,8 +364,6 @@ class BusinessManager(PostgresManagerWithRedis): self, business_uuid: UUIDStr, ) -> Business | None: - from generalresearch.models.gr.business import Business - assert UUID(hex=business_uuid).hex == business_uuid with self.pg_config.make_connection() as conn, conn.cursor() as c: @@ -397,8 +389,6 @@ class BusinessManager(PostgresManagerWithRedis): return Business.model_validate(data) def get_by_id(self, business_id: PositiveInt) -> Business | None: - from generalresearch.models.gr.business import Business - assert isinstance(business_id, int) with self.pg_config.make_connection() as conn, conn.cursor() as c: diff --git a/generalresearch/managers/gr/team.py b/generalresearch/managers/gr/team.py index d04370b..3283467 100644 --- a/generalresearch/managers/gr/team.py +++ b/generalresearch/managers/gr/team.py @@ -11,15 +11,16 @@ from generalresearch.managers.base import ( PostgresManager, PostgresManagerWithRedis, ) -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.gr.team import Membership, MembershipPrivilege +from generalresearch.models.gr.team import ( + Membership, + MembershipPrivilege, +) if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr from generalresearch.models.gr.authentication import GRUser from generalresearch.models.gr.business import Business - from generalresearch.models.gr.team import ( - Team, - ) + from generalresearch.models.gr.team import Team class MembershipManager(PostgresManager): diff --git a/generalresearch/managers/innovate/profiling.py b/generalresearch/managers/innovate/profiling.py index bfa2685..0f32999 100644 --- a/generalresearch/managers/innovate/profiling.py +++ b/generalresearch/managers/innovate/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.innovate.question import InnovateQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/leaderboard/tasks.py b/generalresearch/managers/leaderboard/tasks.py index 072a1aa..9e8dc9f 100644 --- a/generalresearch/managers/leaderboard/tasks.py +++ b/generalresearch/managers/leaderboard/tasks.py @@ -1,4 +1,5 @@ import logging +from typing import TYPE_CHECKING from redis import Redis @@ -7,7 +8,9 @@ from generalresearch.models.thl.leaderboard import ( LeaderboardCode, LeaderboardFrequency, ) -from generalresearch.models.thl.session import Session + +if TYPE_CHECKING: + from generalresearch.models.thl.session import Session logger = logging.getLogger() diff --git a/generalresearch/managers/lucid/profiling.py b/generalresearch/managers/lucid/profiling.py index fdd2d52..5937a59 100644 --- a/generalresearch/managers/lucid/profiling.py +++ b/generalresearch/managers/lucid/profiling.py @@ -2,12 +2,16 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from pydantic import ValidationError -from generalresearch.decorators import LOG from generalresearch.models.lucid.question import LucidQuestion, LucidQuestionType -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper + +from generalresearch.decorators import LOG def get_profiling_library( diff --git a/generalresearch/managers/marketplace/user_pid.py b/generalresearch/managers/marketplace/user_pid.py index 15d8a19..fe24d38 100644 --- a/generalresearch/managers/marketplace/user_pid.py +++ b/generalresearch/managers/marketplace/user_pid.py @@ -2,11 +2,14 @@ from __future__ import annotations from abc import ABC from collections.abc import Collection +from typing import TYPE_CHECKING from uuid import UUID from generalresearch.managers.base import SqlManager from generalresearch.models import Source -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper class UserPidManager(SqlManager, ABC): diff --git a/generalresearch/managers/morning/profiling.py b/generalresearch/managers/morning/profiling.py index 01f99f3..7335e6b 100644 --- a/generalresearch/managers/morning/profiling.py +++ b/generalresearch/managers/morning/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.morning.question import MorningQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/network/label.py b/generalresearch/managers/network/label.py index f0ba9f7..cec59ad 100644 --- a/generalresearch/managers/network/label.py +++ b/generalresearch/managers/network/label.py @@ -2,6 +2,7 @@ from __future__ import annotations from collections.abc import Collection from datetime import UTC, datetime, timedelta +from typing import TYPE_CHECKING from psycopg import sql from pydantic import IPvAnyNetwork, TypeAdapter @@ -9,10 +10,16 @@ from pydantic import IPvAnyNetwork, TypeAdapter from generalresearch.managers.base import PostgresManager from generalresearch.models.custom_types import ( AwareDatetimeISO, - IPvAnyAddressStr, IPvAnyNetworkStr, ) -from generalresearch.models.network.label import IPLabel, IPLabelKind, IPLabelSource +from generalresearch.models.network.label import IPLabel + +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + IPvAnyNetworkStr, + ) + from generalresearch.models.network.label import IPLabelKind, IPLabelSource class IPLabelManager(PostgresManager): diff --git a/generalresearch/managers/network/mtr.py b/generalresearch/managers/network/mtr.py index 179b8a9..7b79d96 100644 --- a/generalresearch/managers/network/mtr.py +++ b/generalresearch/managers/network/mtr.py @@ -1,9 +1,13 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from psycopg import Cursor, sql from generalresearch.managers.base import PostgresManager -from generalresearch.models.network.tool_run import MTRRun + +if TYPE_CHECKING: + from generalresearch.models.network.tool_run import MTRRun class MTRRunManager(PostgresManager): diff --git a/generalresearch/managers/network/nmap.py b/generalresearch/managers/network/nmap.py index 574bce1..96c6009 100644 --- a/generalresearch/managers/network/nmap.py +++ b/generalresearch/managers/network/nmap.py @@ -1,9 +1,13 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from psycopg import Cursor, sql from generalresearch.managers.base import PostgresManager -from generalresearch.models.network.tool_run import NmapRun + +if TYPE_CHECKING: + from generalresearch.models.network.tool_run import NmapRun class NmapRunManager(PostgresManager): diff --git a/generalresearch/managers/network/rdns.py b/generalresearch/managers/network/rdns.py index 95a1381..1800364 100644 --- a/generalresearch/managers/network/rdns.py +++ b/generalresearch/managers/network/rdns.py @@ -1,9 +1,13 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from psycopg import Cursor from generalresearch.managers.base import PostgresManager -from generalresearch.models.network.tool_run import RDNSRun + +if TYPE_CHECKING: + from generalresearch.models.network.tool_run import RDNSRun class RDNSRunManager(PostgresManager): diff --git a/generalresearch/managers/network/tool_run.py b/generalresearch/managers/network/tool_run.py index 73afc13..ec06305 100644 --- a/generalresearch/managers/network/tool_run.py +++ b/generalresearch/managers/network/tool_run.py @@ -1,10 +1,11 @@ from __future__ import annotations from collections.abc import Collection +from typing import TYPE_CHECKING from psycopg import Cursor, sql -from generalresearch.managers.base import Permission, PostgresManager +from generalresearch.managers.base import PostgresManager from generalresearch.managers.network.mtr import MTRRunManager from generalresearch.managers.network.nmap import NmapRunManager from generalresearch.managers.network.rdns import RDNSRunManager @@ -13,10 +14,13 @@ from generalresearch.models.network.tool_run import ( MTRRun, NmapRun, RDNSRun, - ToolName, ToolRun, ) -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.managers.base import Permission + from generalresearch.models.network.tool_run import ToolName + from generalresearch.pg_helper import PostgresConfig class ToolRunManager(PostgresManager): diff --git a/generalresearch/managers/pollfish/profiling.py b/generalresearch/managers/pollfish/profiling.py index daf529b..43afd30 100644 --- a/generalresearch/managers/pollfish/profiling.py +++ b/generalresearch/managers/pollfish/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.pollfish.question import PollfishQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/precision/profiling.py b/generalresearch/managers/precision/profiling.py index 449fd25..813542c 100644 --- a/generalresearch/managers/precision/profiling.py +++ b/generalresearch/managers/precision/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.precision.question import PrecisionQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/prodege/profiling.py b/generalresearch/managers/prodege/profiling.py index 54a7b57..cf77fca 100644 --- a/generalresearch/managers/prodege/profiling.py +++ b/generalresearch/managers/prodege/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.prodege.question import ProdegeQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/repdata/profiling.py b/generalresearch/managers/repdata/profiling.py index 4b97abd..ec30d78 100644 --- a/generalresearch/managers/repdata/profiling.py +++ b/generalresearch/managers/repdata/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.repdata.question import RepDataQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/repdata/survey.py b/generalresearch/managers/repdata/survey.py index ab66374..2c3156c 100644 --- a/generalresearch/managers/repdata/survey.py +++ b/generalresearch/managers/repdata/survey.py @@ -3,6 +3,7 @@ from __future__ import annotations import json from collections.abc import Collection from datetime import UTC, datetime +from typing import TYPE_CHECKING import pymysql @@ -11,10 +12,12 @@ from generalresearch.managers.survey import SurveyManager from generalresearch.models.repdata.survey import ( RepDataCondition, RepDataStreamHashed, - RepDataSurvey, RepDataSurveyHashed, ) +if TYPE_CHECKING: + from generalresearch.models.repdata.survey import RepDataSurvey + SURVEY_FIELDS = [ "survey_id", "survey_uuid", diff --git a/generalresearch/managers/sago/profiling.py b/generalresearch/managers/sago/profiling.py index 4f5b2f5..3bbad3f 100644 --- a/generalresearch/managers/sago/profiling.py +++ b/generalresearch/managers/sago/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.sago.question import SagoQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/spectrum/profiling.py b/generalresearch/managers/spectrum/profiling.py index 8a0904a..5de218c 100644 --- a/generalresearch/managers/spectrum/profiling.py +++ b/generalresearch/managers/spectrum/profiling.py @@ -2,9 +2,12 @@ from __future__ import annotations import json from collections.abc import Collection +from typing import TYPE_CHECKING from generalresearch.models.spectrum.question import SpectrumQuestion -from generalresearch.sql_helper import SqlHelper + +if TYPE_CHECKING: + from generalresearch.sql_helper import SqlHelper def get_profiling_library( diff --git a/generalresearch/managers/survey.py b/generalresearch/managers/survey.py index 1f057fb..65dbdd9 100644 --- a/generalresearch/managers/survey.py +++ b/generalresearch/managers/survey.py @@ -1,9 +1,12 @@ from __future__ import annotations from abc import ABC +from typing import TYPE_CHECKING from generalresearch.managers.base import SqlManager -from generalresearch.models.thl.survey import MarketplaceTask + +if TYPE_CHECKING: + from generalresearch.models.thl.survey import MarketplaceTask class SurveyManager(SqlManager, ABC): diff --git a/generalresearch/managers/thl/buyer.py b/generalresearch/managers/thl/buyer.py index 5aa2a01..1e20e2f 100644 --- a/generalresearch/managers/thl/buyer.py +++ b/generalresearch/managers/thl/buyer.py @@ -2,11 +2,14 @@ from __future__ import annotations from collections.abc import Collection from datetime import UTC, datetime +from typing import TYPE_CHECKING from generalresearch.managers.base import Permission, PostgresManager -from generalresearch.models import Source from generalresearch.models.thl.survey.buyer import Buyer -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.pg_helper import PostgresConfig class BuyerManager(PostgresManager): diff --git a/generalresearch/managers/thl/cashout_method.py b/generalresearch/managers/thl/cashout_method.py index f45e692..e701da3 100644 --- a/generalresearch/managers/thl/cashout_method.py +++ b/generalresearch/managers/thl/cashout_method.py @@ -3,20 +3,24 @@ from __future__ import annotations from collections.abc import Collection from copy import copy from datetime import UTC, datetime -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import UUID, uuid4 from pydantic import NonNegativeInt from generalresearch.managers.base import PostgresManager -from generalresearch.models.thl.user import User from generalresearch.models.thl.wallet import PayoutType from generalresearch.models.thl.wallet.cashout_method import ( - CashMailCashoutMethodData, CashoutMethod, - PaypalCashoutMethodData, ) +if TYPE_CHECKING: + from generalresearch.models.thl.user import User + from generalresearch.models.thl.wallet.cashout_method import ( + CashMailCashoutMethodData, + PaypalCashoutMethodData, + ) + class CashoutMethodManager(PostgresManager): diff --git a/generalresearch/managers/thl/category.py b/generalresearch/managers/thl/category.py index e8a6aa6..e6a091b 100644 --- a/generalresearch/managers/thl/category.py +++ b/generalresearch/managers/thl/category.py @@ -1,11 +1,15 @@ from __future__ import annotations from collections.abc import Collection +from typing import TYPE_CHECKING -from generalresearch.managers.base import Permission, PostgresManager -from generalresearch.models.custom_types import UUIDStr +from generalresearch.managers.base import PostgresManager from generalresearch.models.thl.category import Category -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.managers.base import Permission + from generalresearch.models.custom_types import UUIDStr + from generalresearch.pg_helper import PostgresConfig class CategoryManager(PostgresManager): diff --git a/generalresearch/managers/thl/contest_manager.py b/generalresearch/managers/thl/contest_manager.py index 64206e1..3f85d31 100644 --- a/generalresearch/managers/thl/contest_manager.py +++ b/generalresearch/managers/thl/contest_manager.py @@ -2,7 +2,7 @@ from __future__ import annotations from collections.abc import Collection from datetime import UTC, datetime -from typing import Any, Literal, cast +from typing import TYPE_CHECKING, Any, Literal, cast from uuid import UUID import redis @@ -10,21 +10,10 @@ from pydantic import NonNegativeInt, PositiveInt from redis import Redis from generalresearch.managers.base import PostgresManager -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) -from generalresearch.managers.thl.user_manager.user_manager import ( - UserManager, -) -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.thl.contest import ( ContestPrize, ContestWinner, ) -from generalresearch.models.thl.contest.contest import ( - Contest, - ContestUserView, -) from generalresearch.models.thl.contest.definitions import ( ContestStatus, ContestType, @@ -41,7 +30,6 @@ from generalresearch.models.thl.contest.leaderboard import ( LeaderboardContestUserView, ) from generalresearch.models.thl.contest.milestone import ( - ContestEntryTrigger, MilestoneContest, MilestoneEntry, MilestoneUserView, @@ -54,6 +42,20 @@ from generalresearch.models.thl.contest.raffle import ( ) from generalresearch.models.thl.user import User +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.managers.thl.user_manager.user_manager import ( + UserManager, + ) + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.contest.contest import ( + Contest, + ContestUserView, + ) + from generalresearch.models.thl.contest.milestone import ContestEntryTrigger + CONTEST_SELECT = """ c.id, c.uuid::uuid, diff --git a/generalresearch/managers/thl/ipinfo.py b/generalresearch/managers/thl/ipinfo.py index 90757a2..93914c3 100644 --- a/generalresearch/managers/thl/ipinfo.py +++ b/generalresearch/managers/thl/ipinfo.py @@ -3,6 +3,7 @@ from __future__ import annotations import ipaddress from collections.abc import Collection from decimal import Decimal +from typing import TYPE_CHECKING import faker from grip_client.enums import AccessType @@ -14,17 +15,19 @@ from generalresearch.managers.base import ( PostgresManager, PostgresManagerWithRedis, ) -from generalresearch.models.custom_types import ( - CountryISOLike, - IPvAnyAddressStr, -) from generalresearch.models.thl.ipinfo import ( GeoIPInformation, IPGeoname, IPInformation, normalize_ip, ) -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + CountryISOLike, + IPvAnyAddressStr, + ) + from generalresearch.pg_helper import PostgresConfig fake = faker.Faker() diff --git a/generalresearch/managers/thl/ledger_manager/conditions.py b/generalresearch/managers/thl/ledger_manager/conditions.py index b2fd465..7dd3021 100644 --- a/generalresearch/managers/thl/ledger_manager/conditions.py +++ b/generalresearch/managers/thl/ledger_manager/conditions.py @@ -7,22 +7,23 @@ from typing import TYPE_CHECKING from generalresearch.config import JAMES_BILLINGS_BPID, JAMES_BILLINGS_TX_CUTOFF from generalresearch.currency import USDCent -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.thl.product import Product -from generalresearch.models.thl.session import Session, Wall -from generalresearch.models.thl.user import User - -logging.basicConfig() -logger = logging.getLogger("LedgerManager") -logger.setLevel(logging.INFO) if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.ledger import ( LedgerManager, ) from generalresearch.managers.thl.ledger_manager.thl_ledger import ( ThlLedgerManager, ) + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.product import Product + from generalresearch.models.thl.session import Session, Wall + from generalresearch.models.thl.user import User + +logging.basicConfig() +logger = logging.getLogger("LedgerManager") +logger.setLevel(logging.INFO) def generate_condition_mp_payment(wall: Wall) -> Callable[..., bool]: diff --git a/generalresearch/managers/thl/ledger_manager/ledger.py b/generalresearch/managers/thl/ledger_manager/ledger.py index a5263f0..6cb4b28 100644 --- a/generalresearch/managers/thl/ledger_manager/ledger.py +++ b/generalresearch/managers/thl/ledger_manager/ledger.py @@ -4,7 +4,7 @@ import logging from collections import defaultdict from collections.abc import Callable, Collection from datetime import UTC, datetime, timedelta -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import UUID import redis @@ -28,16 +28,19 @@ from generalresearch.managers.thl.ledger_manager.exceptions import ( LedgerTransactionFlagAlreadyExistsError, LedgerTransactionReleaseLockError, ) -from generalresearch.models.custom_types import UUIDStr, check_valid_uuid +from generalresearch.models.custom_types import check_valid_uuid from generalresearch.models.thl.ledger import ( LedgerAccount, LedgerEntry, LedgerTransaction, - UserLedgerTransactionType, UserLedgerTransactionTypesSummary, ) -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig + +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.ledger import UserLedgerTransactionType + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig logging.basicConfig() logger = logging.getLogger("LedgerManager") diff --git a/generalresearch/managers/thl/ledger_manager/thl_ledger.py b/generalresearch/managers/thl/ledger_manager/thl_ledger.py index ded6518..7aed619 100644 --- a/generalresearch/managers/thl/ledger_manager/thl_ledger.py +++ b/generalresearch/managers/thl/ledger_manager/thl_ledger.py @@ -29,15 +29,12 @@ from generalresearch.managers.thl.ledger_manager.conditions import ( from generalresearch.managers.thl.ledger_manager.ledger import ( LedgerManager, ) -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.thl.contest.contest import Contest from generalresearch.models.thl.contest.definitions import ( ContestPrizeKind, ContestType, ) from generalresearch.models.thl.contest.milestone import MilestoneContest from generalresearch.models.thl.contest.raffle import ( - ContestEntry, ContestEntryType, RaffleContest, ) @@ -53,14 +50,20 @@ from generalresearch.models.thl.ledger import ( from generalresearch.models.thl.ledger import ( TransactionMetadataColumns as tmc, ) -from generalresearch.models.thl.payout import UserPayoutEvent from generalresearch.models.thl.product import Product -from generalresearch.models.thl.session import Session, Status, Wall -from generalresearch.models.thl.user import User +from generalresearch.models.thl.session import Status from generalresearch.models.thl.wallet import PayoutType if TYPE_CHECKING: - from generalresearch.models.thl.contest.contest import ContestWinner + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.contest.contest import Contest, ContestWinner + from generalresearch.models.thl.contest.raffle import ( + ContestEntry, + ) + from generalresearch.models.thl.ledger import LedgerTransaction + from generalresearch.models.thl.payout import UserPayoutEvent + from generalresearch.models.thl.session import Session, Wall + from generalresearch.models.thl.user import User logging.basicConfig() logger = logging.getLogger("LedgerManager") @@ -663,9 +666,7 @@ class ThlLedgerManager(LedgerManager): ) else: - logger.info( - "create_transaction_bp_adjustment. No transactions needed." - ) + logger.info("create_transaction_bp_adjustment. No transactions needed.") return None else: new_bp_payout = new_payout @@ -735,9 +736,7 @@ class ThlLedgerManager(LedgerManager): ) else: - logger.info( - "create_transaction_bp_adjustment. No transactions needed." - ) + logger.info("create_transaction_bp_adjustment. No transactions needed.") return None logger.info(entries) @@ -796,9 +795,7 @@ class ThlLedgerManager(LedgerManager): if skip_one_per_day_check or skip_wallet_balance_check: skip_flag_check = True - assert ( - datetime.now(tz=UTC) > created - ), "created cannot be in the future" + assert datetime.now(tz=UTC) > created, "created cannot be in the future" f = lambda: self.create_tx_bp_payout_( product=product, amount=amount, @@ -902,9 +899,7 @@ class ThlLedgerManager(LedgerManager): :param skip_flag_check: If True, we skip the flag check to allow for retry of a failed previous call. """ - assert ( - datetime.now(tz=UTC) > created - ), "created cannot be in the future" + assert datetime.now(tz=UTC) > created, "created cannot be in the future" assert isinstance(amount, int) assert isinstance(amount, USDCent) diff --git a/generalresearch/managers/thl/payout.py b/generalresearch/managers/thl/payout.py index f50e0d2..2914ba4 100644 --- a/generalresearch/managers/thl/payout.py +++ b/generalresearch/managers/thl/payout.py @@ -2,7 +2,7 @@ from __future__ import annotations from collections.abc import Collection from datetime import UTC, datetime -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import uuid4 import numpy as np @@ -19,16 +19,9 @@ from generalresearch.managers.base import ( from generalresearch.managers.thl.ledger_manager.exceptions import ( LedgerTransactionConditionFailedError, ) -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) -from generalresearch.managers.thl.product import ProductManager -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.models.gr.business import Business from generalresearch.models.thl.definitions import PayoutStatus from generalresearch.models.thl.ledger import ( Direction, - LedgerAccount, OrderBy, ) from generalresearch.models.thl.payout import ( @@ -38,13 +31,22 @@ from generalresearch.models.thl.payout import ( PayoutEvent, UserPayoutEvent, ) -from generalresearch.models.thl.product import Product from generalresearch.models.thl.wallet import PayoutType from generalresearch.models.thl.wallet.cashout_method import ( CashMailOrderData, CashoutRequestInfo, ) +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.managers.thl.product import ProductManager + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.gr.business import Business + from generalresearch.models.thl.ledger import LedgerAccount + from generalresearch.models.thl.product import Product + class PayoutEventManager(PostgresManagerWithRedis): """This is the default base Payout Event Manger. It acts as a base for diff --git a/generalresearch/managers/thl/product.py b/generalresearch/managers/thl/product.py index aac2979..535e566 100644 --- a/generalresearch/managers/thl/product.py +++ b/generalresearch/managers/thl/product.py @@ -18,15 +18,15 @@ from sentry_sdk import capture_exception from generalresearch.decorators import LOG from generalresearch.managers.base import ( - Permission, PostgresManager, ) -from generalresearch.models.custom_types import UUIDStr, is_valid_uuid -from generalresearch.pg_helper import PostgresConfig - -logger = logging.getLogger() +from generalresearch.models.custom_types import is_valid_uuid if TYPE_CHECKING: + from generalresearch.managers.base import ( + Permission, + ) + from generalresearch.models.custom_types import UUIDStr from generalresearch.models.thl.product import ( PayoutConfig, Product, @@ -38,6 +38,9 @@ if TYPE_CHECKING: UserHealthConfig, UserWalletConfig, ) + from generalresearch.pg_helper import PostgresConfig + +logger = logging.getLogger() class ProductManager(PostgresManager): diff --git a/generalresearch/managers/thl/profiling/uqa.py b/generalresearch/managers/thl/profiling/uqa.py index fa1747b..d240eea 100644 --- a/generalresearch/managers/thl/profiling/uqa.py +++ b/generalresearch/managers/thl/profiling/uqa.py @@ -3,13 +3,16 @@ from __future__ import annotations import logging from collections.abc import Collection from datetime import UTC, datetime, timedelta +from typing import TYPE_CHECKING from generalresearch.managers.base import PostgresManagerWithRedis from generalresearch.models.thl.profiling.user_question_answer import ( DUMMY_UQA, UserQuestionAnswer, ) -from generalresearch.models.thl.user import User + +if TYPE_CHECKING: + from generalresearch.models.thl.user import User logger = logging.getLogger() diff --git a/generalresearch/managers/thl/profiling/user_upk.py b/generalresearch/managers/thl/profiling/user_upk.py index 6106037..53475b5 100644 --- a/generalresearch/managers/thl/profiling/user_upk.py +++ b/generalresearch/managers/thl/profiling/user_upk.py @@ -4,27 +4,29 @@ import json from collections import defaultdict from collections.abc import Collection from datetime import UTC, datetime, timedelta -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import UUID from psycopg import Cursor from pydantic import PositiveInt from generalresearch.managers.base import ( - Permission, PostgresManagerWithRedis, ) from generalresearch.managers.thl.profiling.schema import UpkSchemaManager from generalresearch.models.thl.profiling.upk_property import ( Cardinality, PropertyType, - UpkProperty, ) from generalresearch.models.thl.profiling.upk_question_answer import ( UpkQuestionAnswer, ) -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig + +if TYPE_CHECKING: + from generalresearch.managers.base import Permission + from generalresearch.models.thl.profiling.upk_property import UpkProperty + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig class UserUpkManager(PostgresManagerWithRedis): diff --git a/generalresearch/managers/thl/session.py b/generalresearch/managers/thl/session.py index 959003c..7f17252 100644 --- a/generalresearch/managers/thl/session.py +++ b/generalresearch/managers/thl/session.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections.abc import Collection from datetime import UTC, datetime, timedelta from decimal import Decimal -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import UUID, uuid4 from faker import Faker @@ -16,14 +16,7 @@ from generalresearch.managers.base import ( PostgresManager, ) from generalresearch.managers.thl.product import ProductManager -from generalresearch.models import DeviceType -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.legacy.bucket import Bucket -from generalresearch.models.thl.definitions import ( - SessionStatusCode2, - Status, - StatusCode1, -) from generalresearch.models.thl.session import ( Session, Wall, @@ -34,6 +27,15 @@ from generalresearch.models.thl.task_status import ( ) from generalresearch.models.thl.user import User +if TYPE_CHECKING: + from generalresearch.models import DeviceType + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.definitions import ( + SessionStatusCode2, + Status, + StatusCode1, + ) + fake = Faker() @@ -190,7 +192,12 @@ class SessionManager(PostgresManager): # re-run model_validate after finished = finished if finished else datetime.now(tz=UTC) session.update( - status=status, status_code_1=status_code_1, status_code_2=status_code_2, finished=finished, payout=payout, user_payout=user_payout + status=status, + status_code_1=status_code_1, + status_code_2=status_code_2, + finished=finished, + payout=payout, + user_payout=user_payout, ) d = session.model_dump_mysql() self.pg_config.execute_write( @@ -446,9 +453,7 @@ class SessionManager(PostgresManager): if started_before or started_after: started_after = started_after or datetime(2017, 1, 1, tzinfo=UTC) started_before = started_before or datetime.now(tz=UTC) - assert ( - started_after.tzinfo == UTC - ), "started_after must be tz-aware as UTC" + assert started_after.tzinfo == UTC, "started_after must be tz-aware as UTC" assert ( started_before.tzinfo == UTC ), "started_before must be tz-aware as UTC" diff --git a/generalresearch/managers/thl/survey.py b/generalresearch/managers/thl/survey.py index 024ad38..eacb345 100644 --- a/generalresearch/managers/thl/survey.py +++ b/generalresearch/managers/thl/survey.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections import defaultdict from collections.abc import Collection from datetime import UTC, datetime -from typing import Any +from typing import TYPE_CHECKING, Any import pandas as pd from more_itertools import chunked @@ -14,12 +14,14 @@ from generalresearch.managers.base import Permission, PostgresManager from generalresearch.managers.thl.buyer import BuyerManager from generalresearch.managers.thl.category import CategoryManager from generalresearch.models import Source -from generalresearch.models.custom_types import SurveyKey from generalresearch.models.thl.survey.model import ( Survey, SurveyStat, ) -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.models.custom_types import SurveyKey + from generalresearch.pg_helper import PostgresConfig class SurveyManager(PostgresManager): diff --git a/generalresearch/managers/thl/survey_penalty.py b/generalresearch/managers/thl/survey_penalty.py index bf914cb..08f8649 100644 --- a/generalresearch/managers/thl/survey_penalty.py +++ b/generalresearch/managers/thl/survey_penalty.py @@ -4,21 +4,24 @@ import json import threading from collections import defaultdict from datetime import timedelta +from typing import TYPE_CHECKING from cachetools import TTLCache, cachedmethod from generalresearch.decorators import LOG from generalresearch.managers.base import RedisManager -from generalresearch.models.custom_types import ( - UUIDStr, -) -from generalresearch.models.thl.survey.penalty import ( - BPSurveyPenalty, - Penalty, - PenaltyListAdapter, - TeamSurveyPenalty, -) -from generalresearch.redis_helper import RedisConfig +from generalresearch.models.thl.survey.penalty import PenaltyListAdapter + +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + UUIDStr, + ) + from generalresearch.models.thl.survey.penalty import ( + BPSurveyPenalty, + Penalty, + TeamSurveyPenalty, + ) + from generalresearch.redis_helper import RedisConfig class SurveyPenaltyManager(RedisManager): diff --git a/generalresearch/managers/thl/task_adjustment.py b/generalresearch/managers/thl/task_adjustment.py index 2d89334..e3f382d 100644 --- a/generalresearch/managers/thl/task_adjustment.py +++ b/generalresearch/managers/thl/task_adjustment.py @@ -4,17 +4,14 @@ import logging from datetime import UTC, datetime from decimal import Decimal from functools import cached_property +from typing import TYPE_CHECKING from generalresearch.managers import parse_order_by from generalresearch.managers.base import ( PostgresManager, ) -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) from generalresearch.managers.thl.session import SessionManager from generalresearch.managers.thl.wall import WallManager -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.thl.definitions import ( Status, WallAdjustedStatus, @@ -24,6 +21,12 @@ from generalresearch.models.thl.session import ( ) from generalresearch.models.thl.task_adjustment import TaskAdjustmentEvent +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.models.custom_types import UUIDStr + logging.basicConfig() logger = logging.getLogger(__name__) diff --git a/generalresearch/managers/thl/user_compensate.py b/generalresearch/managers/thl/user_compensate.py index 8338424..3f0f3ec 100644 --- a/generalresearch/managers/thl/user_compensate.py +++ b/generalresearch/managers/thl/user_compensate.py @@ -2,15 +2,17 @@ from __future__ import annotations from datetime import UTC, datetime from decimal import Decimal +from typing import TYPE_CHECKING from uuid import uuid4 from pydantic import NonNegativeInt -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.thl.user import User +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.user import User def user_compensate( diff --git a/generalresearch/managers/thl/user_manager/__init__.py b/generalresearch/managers/thl/user_manager/__init__.py index 449dc2a..6414ef2 100644 --- a/generalresearch/managers/thl/user_manager/__init__.py +++ b/generalresearch/managers/thl/user_manager/__init__.py @@ -4,11 +4,12 @@ import csv import logging from pathlib import Path from threading import RLock -from typing import Any +from typing import TYPE_CHECKING, Any from cachetools import TTLCache, cached -from generalresearch.models.thl.product import Product +if TYPE_CHECKING: + from generalresearch.models.thl.product import Product logger = logging.getLogger() diff --git a/generalresearch/managers/thl/user_manager/mysql_user_manager.py b/generalresearch/managers/thl/user_manager/mysql_user_manager.py index af65d65..2af23dc 100644 --- a/generalresearch/managers/thl/user_manager/mysql_user_manager.py +++ b/generalresearch/managers/thl/user_manager/mysql_user_manager.py @@ -4,14 +4,17 @@ import logging from collections.abc import Collection from datetime import UTC, datetime from functools import lru_cache +from typing import TYPE_CHECKING from uuid import uuid4 import psycopg from psycopg import sql -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.thl.user import User -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + from generalresearch.pg_helper import PostgresConfig logging.basicConfig() logger = logging.getLogger() diff --git a/generalresearch/managers/thl/user_manager/rate_limit.py b/generalresearch/managers/thl/user_manager/rate_limit.py index 5d239c6..2aaa134 100644 --- a/generalresearch/managers/thl/user_manager/rate_limit.py +++ b/generalresearch/managers/thl/user_manager/rate_limit.py @@ -1,4 +1,5 @@ import logging +from typing import TYPE_CHECKING from limits import RateLimitItem, RateLimitItemPerHour, storage, strategies from limits.limits import TIME_TYPES, safe_string @@ -10,7 +11,9 @@ from generalresearch.managers.thl.user_manager import ( from generalresearch.managers.thl.user_manager.exceptions import ( UserCreateNotAllowedError, ) -from generalresearch.models.thl.product import Product + +if TYPE_CHECKING: + from generalresearch.models.thl.product import Product logger = logging.getLogger() diff --git a/generalresearch/managers/thl/user_manager/user_manager.py b/generalresearch/managers/thl/user_manager/user_manager.py index 26b1fd6..907a030 100644 --- a/generalresearch/managers/thl/user_manager/user_manager.py +++ b/generalresearch/managers/thl/user_manager/user_manager.py @@ -10,7 +10,9 @@ from pydantic import RedisDsn from generalresearch.managers.base import Permission from generalresearch.managers.thl.product import ProductManager -from generalresearch.managers.thl.user_manager.exceptions import UserDoesntExistError +from generalresearch.managers.thl.user_manager.exceptions import ( + UserDoesntExistError, +) from generalresearch.managers.thl.user_manager.mysql_user_manager import ( MysqlUserManager, ) @@ -20,15 +22,16 @@ from generalresearch.managers.thl.user_manager.rate_limit import ( from generalresearch.managers.thl.user_manager.redis_user_manager import ( RedisUserManager, ) -from generalresearch.pg_helper import PostgresConfig from generalresearch.utils.copying_cache import deepcopy_return if TYPE_CHECKING: + from generalresearch.managers.thl.userhealth import AuditLogManager from generalresearch.models.custom_types import UUIDStr from generalresearch.models.thl.product import Product from generalresearch.models.thl.user import User from generalresearch.models.thl.userhealth import AuditLog + from generalresearch.pg_helper import PostgresConfig logging.basicConfig() logger = logging.getLogger() diff --git a/generalresearch/managers/thl/userhealth.py b/generalresearch/managers/thl/userhealth.py index 2bbdfab..b986256 100644 --- a/generalresearch/managers/thl/userhealth.py +++ b/generalresearch/managers/thl/userhealth.py @@ -11,24 +11,25 @@ from pydantic import NonNegativeInt, PositiveInt from generalresearch.decorators import LOG from generalresearch.managers.base import ( - Permission, PostgresManager, PostgresManagerWithRedis, ) from generalresearch.managers.thl.ipinfo import GeoIpInfoManager -from generalresearch.models.custom_types import IPvAnyAddressStr -from generalresearch.models.thl.product import Product from generalresearch.models.thl.user_iphistory import ( IPRecord, UserIPHistory, UserIPRecord, ) -from generalresearch.models.thl.userhealth import AuditLog, AuditLogLevel -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig +from generalresearch.models.thl.userhealth import AuditLog if TYPE_CHECKING: + from generalresearch.managers.base import Permission + from generalresearch.models.custom_types import IPvAnyAddressStr + from generalresearch.models.thl.product import Product from generalresearch.models.thl.user import User + from generalresearch.models.thl.userhealth import AuditLogLevel + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig fake = faker.Faker() diff --git a/generalresearch/managers/thl/wall.py b/generalresearch/managers/thl/wall.py index 774db9e..b9dc94d 100644 --- a/generalresearch/managers/thl/wall.py +++ b/generalresearch/managers/thl/wall.py @@ -6,6 +6,7 @@ from collections.abc import Collection from datetime import UTC, datetime, timedelta from decimal import Decimal from functools import cached_property +from typing import TYPE_CHECKING from uuid import uuid4 from faker import Faker @@ -15,18 +16,12 @@ from pydantic import AwareDatetime, PositiveInt from generalresearch.managers import parse_order_by from generalresearch.managers.base import ( - Permission, PostgresManager, PostgresManagerWithRedis, ) from generalresearch.models import Source -from generalresearch.models.custom_types import SurveyKey, UUIDStr from generalresearch.models.thl.definitions import ( - ReportValue, - Status, - StatusCode1, WallAdjustedStatus, - WallStatusCode2, ) from generalresearch.models.thl.ledger import OrderBy from generalresearch.models.thl.session import ( @@ -35,7 +30,19 @@ from generalresearch.models.thl.session import ( check_adjusted_status_wall_consistent, ) from generalresearch.models.thl.survey.model import TaskActivity -from generalresearch.pg_helper import PostgresConfig + +if TYPE_CHECKING: + from generalresearch.managers.base import ( + Permission, + ) + from generalresearch.models.custom_types import SurveyKey, UUIDStr + from generalresearch.models.thl.definitions import ( + ReportValue, + Status, + StatusCode1, + WallStatusCode2, + ) + from generalresearch.pg_helper import PostgresConfig logger = logging.getLogger("WallManager") fake = Faker() diff --git a/generalresearch/managers/thl/wallet/__init__.py b/generalresearch/managers/thl/wallet/__init__.py index 05e700d..457483f 100644 --- a/generalresearch/managers/thl/wallet/__init__.py +++ b/generalresearch/managers/thl/wallet/__init__.py @@ -1,28 +1,30 @@ from decimal import Decimal -from typing import Any +from typing import TYPE_CHECKING, Any -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) -from generalresearch.managers.thl.payout import ( - PayoutEventManager, - UserPayoutEventManager, -) -from generalresearch.managers.thl.tango_api import TangoClient -from generalresearch.managers.thl.user_manager.user_manager import ( - UserManager, -) -from generalresearch.managers.thl.userhealth import UserIpHistoryManager from generalresearch.managers.thl.wallet.approve import ( approve_amt_cashout, approve_paypal_order, ) from generalresearch.models.thl.definitions import PayoutStatus -from generalresearch.models.thl.payout import UserPayoutEvent from generalresearch.models.thl.wallet import PayoutType -from generalresearch.models.thl.wallet.cashout_method import ( - CashMailOrderData, -) + +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.managers.thl.payout import ( + PayoutEventManager, + UserPayoutEventManager, + ) + from generalresearch.managers.thl.tango_api import TangoClient + from generalresearch.managers.thl.user_manager.user_manager import ( + UserManager, + ) + from generalresearch.managers.thl.userhealth import UserIpHistoryManager + from generalresearch.models.thl.payout import UserPayoutEvent + from generalresearch.models.thl.wallet.cashout_method import ( + CashMailOrderData, + ) def manage_pending_cashout( diff --git a/generalresearch/managers/thl/wallet/approve.py b/generalresearch/managers/thl/wallet/approve.py index 4a7ae5e..7fedec1 100644 --- a/generalresearch/managers/thl/wallet/approve.py +++ b/generalresearch/managers/thl/wallet/approve.py @@ -1,10 +1,16 @@ -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) -from generalresearch.managers.thl.payout import PayoutEventManager +from __future__ import annotations + +from typing import TYPE_CHECKING + from generalresearch.models.thl.definitions import PayoutStatus -from generalresearch.models.thl.payout import UserPayoutEvent -from generalresearch.models.thl.user import User + +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.managers.thl.payout import PayoutEventManager + from generalresearch.models.thl.payout import UserPayoutEvent + from generalresearch.models.thl.user import User def approve_paypal_order( diff --git a/generalresearch/managers/thl/wallet/tango.py b/generalresearch/managers/thl/wallet/tango.py index be8fd97..038f67f 100644 --- a/generalresearch/managers/thl/wallet/tango.py +++ b/generalresearch/managers/thl/wallet/tango.py @@ -1,16 +1,21 @@ -from typing import Any +from __future__ import annotations + +from typing import TYPE_CHECKING, Any from generalresearch.config import ( is_debug, ) -from generalresearch.managers.thl.ledger_manager.thl_ledger import ( - ThlLedgerManager, -) -from generalresearch.managers.thl.payout import PayoutEventManager -from generalresearch.managers.thl.tango_api import TangoClient, TangoOrderRequest +from generalresearch.managers.thl.tango_api import TangoOrderRequest from generalresearch.models.thl.definitions import PayoutStatus -from generalresearch.models.thl.payout import UserPayoutEvent -from generalresearch.models.thl.user import User + +if TYPE_CHECKING: + from generalresearch.managers.thl.ledger_manager.thl_ledger import ( + ThlLedgerManager, + ) + from generalresearch.managers.thl.payout import PayoutEventManager + from generalresearch.managers.thl.tango_api import TangoClient + from generalresearch.models.thl.payout import UserPayoutEvent + from generalresearch.models.thl.user import User def complete_tango_order( diff --git a/generalresearch/models/admin/request.py b/generalresearch/models/admin/request.py index 6112786..f128e1b 100644 --- a/generalresearch/models/admin/request.py +++ b/generalresearch/models/admin/request.py @@ -2,12 +2,13 @@ from __future__ import annotations from datetime import UTC, datetime, timedelta from enum import Enum -from typing import Literal +from typing import TYPE_CHECKING, Literal import pandas as pd from pydantic import BaseModel, Field, computed_field, model_validator -from generalresearch.models.custom_types import AwareDatetimeISO +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO class ReportType(Enum): diff --git a/generalresearch/models/cint/question.py b/generalresearch/models/cint/question.py index 4c0e52f..44efd13 100644 --- a/generalresearch/models/cint/question.py +++ b/generalresearch/models/cint/question.py @@ -9,14 +9,14 @@ from uuid import UUID from pydantic import BaseModel, Field, field_validator, model_validator from generalresearch.models import Source, string_utils -from generalresearch.models.cint import CintQuestionIdType -from generalresearch.models.custom_types import AwareDatetimeISO from generalresearch.models.thl.profiling.marketplace import ( MarketplaceQuestion, MarketplaceUserQuestionAnswer, ) if TYPE_CHECKING: + from generalresearch.models.cint import CintQuestionIdType + from generalresearch.models.custom_types import AwareDatetimeISO from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/cint/survey.py b/generalresearch/models/cint/survey.py index fde4559..8c8f882 100644 --- a/generalresearch/models/cint/survey.py +++ b/generalresearch/models/cint/survey.py @@ -4,7 +4,7 @@ import json import logging from datetime import UTC, datetime from decimal import Decimal -from typing import Annotated, Any, Literal, Self +from typing import TYPE_CHECKING, Annotated, Any, Literal, Self from more_itertools import flatten from pydantic import ( @@ -19,12 +19,6 @@ from pydantic import ( from generalresearch.locales import Localelator from generalresearch.models import Source, TaskCalculationType -from generalresearch.models.cint import CintQuestionIdType -from generalresearch.models.custom_types import ( - AlphaNumStr, - AwareDatetimeISO, - CoercedStr, -) from generalresearch.models.thl.demographics import Gender from generalresearch.models.thl.survey import MarketplaceTask from generalresearch.models.thl.survey.condition import ( @@ -32,6 +26,14 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.cint import CintQuestionIdType + from generalresearch.models.custom_types import ( + AlphaNumStr, + AwareDatetimeISO, + CoercedStr, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/cint/task_collection.py b/generalresearch/models/cint/task_collection.py index 4ae8de4..31a0173 100644 --- a/generalresearch/models/cint/task_collection.py +++ b/generalresearch/models/cint/task_collection.py @@ -1,15 +1,19 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator -from generalresearch.models.cint.survey import CintSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.cint.survey import CintSurvey + COUNTRY_ISOS: set[str] = Localelator().get_all_countries() LANGUAGE_ISOS: set[str] = Localelator().get_all_languages() diff --git a/generalresearch/models/dynata/question.py b/generalresearch/models/dynata/question.py index b95f7c6..1ed560a 100644 --- a/generalresearch/models/dynata/question.py +++ b/generalresearch/models/dynata/question.py @@ -7,14 +7,16 @@ import re from datetime import timedelta from enum import StrEnum from functools import cached_property -from typing import Any, Literal +from typing import TYPE_CHECKING, Any, Literal from pydantic import BaseModel, Field, PositiveInt, field_validator, model_validator from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import AwareDatetimeISO from generalresearch.models.thl.profiling.marketplace import MarketplaceQuestion +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/dynata/survey.py b/generalresearch/models/dynata/survey.py index 942ab4f..70e3659 100644 --- a/generalresearch/models/dynata/survey.py +++ b/generalresearch/models/dynata/survey.py @@ -5,7 +5,7 @@ import logging from datetime import UTC from decimal import Decimal from functools import cached_property -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from more_itertools import flatten from pydantic import ( @@ -19,14 +19,7 @@ from pydantic import ( ) from generalresearch.locales import Localelator -from generalresearch.models import Source, TaskCalculationType -from generalresearch.models.custom_types import ( - AlphaNumStr, - AlphaNumStrSet, - AwareDatetimeISO, - CoercedStr, - DeviceTypes, -) +from generalresearch.models import Source from generalresearch.models.dynata import DynataStatus from generalresearch.models.thl.demographics import ( Gender, @@ -37,6 +30,16 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models import TaskCalculationType + from generalresearch.models.custom_types import ( + AlphaNumStr, + AlphaNumStrSet, + AwareDatetimeISO, + CoercedStr, + DeviceTypes, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/dynata/task_collection.py b/generalresearch/models/dynata/task_collection.py index 2b82bfd..94868bb 100644 --- a/generalresearch/models/dynata/task_collection.py +++ b/generalresearch/models/dynata/task_collection.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any +from typing import TYPE_CHECKING, Any import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index @@ -8,12 +8,14 @@ from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models import TaskCalculationType from generalresearch.models.dynata import DynataStatus -from generalresearch.models.dynata.survey import DynataSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.dynata.survey import DynataSurvey + COUNTRY_ISOS = Localelator().get_all_countries() LANGUAGE_ISOS = Localelator().get_all_languages() diff --git a/generalresearch/models/events.py b/generalresearch/models/events.py index 70f699b..8d059f9 100644 --- a/generalresearch/models/events.py +++ b/generalresearch/models/events.py @@ -1,6 +1,6 @@ from datetime import UTC, datetime, timedelta from enum import StrEnum -from typing import Annotated, Literal +from typing import TYPE_CHECKING, Annotated, Literal from uuid import uuid4 from pydantic import ( @@ -13,18 +13,19 @@ from pydantic import ( model_validator, ) -from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - UUIDStr, -) -from generalresearch.models.thl.definitions import ( - SessionStatusCode2, - Status, - StatusCode1, - WallStatusCode2, -) +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + UUIDStr, + ) + from generalresearch.models.thl.definitions import ( + SessionStatusCode2, + Status, + StatusCode1, + WallStatusCode2, + ) class MessageKind(StrEnum): diff --git a/generalresearch/models/gr/authentication.py b/generalresearch/models/gr/authentication.py index 25f65fa..21ece8c 100644 --- a/generalresearch/models/gr/authentication.py +++ b/generalresearch/models/gr/authentication.py @@ -17,14 +17,14 @@ from pydantic import ( ) from generalresearch.decorators import LOG -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.gr.business import Business from generalresearch.models.gr.team import Team from generalresearch.models.thl.product import Product + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig class Claims(BaseModel): diff --git a/generalresearch/models/gr/business.py b/generalresearch/models/gr/business.py index f6689a8..146d690 100644 --- a/generalresearch/models/gr/business.py +++ b/generalresearch/models/gr/business.py @@ -20,24 +20,28 @@ from pydantic_extra_types.phone_numbers import PhoneNumber from generalresearch.currency import USDCent from generalresearch.decorators import LOG -from generalresearch.incite.mergers.pop_ledger import PopLedgerMerge from generalresearch.incite.schemas.mergers.pop_ledger import ( numerical_col_names, ) from generalresearch.models.admin.request import ReportRequest, ReportType -from generalresearch.models.custom_types import ( - AwareDatetime, - UUIDStr, - UUIDStrCoerce, -) +from generalresearch.models.gr.team import Team from generalresearch.models.thl.finance import BusinessBalances, POPFinancial -from generalresearch.models.thl.ledger import LedgerAccount, OrderBy -from generalresearch.models.thl.payout import BusinessPayoutEvent -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig +from generalresearch.models.thl.ledger import OrderBy from generalresearch.utils.aggregation import group_by_year from generalresearch.utils.enum import ReprEnumMeta +if TYPE_CHECKING: + from generalresearch.incite.mergers.pop_ledger import PopLedgerMerge + from generalresearch.models.custom_types import ( + AwareDatetime, + UUIDStr, + UUIDStrCoerce, + ) + from generalresearch.models.thl.ledger import LedgerAccount + from generalresearch.models.thl.payout import BusinessPayoutEvent + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig + logging.basicConfig() logger = logging.getLogger(__name__) @@ -49,6 +53,9 @@ if TYPE_CHECKING: from generalresearch.incite.mergers.foundations.enriched_wall import ( EnrichedWallMerge, ) + from generalresearch.managers.gr.business import ( + BusinessBankAccountManager, + ) from generalresearch.managers.thl.ledger_manager.ledger import ( LedgerManager, ) @@ -58,7 +65,7 @@ if TYPE_CHECKING: from generalresearch.managers.thl.payout import ( BusinessPayoutEventManager, ) - from generalresearch.models.gr.team import Team + from generalresearch.managers.thl.product import ProductManager from generalresearch.models.thl.product import Product @@ -263,8 +270,6 @@ class Business(BaseModel): self.addresses = [BusinessAddress.model_validate(i) for i in res] def prefetch_teams(self, pg_config: PostgresConfig) -> None: - from generalresearch.models.gr.team import Team - with pg_config.make_connection() as conn, conn.cursor( row_factory=dict_row ) as c: @@ -288,30 +293,27 @@ class Business(BaseModel): self.teams = [Team.model_validate(i) for i in res] - def prefetch_products(self, thl_pg_config: PostgresConfig) -> None: + def prefetch_products(self, product_manager: ProductManager) -> None: """ :return: All the Products for this Business """ - from generalresearch.managers.thl.product import ProductManager - pm = ProductManager(pg_config=thl_pg_config) - self.products = pm.fetch_uuids(business_uuids=[self.uuid]) + self.products = product_manager.fetch_uuids(business_uuids=[self.uuid]) - def prefetch_bank_accounts(self, pg_config: PostgresConfig) -> None: - from generalresearch.managers.gr.business import ( - BusinessBankAccountManager, + def prefetch_bank_accounts( + self, business_bank_account_manager: BusinessBankAccountManager + ) -> None: + self.bank_accounts = business_bank_account_manager.get_by_business_id( + business_id=self.id ) - bam = BusinessBankAccountManager(pg_config=pg_config) - self.bank_accounts = bam.get_by_business_id(business_id=self.id) - def prefetch_bp_accounts( - self, thl_lm: ThlLedgerManager, thl_pg_config: PostgresConfig + self, thl_lm: ThlLedgerManager, product_manager: ProductManager ): # We need to prefetch the Products everytime because there is no way # of knowing if a new Product has been added since the last time it # ran. - self.prefetch_products(thl_pg_config=thl_pg_config) + self.prefetch_products(product_manager=product_manager) product_lookup = {p.uuid: p for p in self.products} accounts = thl_lm.get_accounts_if_exists( @@ -332,6 +334,7 @@ class Business(BaseModel): ) product = product_lookup[product_uuid] thl_lm.get_account_or_create_bp_wallet(product=product) + if refresh: accounts = thl_lm.get_accounts_if_exists( qualified_names=[ diff --git a/generalresearch/models/gr/team.py b/generalresearch/models/gr/team.py index 4752bea..b36ac4c 100644 --- a/generalresearch/models/gr/team.py +++ b/generalresearch/models/gr/team.py @@ -22,27 +22,33 @@ from pydantic import ( from pydantic.json_schema import SkipJsonSchema from generalresearch.decorators import LOG -from generalresearch.incite.mergers.foundations.enriched_session import ( - EnrichedSessionMerge, -) -from generalresearch.incite.mergers.foundations.enriched_wall import ( - EnrichedWallMerge, -) from generalresearch.models.admin.request import ReportRequest, ReportType -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - UUIDStr, - UUIDStrCoerce, -) -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig from generalresearch.utils.enum import ReprEnumMeta if TYPE_CHECKING: from generalresearch.incite.base import GRLDatasets + from generalresearch.incite.mergers.foundations.enriched_session import ( + EnrichedSessionMerge, + ) + from generalresearch.incite.mergers.foundations.enriched_wall import ( + EnrichedWallMerge, + ) + from generalresearch.managers.gr.authentication import ( + GRUserManager, + ) + from generalresearch.managers.gr.business import BusinessManager + from generalresearch.managers.gr.team import MembershipManager + from generalresearch.managers.thl.product import ProductManager + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + UUIDStr, + UUIDStrCoerce, + ) from generalresearch.models.gr.authentication import GRUser from generalresearch.models.gr.business import Business from generalresearch.models.thl.product import Product + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig class MembershipPrivilege(Enum, metaclass=ReprEnumMeta): @@ -120,36 +126,17 @@ class Team(BaseModel): # --- Prefetch Methods --- - def prefetch_memberships(self, pg_config: PostgresConfig) -> None: - from generalresearch.managers.gr.team import MembershipManager - - mm = MembershipManager(pg_config=pg_config) - self.memberships = mm.get_by_team_id(team_id=self.id) - - def prefetch_gr_users( - self, pg_config: PostgresConfig, redis_config: RedisConfig - ) -> None: - from generalresearch.managers.gr.authentication import ( - GRUserManager, - ) - - gr_um = GRUserManager(pg_config=pg_config, redis_config=redis_config) - - self.gr_users = gr_um.get_by_team(team_id=self.id) - - def prefetch_businesses( - self, pg_config: PostgresConfig, redis_config: RedisConfig - ) -> None: - from generalresearch.managers.gr.business import BusinessManager + def prefetch_memberships(self, membership_manager: MembershipManager) -> None: + self.memberships = membership_manager.get_by_team_id(team_id=self.id) - bm = BusinessManager(pg_config=pg_config, redis_config=redis_config) - self.businesses = bm.get_by_team(team_id=self.id) + def prefetch_gr_users(self, gr_user_manager: GRUserManager) -> None: + self.gr_users = gr_user_manager.get_by_team(team_id=self.id) - def prefetch_products(self, thl_pg_config: PostgresConfig) -> None: - from generalresearch.managers.thl.product import ProductManager + def prefetch_businesses(self, business_manager: BusinessManager) -> None: + self.businesses = business_manager.get_by_team(team_id=self.id) - pm = ProductManager(pg_config=thl_pg_config) - self.products = pm.fetch_uuids(team_uuids=[self.uuid]) + def prefetch_products(self, product_manager: ProductManager) -> None: + self.products = product_manager.fetch_uuids(team_uuids=[self.uuid]) # --- Prebuild Methods --- diff --git a/generalresearch/models/innovate/question.py b/generalresearch/models/innovate/question.py index f5a4846..fc89524 100644 --- a/generalresearch/models/innovate/question.py +++ b/generalresearch/models/innovate/question.py @@ -9,13 +9,13 @@ from typing import TYPE_CHECKING, Any, Literal from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator from generalresearch.models import Source -from generalresearch.models.innovate import InnovateQuestionID from generalresearch.models.thl.profiling.marketplace import ( MarketplaceQuestion, MarketplaceUserQuestionAnswer, ) if TYPE_CHECKING: + from generalresearch.models.innovate import InnovateQuestionID from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/innovate/survey.py b/generalresearch/models/innovate/survey.py index d07f960..60921df 100644 --- a/generalresearch/models/innovate/survey.py +++ b/generalresearch/models/innovate/survey.py @@ -6,6 +6,7 @@ from datetime import UTC, date from decimal import Decimal from functools import cached_property from typing import ( + TYPE_CHECKING, Annotated, Any, Literal, @@ -26,20 +27,12 @@ from generalresearch.locales import Localelator from generalresearch.models import ( LogicalOperator, Source, - TaskCalculationType, -) -from generalresearch.models.custom_types import ( - AlphaNumStrSet, - AwareDatetimeISO, - CoercedStr, - DeviceTypes, ) from generalresearch.models.innovate import ( InnovateDuplicateCheckLevel, InnovateQuotaStatus, InnovateStatus, ) -from generalresearch.models.innovate.question import InnovateQuestionID from generalresearch.models.thl.demographics import Gender from generalresearch.models.thl.survey import MarketplaceTask from generalresearch.models.thl.survey.condition import ( @@ -47,6 +40,18 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models import ( + TaskCalculationType, + ) + from generalresearch.models.custom_types import ( + AlphaNumStrSet, + AwareDatetimeISO, + CoercedStr, + DeviceTypes, + ) + from generalresearch.models.innovate.question import InnovateQuestionID + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/innovate/task_collection.py b/generalresearch/models/innovate/task_collection.py index 7bf9d0f..a647d30 100644 --- a/generalresearch/models/innovate/task_collection.py +++ b/generalresearch/models/innovate/task_collection.py @@ -1,16 +1,20 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models.innovate import InnovateStatus -from generalresearch.models.innovate.survey import InnovateSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.innovate.survey import InnovateSurvey + COUNTRY_ISOS: set[str] = Localelator().get_all_countries() LANGUAGE_ISOS: set[str] = Localelator().get_all_languages() diff --git a/generalresearch/models/legacy/bucket.py b/generalresearch/models/legacy/bucket.py index 2650b90..f20a769 100644 --- a/generalresearch/models/legacy/bucket.py +++ b/generalresearch/models/legacy/bucket.py @@ -4,7 +4,7 @@ import logging import math from datetime import timedelta from decimal import Decimal -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from pydantic import ( BaseModel, @@ -16,13 +16,15 @@ from pydantic import ( ) from generalresearch.models import Source -from generalresearch.models.custom_types import ( - HttpsUrl, - PropertyCode, - UUIDStr, -) from generalresearch.models.thl.stats import StatisticalSummary +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + HttpsUrl, + PropertyCode, + UUIDStr, + ) + logger = logging.getLogger() Eligibility = Literal["conditional", "unconditional", "ineligible"] diff --git a/generalresearch/models/legacy/offerwall.py b/generalresearch/models/legacy/offerwall.py index da28663..c150dcb 100644 --- a/generalresearch/models/legacy/offerwall.py +++ b/generalresearch/models/legacy/offerwall.py @@ -1,27 +1,33 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from pydantic import BaseModel, ConfigDict, Field, NonNegativeInt -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.legacy.bucket import ( - BucketBase, - MarketplaceBucket, - OneShotOfferwallBucket, - OneShotSoftPairOfferwallBucket, - SingleEntryBucket, - SoftPairBucket, - TimeBucksBucket, - TopNBucket, - TopNPlusBucket, - TopNPlusRecontactBucket, - WXETOfferwallBucket, -) from generalresearch.models.legacy.definitions import OfferwallReason from generalresearch.models.thl.payout_format import ( PayoutFormatField, - PayoutFormatType, ) -from generalresearch.models.thl.profiling.upk_question import UpkQuestion + +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.legacy.bucket import ( + BucketBase, + MarketplaceBucket, + OneShotOfferwallBucket, + OneShotSoftPairOfferwallBucket, + SingleEntryBucket, + SoftPairBucket, + TimeBucksBucket, + TopNBucket, + TopNPlusBucket, + TopNPlusRecontactBucket, + WXETOfferwallBucket, + ) + from generalresearch.models.thl.payout_format import ( + PayoutFormatType, + ) + from generalresearch.models.thl.profiling.upk_question import UpkQuestion """ Not Done: diff --git a/generalresearch/models/legacy/questions.py b/generalresearch/models/legacy/questions.py index 9f37837..bebd28f 100644 --- a/generalresearch/models/legacy/questions.py +++ b/generalresearch/models/legacy/questions.py @@ -15,19 +15,19 @@ from pydantic import ( ) from sentry_sdk import capture_exception -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.legacy.api_status import StatusResponse -from generalresearch.models.thl.profiling.upk_question import ( - UpkQuestionOut, -) -from generalresearch.models.thl.session import Wall -from generalresearch.models.thl.user import User if TYPE_CHECKING: from generalresearch.managers.thl.user_manager.user_manager import ( UserManager, ) from generalresearch.managers.thl.wall import WallManager + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.profiling.upk_question import ( + UpkQuestionOut, + ) + from generalresearch.models.thl.session import Wall + from generalresearch.models.thl.user import User class UpkQuestionResponse(StatusResponse): diff --git a/generalresearch/models/lucid/question.py b/generalresearch/models/lucid/question.py index af3420e..98f535b 100644 --- a/generalresearch/models/lucid/question.py +++ b/generalresearch/models/lucid/question.py @@ -7,12 +7,12 @@ from typing import TYPE_CHECKING, Any, Literal, Self from pydantic import BaseModel, Field, field_validator, model_validator from generalresearch.models import Source -from generalresearch.models.lucid import LucidQuestionIdType from generalresearch.models.thl.profiling.marketplace import ( MarketplaceQuestion, ) if TYPE_CHECKING: + from generalresearch.models.lucid import LucidQuestionIdType from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/lucid/survey.py b/generalresearch/models/lucid/survey.py index 4b1bb98..0f03e31 100644 --- a/generalresearch/models/lucid/survey.py +++ b/generalresearch/models/lucid/survey.py @@ -1,22 +1,24 @@ from __future__ import annotations -from typing import Any, Self +from typing import TYPE_CHECKING, Any, Self from pydantic import BaseModel, ConfigDict, Field, NonNegativeInt from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - BigAutoInteger, - CoercedStr, - UUIDStr, -) -from generalresearch.models.thl.locales import CountryISO, LanguageISO from generalresearch.models.thl.survey.condition import ( ConditionValueType, MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + BigAutoInteger, + CoercedStr, + UUIDStr, + ) + from generalresearch.models.thl.locales import CountryISO, LanguageISO + class LucidCondition(MarketplaceCondition): model_config = ConfigDict(populate_by_name=True, frozen=False, extra="ignore") diff --git a/generalresearch/models/morning/question.py b/generalresearch/models/morning/question.py index b64a44a..748fcc6 100644 --- a/generalresearch/models/morning/question.py +++ b/generalresearch/models/morning/question.py @@ -1,18 +1,20 @@ import json from enum import StrEnum -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from uuid import UUID from pydantic import BaseModel, Field, field_validator, model_validator from generalresearch.locales import Localelator from generalresearch.models import Source -from generalresearch.models.morning import MorningQuestionID from generalresearch.models.thl.profiling.marketplace import ( MarketplaceQuestion, MarketplaceUserQuestionAnswer, ) +if TYPE_CHECKING: + from generalresearch.models.morning import MorningQuestionID + # todo: we could validate that the country_iso / language_iso exists ... locale_helper = Localelator() diff --git a/generalresearch/models/morning/survey.py b/generalresearch/models/morning/survey.py index 91d1bce..1e217f6 100644 --- a/generalresearch/models/morning/survey.py +++ b/generalresearch/models/morning/survey.py @@ -6,6 +6,7 @@ from datetime import UTC from decimal import Decimal from functools import cached_property from typing import ( + TYPE_CHECKING, Annotated, Any, Literal, @@ -25,24 +26,27 @@ from pydantic import ( from generalresearch.locales import Localelator from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - UUIDStrCoerce, -) -from generalresearch.models.morning import MorningQuestionID, MorningStatus -from generalresearch.models.morning.question import MorningQuestion +from generalresearch.models.morning import MorningStatus from generalresearch.models.thl.demographics import Gender -from generalresearch.models.thl.locales import ( - CountryISO, - CountryISOs, - LanguageISOs, -) from generalresearch.models.thl.survey import MarketplaceTask from generalresearch.models.thl.survey.condition import ( ConditionValueType, MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + UUIDStrCoerce, + ) + from generalresearch.models.morning import MorningQuestionID + from generalresearch.models.morning.question import MorningQuestion + from generalresearch.models.thl.locales import ( + CountryISO, + CountryISOs, + LanguageISOs, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/morning/task_collection.py b/generalresearch/models/morning/task_collection.py index 9303a2f..1117937 100644 --- a/generalresearch/models/morning/task_collection.py +++ b/generalresearch/models/morning/task_collection.py @@ -1,16 +1,20 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models.morning import MorningStatus -from generalresearch.models.morning.survey import MorningBid from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.morning.survey import MorningBid + COUNTRY_ISOS: set[str] = Localelator().get_all_countries() LANGUAGE_ISOS: set[str] = Localelator().get_all_languages() diff --git a/generalresearch/models/network/label.py b/generalresearch/models/network/label.py index b8fe4b0..c27f36f 100644 --- a/generalresearch/models/network/label.py +++ b/generalresearch/models/network/label.py @@ -3,6 +3,7 @@ from __future__ import annotations import ipaddress from enum import StrEnum from ipaddress import IPv4Network, IPv6Network +from typing import TYPE_CHECKING from pydantic import ( BaseModel, @@ -13,10 +14,10 @@ from pydantic import ( field_validator, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - now_utc_factory, -) +from generalresearch.models.custom_types import now_utc_factory + +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO class IPTrustClass(StrEnum): diff --git a/generalresearch/models/network/mtr/command.py b/generalresearch/models/network/mtr/command.py index 220bfc7..7e74f20 100644 --- a/generalresearch/models/network/mtr/command.py +++ b/generalresearch/models/network/mtr/command.py @@ -5,9 +5,9 @@ from typing import TYPE_CHECKING from generalresearch.models.network.definitions import IPProtocol from generalresearch.models.network.mtr.parser import parse_mtr_output -from generalresearch.models.network.mtr.result import MTRResult if TYPE_CHECKING: + from generalresearch.models.network.mtr.result import MTRResult from generalresearch.models.network.tool_run_command import MTRRunCommand SUPPORTED_PROTOCOLS = { diff --git a/generalresearch/models/network/mtr/execute.py b/generalresearch/models/network/mtr/execute.py index c5b3c5c..1a7c963 100644 --- a/generalresearch/models/network/mtr/execute.py +++ b/generalresearch/models/network/mtr/execute.py @@ -1,21 +1,29 @@ from __future__ import annotations from datetime import UTC, datetime +from typing import TYPE_CHECKING from uuid import uuid4 -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.network.definitions import IPProtocol from generalresearch.models.network.mtr.command import ( get_mtr_version, run_mtr, ) -from generalresearch.models.network.tool_run import MTRRun, Status, ToolClass, ToolName +from generalresearch.models.network.tool_run import ( + MTRRun, + Status, + ToolClass, + ToolName, +) from generalresearch.models.network.tool_run_command import ( MTRRunCommand, MTRRunCommandOptions, ) from generalresearch.models.network.utils import get_source_ip +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + def execute_mtr( ip: str, diff --git a/generalresearch/models/network/mtr/parser.py b/generalresearch/models/network/mtr/parser.py index c29439e..a0f8998 100644 --- a/generalresearch/models/network/mtr/parser.py +++ b/generalresearch/models/network/mtr/parser.py @@ -1,8 +1,11 @@ import json +from typing import TYPE_CHECKING -from generalresearch.models.network.definitions import IPProtocol from generalresearch.models.network.mtr.result import MTRResult +if TYPE_CHECKING: + from generalresearch.models.network.definitions import IPProtocol + def parse_mtr_output(raw: str, port: int, protocol: IPProtocol) -> MTRResult: data = parse_mtr_raw_output(raw) diff --git a/generalresearch/models/network/mtr/result.py b/generalresearch/models/network/mtr/result.py index 34de845..d17136c 100644 --- a/generalresearch/models/network/mtr/result.py +++ b/generalresearch/models/network/mtr/result.py @@ -3,6 +3,7 @@ from __future__ import annotations import re from functools import cached_property from ipaddress import ip_address +from typing import TYPE_CHECKING import tldextract from pydantic import ( @@ -14,7 +15,13 @@ from pydantic import ( model_validator, ) -from generalresearch.models.network.definitions import IPKind, IPProtocol, get_ip_kind +from generalresearch.models.network.definitions import ( + IPProtocol, + get_ip_kind, +) + +if TYPE_CHECKING: + from generalresearch.models.network.definitions import IPKind HOST_RE = re.compile(r"^(?P.+?) \((?P[^)]+)\)$") diff --git a/generalresearch/models/network/nmap/command.py b/generalresearch/models/network/nmap/command.py index 42b7178..3509b8d 100644 --- a/generalresearch/models/network/nmap/command.py +++ b/generalresearch/models/network/nmap/command.py @@ -4,9 +4,9 @@ import subprocess from typing import TYPE_CHECKING from generalresearch.models.network.nmap.parser import parse_nmap_xml -from generalresearch.models.network.nmap.result import NmapResult if TYPE_CHECKING: + from generalresearch.models.network.nmap.result import NmapResult from generalresearch.models.network.tool_run_command import NmapRunCommand diff --git a/generalresearch/models/network/nmap/execute.py b/generalresearch/models/network/nmap/execute.py index 6c05c89..e3610d9 100644 --- a/generalresearch/models/network/nmap/execute.py +++ b/generalresearch/models/network/nmap/execute.py @@ -1,15 +1,23 @@ from __future__ import annotations +from typing import TYPE_CHECKING from uuid import uuid4 -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.network.nmap.command import run_nmap -from generalresearch.models.network.tool_run import NmapRun, Status, ToolClass, ToolName +from generalresearch.models.network.tool_run import ( + NmapRun, + Status, + ToolClass, + ToolName, +) from generalresearch.models.network.tool_run_command import ( NmapRunCommand, NmapRunCommandOptions, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + def execute_nmap( ip: str, diff --git a/generalresearch/models/network/nmap/result.py b/generalresearch/models/network/nmap/result.py index 4552e15..57c2e8b 100644 --- a/generalresearch/models/network/nmap/result.py +++ b/generalresearch/models/network/nmap/result.py @@ -4,13 +4,15 @@ import json from datetime import timedelta from enum import StrEnum from functools import cached_property -from typing import Any, Literal +from typing import TYPE_CHECKING, Any, Literal from pydantic import BaseModel, Field, computed_field -from generalresearch.models.custom_types import AwareDatetimeISO, IPvAnyAddressStr from generalresearch.models.network.definitions import IPProtocol +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, IPvAnyAddressStr + class PortState(StrEnum): OPEN = "open" diff --git a/generalresearch/models/network/rdns/command.py b/generalresearch/models/network/rdns/command.py index c63d6d2..2250449 100644 --- a/generalresearch/models/network/rdns/command.py +++ b/generalresearch/models/network/rdns/command.py @@ -2,9 +2,9 @@ import subprocess from typing import TYPE_CHECKING from generalresearch.models.network.rdns.parser import parse_rdns_output -from generalresearch.models.network.rdns.result import RDNSResult if TYPE_CHECKING: + from generalresearch.models.network.rdns.result import RDNSResult from generalresearch.models.network.tool_run_command import RDNSRunCommand diff --git a/generalresearch/models/network/rdns/execute.py b/generalresearch/models/network/rdns/execute.py index d6de84b..6c14f77 100644 --- a/generalresearch/models/network/rdns/execute.py +++ b/generalresearch/models/network/rdns/execute.py @@ -1,9 +1,9 @@ from __future__ import annotations from datetime import UTC, datetime +from typing import TYPE_CHECKING from uuid import uuid4 -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.network.rdns.command import ( get_dig_version, run_rdns, @@ -19,6 +19,9 @@ from generalresearch.models.network.tool_run_command import ( RDNSRunCommandOptions, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + def execute_rdns(ip: str, scan_group_id: UUIDStr | None = None): started_at = datetime.now(tz=UTC) diff --git a/generalresearch/models/network/rdns/parser.py b/generalresearch/models/network/rdns/parser.py index 31a5ed6..dc33997 100644 --- a/generalresearch/models/network/rdns/parser.py +++ b/generalresearch/models/network/rdns/parser.py @@ -1,9 +1,12 @@ import ipaddress import re +from typing import TYPE_CHECKING -from generalresearch.models.custom_types import IPvAnyAddressStr from generalresearch.models.network.rdns.result import RDNSResult +if TYPE_CHECKING: + from generalresearch.models.custom_types import IPvAnyAddressStr + PTR_RE = re.compile(r"\sPTR\s+([^\s]+)\.") diff --git a/generalresearch/models/network/rdns/result.py b/generalresearch/models/network/rdns/result.py index 46af643..6845775 100644 --- a/generalresearch/models/network/rdns/result.py +++ b/generalresearch/models/network/rdns/result.py @@ -2,11 +2,13 @@ from __future__ import annotations import json from functools import cached_property +from typing import TYPE_CHECKING import tldextract from pydantic import BaseModel, Field, computed_field, model_validator -from generalresearch.models.custom_types import IPvAnyAddressStr +if TYPE_CHECKING: + from generalresearch.models.custom_types import IPvAnyAddressStr class RDNSResult(BaseModel): diff --git a/generalresearch/models/network/tool_run.py b/generalresearch/models/network/tool_run.py index c49ffc0..8479f15 100644 --- a/generalresearch/models/network/tool_run.py +++ b/generalresearch/models/network/tool_run.py @@ -1,25 +1,26 @@ from __future__ import annotations from enum import StrEnum -from typing import Literal +from typing import TYPE_CHECKING, Literal from uuid import uuid4 from pydantic import BaseModel, Field, PositiveInt -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - IPvAnyAddressStr, - UUIDStr, -) -from generalresearch.models.network.mtr.result import MTRResult -from generalresearch.models.network.nmap.result import NmapResult -from generalresearch.models.network.rdns.result import RDNSResult -from generalresearch.models.network.tool_run_command import ( - MTRRunCommand, - NmapRunCommand, - RDNSRunCommand, - ToolRunCommand, -) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + IPvAnyAddressStr, + UUIDStr, + ) + from generalresearch.models.network.mtr.result import MTRResult + from generalresearch.models.network.nmap.result import NmapResult + from generalresearch.models.network.rdns.result import RDNSResult + from generalresearch.models.network.tool_run_command import ( + MTRRunCommand, + NmapRunCommand, + RDNSRunCommand, + ToolRunCommand, + ) class ToolClass(StrEnum): diff --git a/generalresearch/models/network/tool_run_command.py b/generalresearch/models/network/tool_run_command.py index 6f22d6b..b07b811 100644 --- a/generalresearch/models/network/tool_run_command.py +++ b/generalresearch/models/network/tool_run_command.py @@ -1,12 +1,14 @@ from __future__ import annotations -from typing import Literal +from typing import TYPE_CHECKING, Literal from pydantic import BaseModel, Field -from generalresearch.models.custom_types import IPvAnyAddressStr from generalresearch.models.network.definitions import IPProtocol +if TYPE_CHECKING: + from generalresearch.models.custom_types import IPvAnyAddressStr + class ToolRunCommand(BaseModel): command: str = Field() diff --git a/generalresearch/models/precision/question.py b/generalresearch/models/precision/question.py index f532998..ba17361 100644 --- a/generalresearch/models/precision/question.py +++ b/generalresearch/models/precision/question.py @@ -9,13 +9,13 @@ from typing import TYPE_CHECKING, Any, Literal from pydantic import BaseModel, Field, ValidationError, field_validator, model_validator from generalresearch.models import Source, string_utils -from generalresearch.models.precision import PrecisionQuestionID from generalresearch.models.thl.profiling.marketplace import ( MarketplaceQuestion, MarketplaceUserQuestionAnswer, ) if TYPE_CHECKING: + from generalresearch.models.precision import PrecisionQuestionID from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/precision/survey.py b/generalresearch/models/precision/survey.py index bf9e83e..fa30882 100644 --- a/generalresearch/models/precision/survey.py +++ b/generalresearch/models/precision/survey.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from datetime import UTC from functools import cached_property -from typing import Annotated, Any, Literal, Self +from typing import TYPE_CHECKING, Annotated, Any, Literal, Self from more_itertools import flatten from pydantic import ( @@ -16,14 +16,7 @@ from pydantic import ( ) from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AlphaNumStrSet, - AwareDatetimeISO, - CoercedStr, - DeviceTypes, - UUIDStrCoerce, -) -from generalresearch.models.precision import PrecisionQuestionID, PrecisionStatus +from generalresearch.models.precision import PrecisionStatus from generalresearch.models.thl.demographics import Gender from generalresearch.models.thl.survey import MarketplaceTask from generalresearch.models.thl.survey.condition import ( @@ -31,6 +24,16 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AlphaNumStrSet, + AwareDatetimeISO, + CoercedStr, + DeviceTypes, + UUIDStrCoerce, + ) + from generalresearch.models.precision import PrecisionQuestionID + class PrecisionCondition(MarketplaceCondition): question_id: PrecisionQuestionID | None = Field() diff --git a/generalresearch/models/precision/task_collection.py b/generalresearch/models/precision/task_collection.py index c8db2af..71241ad 100644 --- a/generalresearch/models/precision/task_collection.py +++ b/generalresearch/models/precision/task_collection.py @@ -1,16 +1,18 @@ -from typing import Any +from typing import TYPE_CHECKING, Any import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models.precision import PrecisionStatus -from generalresearch.models.precision.survey import PrecisionSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.precision.survey import PrecisionSurvey + COUNTRY_ISOS = Localelator().get_all_countries() LANGUAGE_ISOS = Localelator().get_all_languages() diff --git a/generalresearch/models/prodege/question.py b/generalresearch/models/prodege/question.py index 58aed67..c43b51a 100644 --- a/generalresearch/models/prodege/question.py +++ b/generalresearch/models/prodege/question.py @@ -19,11 +19,11 @@ from pydantic import ( from generalresearch.locales import Localelator from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import AwareDatetimeISO -from generalresearch.models.prodege import ProdegeQuestionIdType from generalresearch.models.thl.profiling.marketplace import MarketplaceQuestion if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO + from generalresearch.models.prodege import ProdegeQuestionIdType from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/prodege/survey.py b/generalresearch/models/prodege/survey.py index 5d0369a..7e56a9c 100644 --- a/generalresearch/models/prodege/survey.py +++ b/generalresearch/models/prodege/survey.py @@ -7,7 +7,7 @@ from collections import defaultdict from datetime import UTC, datetime from decimal import Decimal from functools import cached_property -from typing import Any, Literal +from typing import TYPE_CHECKING, Any, Literal from pydantic import ( BaseModel, @@ -21,18 +21,9 @@ from pydantic import ( from generalresearch.locales import Localelator from generalresearch.models import LogicalOperator, Source, TaskCalculationType -from generalresearch.models.custom_types import ( - AlphaNumStrSet, - AwareDatetimeISO, - CoercedStr, - InclExcl, - UUIDStr, -) from generalresearch.models.prodege import ( ProdegePastParticipationType, - ProdegeQuestionIdType, ProdegeStatus, - ProdgeRedirectStatus, ) from generalresearch.models.prodege.definitions import PG_COUNTRY_TO_ISO from generalresearch.models.thl.demographics import Gender @@ -42,6 +33,19 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AlphaNumStrSet, + AwareDatetimeISO, + CoercedStr, + InclExcl, + UUIDStr, + ) + from generalresearch.models.prodege import ( + ProdegeQuestionIdType, + ProdgeRedirectStatus, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/prodege/task_collection.py b/generalresearch/models/prodege/task_collection.py index 9f6a81b..774fc7b 100644 --- a/generalresearch/models/prodege/task_collection.py +++ b/generalresearch/models/prodege/task_collection.py @@ -1,16 +1,18 @@ -from typing import Any +from typing import TYPE_CHECKING, Any import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models.prodege import ProdegeStatus -from generalresearch.models.prodege.survey import ProdegeSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.prodege.survey import ProdegeSurvey + COUNTRY_ISOS = Localelator().get_all_countries() LANGUAGE_ISOS = Localelator().get_all_languages() diff --git a/generalresearch/models/repdata/question.py b/generalresearch/models/repdata/question.py index 4fa2d22..8cb1fa7 100644 --- a/generalresearch/models/repdata/question.py +++ b/generalresearch/models/repdata/question.py @@ -18,10 +18,10 @@ from pydantic import ( ) from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.thl.profiling.marketplace import MarketplaceQuestion if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/repdata/survey.py b/generalresearch/models/repdata/survey.py index c5b0730..cea61ed 100644 --- a/generalresearch/models/repdata/survey.py +++ b/generalresearch/models/repdata/survey.py @@ -6,7 +6,7 @@ import logging from datetime import UTC, datetime from decimal import Decimal from functools import cached_property -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from uuid import UUID from pydantic import ( @@ -27,11 +27,6 @@ from generalresearch.models import ( Source, TaskCalculationType, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CoercedStr, - UUIDStr, -) from generalresearch.models.repdata import RepDataStatus from generalresearch.models.thl.demographics import Gender from generalresearch.models.thl.survey import MarketplaceTask @@ -40,6 +35,13 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CoercedStr, + UUIDStr, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/repdata/task_collection.py b/generalresearch/models/repdata/task_collection.py index 5b9a4ba..04d79bd 100644 --- a/generalresearch/models/repdata/task_collection.py +++ b/generalresearch/models/repdata/task_collection.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any +from typing import TYPE_CHECKING, Any import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index @@ -8,12 +8,14 @@ from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models import TaskCalculationType from generalresearch.models.repdata import RepDataStatus -from generalresearch.models.repdata.survey import RepDataSurveyHashed from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.repdata.survey import RepDataSurveyHashed + COUNTRY_ISOS = Localelator().get_all_countries() LANGUAGE_ISOS = Localelator().get_all_languages() diff --git a/generalresearch/models/sago/question.py b/generalresearch/models/sago/question.py index 291214f..cf9ea19 100644 --- a/generalresearch/models/sago/question.py +++ b/generalresearch/models/sago/question.py @@ -19,10 +19,10 @@ from pydantic import ( ) from generalresearch.models import MAX_INT32, Source, string_utils -from generalresearch.models.custom_types import AwareDatetimeISO from generalresearch.models.thl.profiling.marketplace import MarketplaceQuestion if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/sago/survey.py b/generalresearch/models/sago/survey.py index 8550cd3..c2f886a 100644 --- a/generalresearch/models/sago/survey.py +++ b/generalresearch/models/sago/survey.py @@ -5,7 +5,7 @@ import logging from datetime import UTC from decimal import Decimal from functools import cached_property -from typing import Annotated, Any, Literal, Self +from typing import TYPE_CHECKING, Annotated, Any, Literal, Self from more_itertools import flatten from pydantic import ( @@ -19,14 +19,6 @@ from pydantic import ( from generalresearch.locales import Localelator from generalresearch.models import LogicalOperator, Source -from generalresearch.models.custom_types import ( - AlphaNumStr, - AlphaNumStrSet, - AwareDatetimeISO, - CoercedStr, - DeviceTypes, - IPLikeStrSet, -) from generalresearch.models.sago import SagoStatus from generalresearch.models.thl.demographics import Gender from generalresearch.models.thl.survey import MarketplaceTask @@ -35,6 +27,16 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AlphaNumStr, + AlphaNumStrSet, + AwareDatetimeISO, + CoercedStr, + DeviceTypes, + IPLikeStrSet, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/sago/task_collection.py b/generalresearch/models/sago/task_collection.py index 2879d9c..490f7a0 100644 --- a/generalresearch/models/sago/task_collection.py +++ b/generalresearch/models/sago/task_collection.py @@ -1,18 +1,20 @@ from __future__ import annotations -from typing import Any +from typing import TYPE_CHECKING, Any import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models.sago import SagoStatus -from generalresearch.models.sago.survey import SagoSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.sago.survey import SagoSurvey + COUNTRY_ISOS: set[str] = Localelator().get_all_countries() LANGUAGE_ISOS: set[str] = Localelator().get_all_languages() diff --git a/generalresearch/models/spectrum/question.py b/generalresearch/models/spectrum/question.py index 7add692..89fbeb3 100644 --- a/generalresearch/models/spectrum/question.py +++ b/generalresearch/models/spectrum/question.py @@ -19,13 +19,13 @@ from pydantic import ( ) from generalresearch.models import MAX_INT32, Source, string_utils -from generalresearch.models.custom_types import AwareDatetimeISO -from generalresearch.models.spectrum import SpectrumQuestionIdType from generalresearch.models.thl.profiling.marketplace import ( MarketplaceQuestion, ) if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO + from generalresearch.models.spectrum import SpectrumQuestionIdType from generalresearch.models.thl.profiling.upk_question import ( UpkQuestion, ) diff --git a/generalresearch/models/spectrum/survey.py b/generalresearch/models/spectrum/survey.py index 424d206..4daa00b 100644 --- a/generalresearch/models/spectrum/survey.py +++ b/generalresearch/models/spectrum/survey.py @@ -4,20 +4,13 @@ import json import logging from datetime import UTC from decimal import Decimal -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from more_itertools import flatten from pydantic import BaseModel, ConfigDict, Field, computed_field, model_validator from generalresearch.locales import Localelator from generalresearch.models import Source, TaskCalculationType -from generalresearch.models.custom_types import ( - AlphaNumStr, - AlphaNumStrSet, - AwareDatetimeISO, - CoercedStr, - UUIDStrSet, -) from generalresearch.models.spectrum import SpectrumStatus from generalresearch.models.thl.demographics import Gender from generalresearch.models.thl.survey import MarketplaceTask @@ -26,6 +19,15 @@ from generalresearch.models.thl.survey.condition import ( MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AlphaNumStr, + AlphaNumStrSet, + AwareDatetimeISO, + CoercedStr, + UUIDStrSet, + ) + logging.basicConfig() logger = logging.getLogger() logger.setLevel(logging.INFO) diff --git a/generalresearch/models/spectrum/task_collection.py b/generalresearch/models/spectrum/task_collection.py index 8ca5a93..d909292 100644 --- a/generalresearch/models/spectrum/task_collection.py +++ b/generalresearch/models/spectrum/task_collection.py @@ -1,17 +1,21 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pandas as pd from pandera.pandas import Check, Column, DataFrameSchema, Index from generalresearch.locales import Localelator from generalresearch.models import TaskCalculationType from generalresearch.models.spectrum import SpectrumStatus -from generalresearch.models.spectrum.survey import SpectrumSurvey from generalresearch.models.thl.survey.task_collection import ( TaskCollection, create_empty_df_from_schema, ) +if TYPE_CHECKING: + from generalresearch.models.spectrum.survey import SpectrumSurvey + COUNTRY_ISOS: set[str] = Localelator().get_all_countries() LANGUAGE_ISOS: set[str] = Localelator().get_all_languages() diff --git a/generalresearch/models/thl/category.py b/generalresearch/models/thl/category.py index ebfc840..32841a5 100644 --- a/generalresearch/models/thl/category.py +++ b/generalresearch/models/thl/category.py @@ -1,11 +1,12 @@ from __future__ import annotations -from typing import Any, Self +from typing import TYPE_CHECKING, Any, Self from uuid import uuid4 from pydantic import BaseModel, Field, PositiveInt, model_validator -from generalresearch.models.custom_types import UUIDStr +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr class Category(BaseModel, frozen=True): diff --git a/generalresearch/models/thl/contest/__init__.py b/generalresearch/models/thl/contest/__init__.py index 65b28f4..f243ce4 100644 --- a/generalresearch/models/thl/contest/__init__.py +++ b/generalresearch/models/thl/contest/__init__.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import UTC, datetime -from typing import Any, Self +from typing import TYPE_CHECKING, Any, Self from uuid import uuid4 from pydantic import ( @@ -12,10 +12,12 @@ from pydantic import ( model_validator, ) -from generalresearch.currency import USDCent -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.thl.contest.definitions import ContestPrizeKind -from generalresearch.models.thl.user import User + +if TYPE_CHECKING: + from generalresearch.currency import USDCent + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.user import User class ContestEntryRule(BaseModel): diff --git a/generalresearch/models/thl/contest/contest.py b/generalresearch/models/thl/contest/contest.py index 6fc60f6..173d486 100644 --- a/generalresearch/models/thl/contest/contest.py +++ b/generalresearch/models/thl/contest/contest.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from abc import ABC, abstractmethod from datetime import UTC, datetime -from typing import Any, Self +from typing import TYPE_CHECKING, Any, Self from uuid import uuid4 from pydantic import ( @@ -15,18 +15,22 @@ from pydantic import ( model_validator, ) -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.thl.contest import ( ContestEndCondition, ContestPrize, - ContestWinner, ) from generalresearch.models.thl.contest.definitions import ( ContestEndReason, ContestStatus, ContestType, ) -from generalresearch.models.thl.locales import CountryISOs + +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.contest import ( + ContestWinner, + ) + from generalresearch.models.thl.locales import CountryISOs class ContestBase(BaseModel, ABC): diff --git a/generalresearch/models/thl/contest/contest_entry.py b/generalresearch/models/thl/contest/contest_entry.py index b5f0ac3..a57b2df 100644 --- a/generalresearch/models/thl/contest/contest_entry.py +++ b/generalresearch/models/thl/contest/contest_entry.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import UTC, datetime -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import uuid4 from pydantic import ( @@ -12,9 +12,11 @@ from pydantic import ( ) from generalresearch.currency import USDCent -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.models.thl.contest.definitions import ContestEntryType -from generalresearch.models.thl.user import User + +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.contest.definitions import ContestEntryType + from generalresearch.models.thl.user import User class ContestEntryCreate(BaseModel): diff --git a/generalresearch/models/thl/contest/leaderboard.py b/generalresearch/models/thl/contest/leaderboard.py index 080f356..efbbd0a 100644 --- a/generalresearch/models/thl/contest/leaderboard.py +++ b/generalresearch/models/thl/contest/leaderboard.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import UTC, datetime, timedelta -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from pydantic import ( ConfigDict, @@ -16,9 +16,6 @@ from generalresearch.currency import USDCent from generalresearch.decorators import LOG from generalresearch.managers.leaderboard import country_timezone from generalresearch.managers.leaderboard.manager import LeaderboardManager -from generalresearch.managers.thl.user_manager.user_manager import ( - UserManager, -) from generalresearch.models.thl.contest import ( ContestEndCondition, ContestPrize, @@ -42,6 +39,11 @@ from generalresearch.models.thl.leaderboard import ( LeaderboardFrequency, ) +if TYPE_CHECKING: + from generalresearch.managers.thl.user_manager.user_manager import ( + UserManager, + ) + class LeaderboardContestCreate(ContestBase): model_config = ConfigDict( diff --git a/generalresearch/models/thl/contest/milestone.py b/generalresearch/models/thl/contest/milestone.py index db5ba2f..e2ff2bc 100644 --- a/generalresearch/models/thl/contest/milestone.py +++ b/generalresearch/models/thl/contest/milestone.py @@ -2,7 +2,7 @@ from __future__ import annotations import logging from datetime import timedelta -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from pydantic import ( BaseModel, @@ -13,7 +13,6 @@ from pydantic import ( ) from generalresearch.currency import USDCent -from generalresearch.models.custom_types import AwareDatetimeISO from generalresearch.models.thl.contest import ( ContestPrize, ) @@ -32,6 +31,9 @@ from generalresearch.models.thl.contest.definitions import ( ContestType, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO + logging.basicConfig() LOG = logging.getLogger() LOG.setLevel(logging.INFO) diff --git a/generalresearch/models/thl/contest/raffle.py b/generalresearch/models/thl/contest/raffle.py index 14b3fb6..b944740 100644 --- a/generalresearch/models/thl/contest/raffle.py +++ b/generalresearch/models/thl/contest/raffle.py @@ -4,7 +4,7 @@ import logging import random from collections import defaultdict from datetime import UTC, datetime -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from pydantic import ( ConfigDict, @@ -20,7 +20,6 @@ from generalresearch.models.thl.contest import ( ContestEndCondition, ContestEntryRule, ContestPrize, - ContestWinner, ) from generalresearch.models.thl.contest.contest import ( Contest, @@ -28,7 +27,6 @@ from generalresearch.models.thl.contest.contest import ( ContestUserView, ) from generalresearch.models.thl.contest.contest_entry import ( - ContestEntry, ContestEntryType, ) from generalresearch.models.thl.contest.definitions import ( @@ -38,6 +36,14 @@ from generalresearch.models.thl.contest.definitions import ( ContestType, ) +if TYPE_CHECKING: + from generalresearch.models.thl.contest import ( + ContestWinner, + ) + from generalresearch.models.thl.contest.contest_entry import ( + ContestEntry, + ) + logging.basicConfig() LOG = logging.getLogger() LOG.setLevel(logging.INFO) diff --git a/generalresearch/models/thl/demographics.py b/generalresearch/models/thl/demographics.py index c11f8b2..ce4939c 100644 --- a/generalresearch/models/thl/demographics.py +++ b/generalresearch/models/thl/demographics.py @@ -8,9 +8,8 @@ from typing import TYPE_CHECKING, Any, Literal import numpy as np -from generalresearch.models.thl.locales import CountryISO - if TYPE_CHECKING: + from generalresearch.models.thl.locales import CountryISO from generalresearch.models.thl.survey import MarketplaceTask diff --git a/generalresearch/models/thl/finance.py b/generalresearch/models/thl/finance.py index 79a74a7..4b750da 100644 --- a/generalresearch/models/thl/finance.py +++ b/generalresearch/models/thl/finance.py @@ -18,17 +18,17 @@ from pydantic import ( from pydantic.json_schema import SkipJsonSchema from generalresearch.config import is_debug -from generalresearch.currency import USDCent from generalresearch.decorators import LOG from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.thl.definitions import SessionAdjustedStatus -from generalresearch.pg_helper import PostgresConfig payout_example = random.randint(150, 750 * 100) adjustment_example = random.randint(-1_000, 50 * 100) if TYPE_CHECKING: + from generalresearch.currency import USDCent from generalresearch.models.thl.ledger import LedgerAccount + from generalresearch.pg_helper import PostgresConfig class AdjustmentType(BaseModel): diff --git a/generalresearch/models/thl/ipinfo.py b/generalresearch/models/thl/ipinfo.py index 8fbae4c..8322c7d 100644 --- a/generalresearch/models/thl/ipinfo.py +++ b/generalresearch/models/thl/ipinfo.py @@ -15,14 +15,13 @@ from pydantic import ( field_validator, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - IPvAnyAddressStr, -) - if TYPE_CHECKING: from generalresearch.managers.thl.ipinfo import IPGeonameManager + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + IPvAnyAddressStr, + ) fake = Faker() diff --git a/generalresearch/models/thl/leaderboard.py b/generalresearch/models/thl/leaderboard.py index 4d116a5..3b33fe6 100644 --- a/generalresearch/models/thl/leaderboard.py +++ b/generalresearch/models/thl/leaderboard.py @@ -4,7 +4,7 @@ import logging import math from datetime import UTC, datetime, timedelta from enum import StrEnum -from typing import Literal +from typing import TYPE_CHECKING, Literal from uuid import UUID, uuid3 from zoneinfo import ZoneInfo @@ -21,9 +21,12 @@ from pydantic import ( from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.legacy.api_status import StatusResponse -from generalresearch.models.thl.locales import CountryISO from generalresearch.utils.enum import ReprEnumMeta +if TYPE_CHECKING: + from generalresearch.models.thl.locales import CountryISO + + logger = logging.getLogger() diff --git a/generalresearch/models/thl/ledger.py b/generalresearch/models/thl/ledger.py index 518e390..c38e83b 100644 --- a/generalresearch/models/thl/ledger.py +++ b/generalresearch/models/thl/ledger.py @@ -2,7 +2,7 @@ from __future__ import annotations from datetime import UTC, datetime from enum import IntEnum, StrEnum -from typing import Annotated, Any, Literal, Self +from typing import TYPE_CHECKING, Annotated, Any, Literal, Self from uuid import uuid4 from pydantic import ( @@ -16,12 +16,7 @@ from pydantic import ( model_validator, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - HttpsUrlStr, - UUIDStr, - check_valid_uuid, -) +from generalresearch.models.custom_types import check_valid_uuid from generalresearch.models.thl.pagination import Page from generalresearch.models.thl.payout_format import ( PayoutFormatType, @@ -29,6 +24,16 @@ from generalresearch.models.thl.payout_format import ( ) from generalresearch.utils.enum import ReprEnumMeta +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + HttpsUrlStr, + UUIDStr, + ) + from generalresearch.models.thl.payout_format import ( + PayoutFormatType, + ) + def _example_user_tx_payout(schema: dict[str, Any]) -> None: diff --git a/generalresearch/models/thl/offerwall/base.py b/generalresearch/models/thl/offerwall/base.py index 33b9847..1d41ef2 100644 --- a/generalresearch/models/thl/offerwall/base.py +++ b/generalresearch/models/thl/offerwall/base.py @@ -4,7 +4,7 @@ import statistics from datetime import timedelta from decimal import Decimal from string import Formatter -from typing import Annotated, Any, Self +from typing import TYPE_CHECKING, Annotated, Any, Self from uuid import uuid4 import numpy as np @@ -20,31 +20,37 @@ from pydantic import ( ) from generalresearch.models import Source -from generalresearch.models.custom_types import HttpsUrl, UUIDStr from generalresearch.models.legacy.bucket import ( Bucket as LegacyBucket, ) from generalresearch.models.legacy.bucket import ( - CategoryAssociation, DurationSummary, - Eligibility, PayoutSummary, PayoutSummaryDecimal, - SurveyEligibilityCriterion, ) from generalresearch.models.legacy.definitions import OfferwallReason -from generalresearch.models.thl.locales import CountryISO from generalresearch.models.thl.offerwall import ( OFFERWALL_TYPE_CLASS, - OfferWallType, - OfferWallTypeClass, ) from generalresearch.models.thl.offerwall.bucket import ( generate_offerwall_entry_url, ) -from generalresearch.models.thl.profiling.upk_question import UpkQuestion from generalresearch.models.thl.soft_pair import SoftPairResultType -from generalresearch.models.thl.user import User + +if TYPE_CHECKING: + from generalresearch.models.custom_types import HttpsUrl, UUIDStr + from generalresearch.models.legacy.bucket import ( + CategoryAssociation, + Eligibility, + SurveyEligibilityCriterion, + ) + from generalresearch.models.thl.locales import CountryISO + from generalresearch.models.thl.offerwall import ( + OfferWallType, + OfferWallTypeClass, + ) + from generalresearch.models.thl.profiling.upk_question import UpkQuestion + from generalresearch.models.thl.user import User class MergeTableFeatures(BaseModel): diff --git a/generalresearch/models/thl/offerwall/cache.py b/generalresearch/models/thl/offerwall/cache.py index 97546b2..aa18014 100644 --- a/generalresearch/models/thl/offerwall/cache.py +++ b/generalresearch/models/thl/offerwall/cache.py @@ -1,18 +1,19 @@ from __future__ import annotations from datetime import UTC, datetime -from typing import Any +from typing import TYPE_CHECKING, Any from pydantic import BaseModel, Field -from generalresearch.models import Source -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.models.thl.offerwall import OfferWallRequest -from generalresearch.models.thl.offerwall.base import ( - OfferwallBase, - ScoredTaskResult, - TaskResult, -) +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.offerwall import OfferWallRequest + from generalresearch.models.thl.offerwall.base import ( + OfferwallBase, + ScoredTaskResult, + TaskResult, + ) class GetOfferWallCache(BaseModel): diff --git a/generalresearch/models/thl/payout.py b/generalresearch/models/thl/payout.py index ce8a809..9902af3 100644 --- a/generalresearch/models/thl/payout.py +++ b/generalresearch/models/thl/payout.py @@ -2,7 +2,7 @@ from __future__ import annotations import json from datetime import UTC, datetime -from typing import Self +from typing import TYPE_CHECKING, Self from uuid import uuid4 from pydantic import ( @@ -17,12 +17,18 @@ from pydantic import ( from pydantic.json_schema import SkipJsonSchema from generalresearch.currency import USDCent -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr, UUIDStrCoerce from generalresearch.models.thl.definitions import PayoutStatus from generalresearch.models.thl.wallet import PayoutType -from generalresearch.models.thl.wallet.cashout_method import ( - CashMailOrderData, -) + +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + UUIDStr, + UUIDStrCoerce, + ) + from generalresearch.models.thl.wallet.cashout_method import ( + CashMailOrderData, + ) class PayoutEvent(BaseModel): @@ -59,9 +65,7 @@ class PayoutEvent(BaseModel): examples=["a6dc1fc1bf934557b952f253dee12813"], ) - created: AwareDatetimeISO = Field( - default_factory=lambda: datetime.now(tz=UTC) - ) + created: AwareDatetimeISO = Field(default_factory=lambda: datetime.now(tz=UTC)) # In the smallest unit of the currency being transacted. For USD, this # is cents. @@ -233,9 +237,7 @@ class BusinessPayoutEventCreate(BaseModel): examples=[uuid4().hex], ) - created: AwareDatetimeISO = Field( - default_factory=lambda: datetime.now(tz=UTC) - ) + created: AwareDatetimeISO = Field(default_factory=lambda: datetime.now(tz=UTC)) # In the smallest unit of the currency being transacted. For USD, this # is cents. @@ -351,5 +353,6 @@ class BusinessPayoutEventCreate(BaseModel): ) return d + class BusinessPayoutEvent(BusinessPayoutEventCreate): id: SkipJsonSchema[PositiveInt] = Field(exclude=True) diff --git a/generalresearch/models/thl/product.py b/generalresearch/models/thl/product.py index 83955a6..988b72d 100644 --- a/generalresearch/models/thl/product.py +++ b/generalresearch/models/thl/product.py @@ -45,7 +45,13 @@ from generalresearch.models.custom_types import ( HttpsUrlStr, UUIDStr, ) -from generalresearch.models.thl.ledger import LedgerAccount +from generalresearch.models.thl.finance import ( + POPFinancial, + ProductBalances, +) +from generalresearch.models.thl.payout import ( + BrokerageProductPayoutEvent, +) from generalresearch.models.thl.payout_format import ( PayoutFormatType, format_payout_format, @@ -70,13 +76,7 @@ if TYPE_CHECKING: from generalresearch.managers.thl.payout import ( BrokerageProductPayoutEventManager, ) - from generalresearch.models.thl.finance import ( - POPFinancial, - ProductBalances, - ) - from generalresearch.models.thl.payout import ( - BrokerageProductPayoutEvent, - ) + from generalresearch.models.thl.ledger import LedgerAccount # fmt: off diff --git a/generalresearch/models/thl/profiling/marketplace.py b/generalresearch/models/thl/profiling/marketplace.py index 0129e38..0c1e39b 100644 --- a/generalresearch/models/thl/profiling/marketplace.py +++ b/generalresearch/models/thl/profiling/marketplace.py @@ -3,18 +3,21 @@ from __future__ import annotations from abc import ABC, abstractmethod from datetime import UTC, datetime from functools import cached_property -from typing import Any +from typing import TYPE_CHECKING, Any from pydantic import BaseModel, ConfigDict, Field, PositiveInt, computed_field -from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - LanguageISOLike, - UUIDStr, -) -from generalresearch.models.thl.locales import CountryISO, LanguageISO +from generalresearch.models import MAX_INT32 + +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + LanguageISOLike, + UUIDStr, + ) + from generalresearch.models.thl.locales import CountryISO, LanguageISO class MarketplaceQuestion(BaseModel, ABC): diff --git a/generalresearch/models/thl/profiling/question.py b/generalresearch/models/thl/profiling/question.py index 3e2984a..920dd3a 100644 --- a/generalresearch/models/thl/profiling/question.py +++ b/generalresearch/models/thl/profiling/question.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any +from typing import TYPE_CHECKING, Any from pydantic import ( BaseModel, @@ -9,13 +9,14 @@ from pydantic import ( computed_field, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - LanguageISOLike, - UUIDStr, -) -from generalresearch.models.thl.profiling.upk_question import UpkQuestion +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + LanguageISOLike, + UUIDStr, + ) + from generalresearch.models.thl.profiling.upk_question import UpkQuestion class Question(BaseModel): diff --git a/generalresearch/models/thl/profiling/upk_property.py b/generalresearch/models/thl/profiling/upk_property.py index e46e00a..922f5a4 100644 --- a/generalresearch/models/thl/profiling/upk_property.py +++ b/generalresearch/models/thl/profiling/upk_property.py @@ -2,14 +2,17 @@ from __future__ import annotations from enum import StrEnum from functools import cached_property +from typing import TYPE_CHECKING from uuid import uuid4 from pydantic import BaseModel, ConfigDict, Field, TypeAdapter -from generalresearch.models.custom_types import CountryISOLike, UUIDStr -from generalresearch.models.thl.category import Category from generalresearch.utils.enum import ReprEnumMeta +if TYPE_CHECKING: + from generalresearch.models.custom_types import CountryISOLike, UUIDStr + from generalresearch.models.thl.category import Category + class PropertyType(StrEnum, metaclass=ReprEnumMeta): # UserProfileKnowledge Item diff --git a/generalresearch/models/thl/profiling/upk_question.py b/generalresearch/models/thl/profiling/upk_question.py index 3bb0733..a73683c 100644 --- a/generalresearch/models/thl/profiling/upk_question.py +++ b/generalresearch/models/thl/profiling/upk_question.py @@ -5,7 +5,7 @@ import json import re from enum import StrEnum from functools import cached_property -from typing import Annotated, Any, Literal +from typing import TYPE_CHECKING, Annotated, Any, Literal from pydantic import ( BaseModel, @@ -18,9 +18,11 @@ from pydantic import ( ) from generalresearch.models import Source -from generalresearch.models.custom_types import UUIDStr from generalresearch.models.thl.category import Category +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + class UPKImportance(BaseModel): task_count: int | None = Field( diff --git a/generalresearch/models/thl/profiling/upk_question_answer.py b/generalresearch/models/thl/profiling/upk_question_answer.py index d8323ad..41895b1 100644 --- a/generalresearch/models/thl/profiling/upk_question_answer.py +++ b/generalresearch/models/thl/profiling/upk_question_answer.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import UTC, datetime -from typing import Any, Self +from typing import TYPE_CHECKING, Any, Self from uuid import uuid4 from pydantic import ( @@ -14,16 +14,18 @@ from pydantic import ( ) from generalresearch.models import MAX_INT32 -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - UUIDStr, -) from generalresearch.models.thl.profiling.upk_property import ( Cardinality, PropertyType, ) +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + UUIDStr, + ) + class UpkQuestionAnswer(BaseModel): diff --git a/generalresearch/models/thl/profiling/user_info.py b/generalresearch/models/thl/profiling/user_info.py index 32af704..c82e2d2 100644 --- a/generalresearch/models/thl/profiling/user_info.py +++ b/generalresearch/models/thl/profiling/user_info.py @@ -1,14 +1,17 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from pydantic import BaseModel, ConfigDict, Field from pydantic.json_schema import SkipJsonSchema -from generalresearch.models import Source -from generalresearch.models.custom_types import AwareDatetimeISO -from generalresearch.models.thl.profiling.user_question_answer import ( - MarketplaceResearchProfileQuestion, -) -from generalresearch.models.thl.user import User +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import AwareDatetimeISO + from generalresearch.models.thl.profiling.user_question_answer import ( + MarketplaceResearchProfileQuestion, + ) + from generalresearch.models.thl.user import User class UserProfileKnowledgeAnswer(BaseModel): diff --git a/generalresearch/models/thl/profiling/user_question_answer.py b/generalresearch/models/thl/profiling/user_question_answer.py index 378345e..b1868b3 100644 --- a/generalresearch/models/thl/profiling/user_question_answer.py +++ b/generalresearch/models/thl/profiling/user_question_answer.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from collections.abc import Iterator from datetime import UTC, datetime, timedelta -from typing import Any, Literal +from typing import TYPE_CHECKING, Any, Literal from pydantic import ( BaseModel, @@ -14,10 +14,13 @@ from pydantic import ( model_validator, ) -from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.models.thl.locales import CountryISO, LanguageISO -from generalresearch.models.thl.profiling.upk_question import UpkQuestion +from generalresearch.models import MAX_INT32 + +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.locales import CountryISO, LanguageISO + from generalresearch.models.thl.profiling.upk_question import UpkQuestion class UserQuestionAnswer(BaseModel): diff --git a/generalresearch/models/thl/report_task.py b/generalresearch/models/thl/report_task.py index 299ba90..e4a8f48 100644 --- a/generalresearch/models/thl/report_task.py +++ b/generalresearch/models/thl/report_task.py @@ -3,11 +3,14 @@ from __future__ import annotations import random from collections import defaultdict from collections.abc import Collection +from typing import TYPE_CHECKING from pydantic import BaseModel, ConfigDict, Field from generalresearch.models.thl.definitions import ReportValue -from generalresearch.models.thl.user import BPUIDStr + +if TYPE_CHECKING: + from generalresearch.models.thl.user import BPUIDStr # If a report is made with multiple values, we'll take the one with the # highest priority diff --git a/generalresearch/models/thl/session.py b/generalresearch/models/thl/session.py index 31dc668..871e5c4 100644 --- a/generalresearch/models/thl/session.py +++ b/generalresearch/models/thl/session.py @@ -18,14 +18,7 @@ from pydantic import ( model_validator, ) -from generalresearch.models import DeviceType, Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - EnumNameSerializer, - IPvAnyAddressStr, - UUIDStr, -) -from generalresearch.models.legacy.bucket import Bucket +from generalresearch.models import Source from generalresearch.models.thl import ( decimal_to_int_cents, int_cents_to_decimal, @@ -33,9 +26,7 @@ from generalresearch.models.thl import ( from generalresearch.models.thl.definitions import ( WALL_ALLOWED_STATUS_CODE_1_2, WALL_ALLOWED_STATUS_STATUS_CODE, - ReportValue, SessionAdjustedStatus, - SessionStatusCode2, Status, StatusCode1, WallAdjustedStatus, @@ -46,6 +37,18 @@ if TYPE_CHECKING: from generalresearch.managers.thl.ledger_manager.thl_ledger import ( ThlLedgerManager, ) + from generalresearch.models import DeviceType + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + EnumNameSerializer, + IPvAnyAddressStr, + UUIDStr, + ) + from generalresearch.models.legacy.bucket import Bucket + from generalresearch.models.thl.definitions import ( + ReportValue, + SessionStatusCode2, + ) from generalresearch.models.thl.product import Product from generalresearch.models.thl.user import User diff --git a/generalresearch/models/thl/soft_pair.py b/generalresearch/models/thl/soft_pair.py index 7c2f36e..313d374 100644 --- a/generalresearch/models/thl/soft_pair.py +++ b/generalresearch/models/thl/soft_pair.py @@ -2,12 +2,14 @@ from __future__ import annotations from dataclasses import dataclass from enum import Enum +from typing import TYPE_CHECKING -from generalresearch.models import Source -from generalresearch.models.dynata.survey import DynataCondition -from generalresearch.models.thl.survey.condition import ( - MarketplaceCondition, -) +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.dynata.survey import DynataCondition + from generalresearch.models.thl.survey.condition import ( + MarketplaceCondition, + ) class SoftPairResultType(int, Enum): diff --git a/generalresearch/models/thl/survey/__init__.py b/generalresearch/models/thl/survey/__init__.py index 6e6b475..d0f2b33 100644 --- a/generalresearch/models/thl/survey/__init__.py +++ b/generalresearch/models/thl/survey/__init__.py @@ -3,27 +3,32 @@ from __future__ import annotations from abc import ABC, abstractmethod from decimal import Decimal from itertools import product +from typing import TYPE_CHECKING from more_itertools import flatten from pydantic import BaseModel, Field -from generalresearch.models import Source from generalresearch.models.thl.demographics import ( AgeGroup, DemographicTarget, Gender, ) -from generalresearch.models.thl.locales import ( - CountryISO, - CountryISOs, - LanguageISO, - LanguageISOs, -) from generalresearch.models.thl.survey.condition import ( ConditionValueType, - MarketplaceCondition, ) +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.thl.locales import ( + CountryISO, + CountryISOs, + LanguageISO, + LanguageISOs, + ) + from generalresearch.models.thl.survey.condition import ( + MarketplaceCondition, + ) + class MarketplaceTask(BaseModel, ABC): """This is called a "Task" even though generally it represents a survey diff --git a/generalresearch/models/thl/survey/buyer.py b/generalresearch/models/thl/survey/buyer.py index b888007..26846d3 100644 --- a/generalresearch/models/thl/survey/buyer.py +++ b/generalresearch/models/thl/survey/buyer.py @@ -3,7 +3,7 @@ from __future__ import annotations from datetime import UTC, datetime from decimal import Decimal from math import log -from typing import Annotated +from typing import TYPE_CHECKING, Annotated from pydantic import ( BaseModel, @@ -17,11 +17,13 @@ from pydantic import ( from scipy.stats import beta as beta_dist from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - UUIDStr, -) + +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + UUIDStr, + ) class Buyer(BaseModel): diff --git a/generalresearch/models/thl/survey/model.py b/generalresearch/models/thl/survey/model.py index 2eed8f7..9fa3d8e 100644 --- a/generalresearch/models/thl/survey/model.py +++ b/generalresearch/models/thl/survey/model.py @@ -2,7 +2,7 @@ from __future__ import annotations from datetime import UTC, datetime from decimal import Decimal -from typing import Annotated, Any +from typing import TYPE_CHECKING, Annotated, Any from pydantic import ( BaseModel, @@ -17,18 +17,21 @@ from pydantic import ( ) from generalresearch.managers.thl.buyer import Buyer -from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - EnumNameSerializer, - PropertyCode, - SurveyKey, -) -from generalresearch.models.thl.category import Category -from generalresearch.models.thl.definitions import Status, StatusCode1 +from generalresearch.models.thl.definitions import StatusCode1 from generalresearch.models.thl.pagination import Page +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + EnumNameSerializer, + PropertyCode, + SurveyKey, + ) + from generalresearch.models.thl.category import Category + from generalresearch.models.thl.definitions import Status + class SurveyCategoryModel(BaseModel): model_config = ConfigDict(from_attributes=True) diff --git a/generalresearch/models/thl/survey/penalty.py b/generalresearch/models/thl/survey/penalty.py index 755d25c..54edb94 100644 --- a/generalresearch/models/thl/survey/penalty.py +++ b/generalresearch/models/thl/survey/penalty.py @@ -2,15 +2,16 @@ from __future__ import annotations import abc from datetime import UTC, datetime -from typing import Annotated, Literal +from typing import TYPE_CHECKING, Annotated, Literal from pydantic import BaseModel, ConfigDict, Field, TypeAdapter -from generalresearch.models import Source -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - UUIDStr, -) +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + UUIDStr, + ) class SurveyPenalty(BaseModel, abc.ABC): diff --git a/generalresearch/models/thl/survey/task_collection.py b/generalresearch/models/thl/survey/task_collection.py index d8db0d1..c9614d5 100644 --- a/generalresearch/models/thl/survey/task_collection.py +++ b/generalresearch/models/thl/survey/task_collection.py @@ -3,12 +3,14 @@ from __future__ import annotations import copy import json import logging +from typing import TYPE_CHECKING import pandas as pd import pandera.pandas as pa from pydantic import BaseModel, ConfigDict, Field, model_validator -from generalresearch.models.thl.survey import MarketplaceTask +if TYPE_CHECKING: + from generalresearch.models.thl.survey import MarketplaceTask logging.basicConfig() logger = logging.getLogger() diff --git a/generalresearch/models/thl/task_adjustment.py b/generalresearch/models/thl/task_adjustment.py index 27c47d4..fa5592e 100644 --- a/generalresearch/models/thl/task_adjustment.py +++ b/generalresearch/models/thl/task_adjustment.py @@ -2,16 +2,20 @@ from __future__ import annotations from datetime import UTC, datetime from decimal import Decimal +from typing import TYPE_CHECKING from uuid import uuid4 from pydantic import BaseModel, ConfigDict, Field, PositiveInt, model_validator -from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr +from generalresearch.models import MAX_INT32 from generalresearch.models.thl.definitions import ( WallAdjustedStatus, ) +if TYPE_CHECKING: + from generalresearch.models import Source + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + class TaskAdjustmentEvent(BaseModel): """ diff --git a/generalresearch/models/thl/task_status.py b/generalresearch/models/thl/task_status.py index 7719b18..817f4c5 100644 --- a/generalresearch/models/thl/task_status.py +++ b/generalresearch/models/thl/task_status.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import datetime -from typing import Annotated, Any, Literal +from typing import TYPE_CHECKING, Annotated, Any, Literal from pydantic import ( BaseModel, @@ -13,11 +13,6 @@ from pydantic import ( model_validator, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - EnumNameSerializer, - UUIDStr, -) from generalresearch.models.thl import decimal_to_int_cents from generalresearch.models.thl.definitions import ( SessionAdjustedStatus, @@ -28,13 +23,23 @@ from generalresearch.models.thl.definitions import ( from generalresearch.models.thl.pagination import Page from generalresearch.models.thl.payout_format import ( PayoutFormatOptionalField, - PayoutFormatType, -) -from generalresearch.models.thl.product import ( - PayoutTransformation, - Product, ) -from generalresearch.models.thl.session import Session, WallOut +from generalresearch.models.thl.session import WallOut + +if TYPE_CHECKING: + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + EnumNameSerializer, + UUIDStr, + ) + from generalresearch.models.thl.payout_format import ( + PayoutFormatType, + ) + from generalresearch.models.thl.product import ( + PayoutTransformation, + Product, + ) + from generalresearch.models.thl.session import Session # API uses the ints, b/c this is what the grpc returned originally ... STATUS_MAP = { @@ -171,12 +176,12 @@ class TaskStatusResponse(BaseModel): # Serialize enum → int @field_serializer("status", return_type=int) - def serialize_status(self, v: Status | None, _info): + def serialize_status(self, v: Status | None): return STATUS_MAP[v] # Accept int OR string for input, but internally store a Status enum @field_validator("status", mode="before") - def deserialize_status(cls, v): + def deserialize_status(cls, v: Status | None): # int → enum if isinstance(v, int): return REVERSE_STATUS_MAP[v] diff --git a/generalresearch/models/thl/user.py b/generalresearch/models/thl/user.py index d3ffb0d..302aa72 100644 --- a/generalresearch/models/thl/user.py +++ b/generalresearch/models/thl/user.py @@ -21,18 +21,18 @@ from pydantic import ( from sentry_sdk import set_tag, set_user from generalresearch.models import MAX_INT32 -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.models.thl.ipinfo import GeoIPInformation -from generalresearch.models.thl.ledger import LedgerTransaction -from generalresearch.models.thl.product import Product -from generalresearch.models.thl.userhealth import AuditLog -from generalresearch.pg_helper import PostgresConfig if TYPE_CHECKING: from generalresearch.managers.thl.ledger_manager.thl_ledger import ( ThlLedgerManager, ) from generalresearch.managers.thl.userhealth import AuditLogManager + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.ipinfo import GeoIPInformation + from generalresearch.models.thl.ledger import LedgerTransaction + from generalresearch.models.thl.product import Product + from generalresearch.models.thl.userhealth import AuditLog + from generalresearch.pg_helper import PostgresConfig # from generalresearch.managers.thl.userhealth import UserIpHistoryManager diff --git a/generalresearch/models/thl/user_iphistory.py b/generalresearch/models/thl/user_iphistory.py index 812c18f..0d25322 100644 --- a/generalresearch/models/thl/user_iphistory.py +++ b/generalresearch/models/thl/user_iphistory.py @@ -5,7 +5,6 @@ from datetime import UTC, datetime, timedelta from typing import TYPE_CHECKING, Self from faker import Faker -from grip_client.enums import AccessType from pydantic import ( BaseModel, ConfigDict, @@ -14,18 +13,20 @@ from pydantic import ( field_validator, ) -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - CountryISOLike, - IPvAnyAddressStr, -) from generalresearch.models.thl.ipinfo import normalize_ip -from generalresearch.pg_helper import PostgresConfig -from generalresearch.redis_helper import RedisConfig if TYPE_CHECKING: + from grip_client.enums import AccessType + + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + CountryISOLike, + IPvAnyAddressStr, + ) from generalresearch.models.thl.ipinfo import GeoIPInformation from generalresearch.models.thl.user import User + from generalresearch.pg_helper import PostgresConfig + from generalresearch.redis_helper import RedisConfig fake = Faker() diff --git a/generalresearch/models/thl/user_profile.py b/generalresearch/models/thl/user_profile.py index 0ec605a..2dc19b7 100644 --- a/generalresearch/models/thl/user_profile.py +++ b/generalresearch/models/thl/user_profile.py @@ -1,7 +1,7 @@ from __future__ import annotations import hashlib -from typing import Annotated, Any, Self +from typing import TYPE_CHECKING, Annotated, Any, Self from pydantic import ( BaseModel, @@ -14,9 +14,11 @@ from pydantic import ( from pydantic.json_schema import SkipJsonSchema from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import UUIDStr -from generalresearch.models.thl.user import User -from generalresearch.models.thl.user_streak import UserStreak + +if TYPE_CHECKING: + from generalresearch.models.custom_types import UUIDStr + from generalresearch.models.thl.user import User + from generalresearch.models.thl.user_streak import UserStreak class UserMetadata(BaseModel): diff --git a/generalresearch/models/thl/user_quality_event.py b/generalresearch/models/thl/user_quality_event.py index cfb4ff3..5438740 100644 --- a/generalresearch/models/thl/user_quality_event.py +++ b/generalresearch/models/thl/user_quality_event.py @@ -3,16 +3,18 @@ from __future__ import annotations from datetime import UTC, datetime from decimal import Decimal from enum import StrEnum -from typing import Literal +from typing import TYPE_CHECKING, Literal from pydantic import BaseModel, Field, PositiveInt from generalresearch.models import MAX_INT32, Source -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr -from generalresearch.models.thl.definitions import WallAdjustedStatus -from generalresearch.models.thl.user import BPUIDStr from generalresearch.utils.enum import ReprEnumMeta +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.definitions import WallAdjustedStatus + from generalresearch.models.thl.user import BPUIDStr + """ Typically used internally. These affect a user's quality standing. """ diff --git a/generalresearch/models/thl/user_streak.py b/generalresearch/models/thl/user_streak.py index cc4d643..6cd853a 100644 --- a/generalresearch/models/thl/user_streak.py +++ b/generalresearch/models/thl/user_streak.py @@ -2,6 +2,7 @@ from __future__ import annotations from datetime import date, datetime, timedelta from enum import StrEnum +from typing import TYPE_CHECKING from zoneinfo import ZoneInfo import pandas as pd @@ -19,7 +20,9 @@ from pydantic.json_schema import SkipJsonSchema from generalresearch.managers.leaderboard import country_timezone from generalresearch.models import MAX_INT32 -from generalresearch.models.thl.locales import CountryISO + +if TYPE_CHECKING: + from generalresearch.models.thl.locales import CountryISO class StreakPeriod(StrEnum): diff --git a/generalresearch/models/thl/wallet/cashout_method.py b/generalresearch/models/thl/wallet/cashout_method.py index 6158afd..1db85e8 100644 --- a/generalresearch/models/thl/wallet/cashout_method.py +++ b/generalresearch/models/thl/wallet/cashout_method.py @@ -4,7 +4,7 @@ import hashlib import logging from datetime import UTC, datetime from enum import StrEnum -from typing import Any, Literal, Self +from typing import TYPE_CHECKING, Any, Literal, Self from pydantic import ( BaseModel, @@ -17,19 +17,22 @@ from pydantic import ( model_validator, ) -from generalresearch.currency import USDCent -from generalresearch.models.custom_types import ( - AwareDatetimeISO, - HttpsUrlStr, - UUIDStr, -) from generalresearch.models.legacy.api_status import StatusResponse from generalresearch.models.thl.definitions import PayoutStatus -from generalresearch.models.thl.locales import CountryISO -from generalresearch.models.thl.user import BPUIDStr, User -from generalresearch.models.thl.wallet import Currency, PayoutType +from generalresearch.models.thl.wallet import PayoutType from generalresearch.utils.enum import ReprEnumMeta +if TYPE_CHECKING: + from generalresearch.currency import USDCent + from generalresearch.models.custom_types import ( + AwareDatetimeISO, + HttpsUrlStr, + UUIDStr, + ) + from generalresearch.models.thl.locales import CountryISO + from generalresearch.models.thl.user import BPUIDStr, User + from generalresearch.models.thl.wallet import Currency + logger = logging.getLogger() example_cashout_method = { diff --git a/generalresearch/models/thl/wallet/payout.py b/generalresearch/models/thl/wallet/payout.py index d43807d..7301b31 100644 --- a/generalresearch/models/thl/wallet/payout.py +++ b/generalresearch/models/thl/wallet/payout.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from collections.abc import Collection from datetime import UTC, datetime -from typing import Any +from typing import TYPE_CHECKING, Any from uuid import uuid4 from pydantic import ( @@ -15,12 +15,14 @@ from pydantic import ( ) from generalresearch.currency import USDCent -from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr from generalresearch.models.thl.definitions import PayoutStatus from generalresearch.models.thl.wallet import PayoutType -from generalresearch.models.thl.wallet.cashout_method import ( - CashMailOrderData, -) + +if TYPE_CHECKING: + from generalresearch.models.custom_types import AwareDatetimeISO, UUIDStr + from generalresearch.models.thl.wallet.cashout_method import ( + CashMailOrderData, + ) class PayoutEvent(BaseModel, validate_assignment=True): diff --git a/generalresearch/models/thl/wallet/user_wallet.py b/generalresearch/models/thl/wallet/user_wallet.py index dbe66fa..625fd52 100644 --- a/generalresearch/models/thl/wallet/user_wallet.py +++ b/generalresearch/models/thl/wallet/user_wallet.py @@ -1,15 +1,20 @@ from __future__ import annotations import logging +from typing import TYPE_CHECKING from pydantic import BaseModel, ConfigDict, Field, NonNegativeInt from generalresearch.models.legacy.api_status import StatusResponse from generalresearch.models.thl.payout_format import ( PayoutFormatField, - PayoutFormatType, ) +if TYPE_CHECKING: + from generalresearch.models.thl.payout_format import ( + PayoutFormatType, + ) + logger = logging.getLogger() example_wallet_balance = { diff --git a/generalresearch/wall_status_codes/cint.py b/generalresearch/wall_status_codes/cint.py index c31c0ba..13028dc 100644 --- a/generalresearch/wall_status_codes/cint.py +++ b/generalresearch/wall_status_codes/cint.py @@ -1,8 +1,10 @@ -from typing import Any +from typing import TYPE_CHECKING, Any -from generalresearch.models.thl.definitions import Status, StatusCode1 from generalresearch.wall_status_codes import lucid +if TYPE_CHECKING: + from generalresearch.models.thl.definitions import Status, StatusCode1 + def annotate_status_code( ext_status_code_1: str, diff --git a/test_utils/conftest.py b/test_utils/conftest.py index 041caf2..f55fe11 100644 --- a/test_utils/conftest.py +++ b/test_utils/conftest.py @@ -180,7 +180,7 @@ def git_key_path( yield Path(fn) - # os.unlink(fn) + os.unlink(fn) @pytest.fixture(scope="session") diff --git a/test_utils/managers/gr/conftest.py b/test_utils/managers/gr/conftest.py index 69f3e9a..40bd7b3 100644 --- a/test_utils/managers/gr/conftest.py +++ b/test_utils/managers/gr/conftest.py @@ -1,8 +1,11 @@ from __future__ import annotations -from collections.abc import Callable +import subprocess +from collections.abc import Callable, Generator +from random import randint import pytest +import redis import redis.asyncio as redis_async from pydantic import PostgresDsn from redis import Redis @@ -19,9 +22,16 @@ from generalresearch.redis_helper import RedisConfig # === Msc === +@pytest.fixture(scope="session") +def gr_redis_config_db() -> str: + return str(randint(99, 1_023)) + + @pytest.fixture(scope="session") def gr_redis(settings: GRLBaseSettings) -> Redis: - assert "unittest" in str(settings.gr_redis) or "127.0.0.1" in str(settings.gr_redis) + assert "unittest" in str(settings.testing_redis) or "127.0.0.1" in str( + settings.testing_redis + ) return Redis.from_url( url=str(settings.gr_redis), decode_responses=True, @@ -32,10 +42,12 @@ def gr_redis(settings: GRLBaseSettings) -> Redis: @pytest.fixture def gr_redis_async(settings: GRLBaseSettings) -> redis_async.Redis: - assert "unittest" in str(settings.gr_redis) or "127.0.0.1" in str(settings.gr_redis) + assert "unittest" in str(settings.testing_redis) or "127.0.0.1" in str( + settings.testing_redis + ) return redis_async.Redis.from_url( - str(settings.gr_redis), + str(settings.testing_redis), decode_responses=True, socket_timeout=0.20, socket_connect_timeout=0.20, @@ -43,21 +55,39 @@ def gr_redis_async(settings: GRLBaseSettings) -> redis_async.Redis: @pytest.fixture(scope="session") -def gr_redis_config(settings: GRLBaseSettings) -> RedisConfig: - assert "unittest" in str(settings.gr_redis) or "127.0.0.1" in str(settings.gr_redis) +def gr_redis_config( + settings: GRLBaseSettings, gr_redis_config_db: str +) -> Generator[RedisConfig]: + assert "unittest" in str(settings.testing_redis) or "127.0.0.1" in str( + settings.testing_redis + ) - return RedisConfig( - dsn=settings.gr_redis, + uri = f"redis://{settings.testing_redis}/{gr_redis_config_db}" + + res = subprocess.run( + ["redis-cli", "-u", uri, "SET", "jenkins_lock", "1", "NX", "EX", "3600"], + check=True, + text=True, + capture_output=True, + ) + + if res.stdout.strip() != "OK": + raise ValueError("Redis already locked... aborting.") + + yield RedisConfig( + dsn=uri, decode_responses=True, socket_timeout=settings.redis_timeout, socket_connect_timeout=settings.redis_timeout, ) + r = redis.from_url(uri) + r.flushdb() + @pytest.fixture(scope="session") def gr_db(django_db_factory: Callable[..., PostgresDsn]) -> PostgresConfig: _dsn = django_db_factory("gr.common") - print("DDDD:", _dsn) return PostgresConfig( dsn=_dsn, diff --git a/test_utils/models/conftest.py b/test_utils/models/conftest.py index 5570b40..3a10ea3 100644 --- a/test_utils/models/conftest.py +++ b/test_utils/models/conftest.py @@ -22,12 +22,6 @@ from generalresearch.pg_helper import PostgresConfig if TYPE_CHECKING: from generalresearch.currency import USDCent - from generalresearch.managers.gr.business import ( - BusinessAddressManager, - BusinessBankAccountManager, - BusinessManager, - ) - from generalresearch.managers.gr.team import TeamManager from generalresearch.managers.thl.buyer import BuyerManager from generalresearch.managers.thl.ipinfo import ( IPGeonameManager, @@ -45,8 +39,6 @@ if TYPE_CHECKING: from generalresearch.managers.thl.wall import WallManager from generalresearch.models.gr.business import ( Business, - BusinessAddress, - BusinessBankAccount, ) from generalresearch.models.gr.team import Team from generalresearch.models.thl.ipinfo import IPGeoname, IPInformation @@ -407,35 +399,6 @@ def bp_payout_factory( return _inner -# === GR === - - -@pytest.fixture -def business(request, business_manager: BusinessManager) -> Business: - return business_manager.create_dummy() - - -@pytest.fixture -def business_address( - request, business: Business, business_address_manager: BusinessAddressManager -) -> BusinessAddress: - return business_address_manager.create_dummy(business_id=business.id) - - -@pytest.fixture -def business_bank_account( - request, - business: Business, - business_bank_account_manager: BusinessBankAccountManager, -) -> BusinessBankAccount: - return business_bank_account_manager.create_dummy(business_id=business.id) - - -@pytest.fixture -def team(request, team_manager: TeamManager) -> Team: - return team_manager.create_dummy() - - @pytest.fixture def audit_log(audit_log_manager: AuditLogManager, user: User) -> AuditLog: diff --git a/test_utils/models/gr/conftest.py b/test_utils/models/gr/conftest.py index 90b86aa..b623255 100644 --- a/test_utils/models/gr/conftest.py +++ b/test_utils/models/gr/conftest.py @@ -1,6 +1,7 @@ from __future__ import annotations from collections.abc import Callable +from random import randint from uuid import uuid4 import pytest @@ -20,7 +21,6 @@ from generalresearch.models.gr.business import ( Business, BusinessAddress, BusinessBankAccount, - BusinessType, TransferMethod, ) from generalresearch.models.gr.team import Membership, Team @@ -134,27 +134,38 @@ def gr_business_address_factory( @pytest.fixture def gr_business_factory( - gr_bm: BusinessManager, + gr_business_manager: BusinessManager, ) -> Callable[..., Business]: def _inner( - uuid: UUIDStr | None = None, - name: str | None = None, - team: Team | None = None, - kind: BusinessType | None = None, - tax_number: str | None = None, + save: bool = True, name: str | None = None, team: Team | None = None, **kwargs ) -> Business: - from random import randint + name = name or f"" + tax_number = str(randint(1, 999_999_999)) + + if save: + return gr_business_manager.create( + name=name, + kind="c", + uuid=uuid4().hex, + team=team, + tax_number=tax_number, + **kwargs, + ) + else: + raise ValueError("Unsaved Business not supported yet") - uuid = uuid or uuid4().hex - name = name or "< Unknown >" - tax_number = tax_number or str(randint(1, 999_999_999)) + return _inner - return gr_bm.create( - uuid=uuid, name=name, team=team, kind=kind, tax_number=tax_number - ) - return _inner +@pytest.fixture +def gr_business(gr_business_factory: Callable[..., Business]) -> Business: + return gr_business_factory(save=True) + + +@pytest.fixture +def unsaved_gr_business(gr_business_factory: Callable[..., Business]) -> Business: + return gr_business_factory(save=False) @pytest.fixture @@ -183,6 +194,21 @@ def gr_user_token( return res +@pytest.fixture +def business_address( + gr_business: Business, business_address_manager: BusinessAddressManager +) -> BusinessAddress: + return business_address_manager.create_dummy(business_id=gr_business.id) + + +@pytest.fixture +def business_bank_account( + gr_business: Business, + business_bank_account_manager: BusinessBankAccountManager, +) -> BusinessBankAccount: + return business_bank_account_manager.create_dummy(business_id=gr_business.id) + + @pytest.fixture() def gr_user_token_header(gr_user_token: GRToken) -> dict[str, str]: return gr_user_token.auth_header diff --git a/tests/models/gr/test_business.py b/tests/models/gr/test_business.py index f0107de..9310d2c 100644 --- a/tests/models/gr/test_business.py +++ b/tests/models/gr/test_business.py @@ -5,6 +5,7 @@ from collections.abc import Callable from datetime import UTC, datetime, timedelta from decimal import Decimal from pathlib import Path +from typing import TYPE_CHECKING from uuid import uuid4 import pandas as pd @@ -43,18 +44,22 @@ from generalresearch.models.thl.finance import ( BusinessBalances, ProductBalances, ) -from generalresearch.models.thl.product import BrokerageProductPayoutEvent, Product -from generalresearch.models.thl.session import Session +from generalresearch.models.thl.product import Product from generalresearch.models.thl.user import User from generalresearch.pg_helper import PostgresConfig from generalresearch.redis_helper import RedisConfig +if TYPE_CHECKING: + from generalresearch.managers.thl.product import ProductManager + from generalresearch.models.thl.product import BrokerageProductPayoutEvent + from generalresearch.models.thl.session import Session + class TestBusinessBankAccount: def test_init( self, - business: Business, + gr_business: Business, business_bank_account_manager: BusinessBankAccountManager, ): from generalresearch.models.gr.business import ( @@ -63,7 +68,7 @@ class TestBusinessBankAccount: ) instance = business_bank_account_manager.create( - business_id=business.id, + business_id=gr_business.id, uuid=uuid4().hex, transfer_method=TransferMethod.ACH, ) @@ -72,7 +77,7 @@ class TestBusinessBankAccount: def test_business( self, business_bank_account: BusinessBankAccount, - business: Business, + gr_business: Business, gr_db: PostgresConfig, gr_redis_config: RedisConfig, ): @@ -84,7 +89,7 @@ class TestBusinessBankAccount: pg_config=gr_db, redis_config=gr_redis_config ) assert isinstance(business_bank_account.business, Business) - assert business_bank_account.business.uuid == business.uuid + assert business_bank_account.business.uuid == gr_business.uuid class TestBusinessAddress: @@ -122,11 +127,12 @@ class TestBusiness: def test_str_and_repr( self, - business: Business, + gr_business: Business, product_factory: Callable[..., Product], thl_web_rr: PostgresConfig, ledger_manager: LedgerManager, thl_ledger_manager: ThlLedgerManager, + product_manager: ProductManager, business_payout_event_manager: BusinessPayoutEventManager, bp_payout_factory: Callable[..., BusinessPayoutEventManager], start: datetime, @@ -139,28 +145,28 @@ class TestBusiness: create_main_accounts: Callable[..., None], ): create_main_accounts() - p1 = product_factory(business=business) + p1 = product_factory(business=gr_business) u1 = user_factory(product=p1) - p2 = product_factory(business=business) + p2 = product_factory(business=gr_business) thl_ledger_manager.get_account_or_create_bp_wallet(product=p1) thl_ledger_manager.get_account_or_create_bp_wallet(product=p2) - res1 = repr(business) + res1 = repr(gr_business) - assert business.uuid in res1 + assert gr_business.uuid in res1 assert " 0 ] ) - assert business.balance.retainer == approx(predicted_retainer, rel=0.01) + assert gr_business.balance.retainer == approx(predicted_retainer, rel=0.01) def test_neg_balance_cache( self, @@ -837,7 +845,7 @@ class TestBusinessBalance: create_main_accounts: Callable[..., None], delete_df_collection: Callable[..., None], ledger_collection, - business: Business, + gr_business: Business, user_factory: Callable[..., User], product_factory: Callable[..., Product], session_with_tx_factory: Callable[..., Session], @@ -858,8 +866,8 @@ class TestBusinessBalance: create_main_accounts() delete_df_collection(coll=ledger_collection) - p1: Product = product_factory(business=business) - p2: Product = product_factory(business=business) + p1: Product = product_factory(business=gr_business) + p2: Product = product_factory(business=gr_business) u1: User = user_factory(product=p1) u2: User = user_factory(product=p2) thl_ledger_manager.get_account_or_create_bp_wallet(product=p1) @@ -901,7 +909,7 @@ class TestBusinessBalance: ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -910,8 +918,8 @@ class TestBusinessBalance: ) # Check Product 1 - assert isinstance(business.balance, BusinessBalances) - pb1 = business.balance.product_balances[0] + assert isinstance(gr_business.balance, BusinessBalances) + pb1 = gr_business.balance.product_balances[0] assert pb1.product_id == p1.uuid assert pb1.payout == 71 assert pb1.adjustment == -71 @@ -921,7 +929,7 @@ class TestBusinessBalance: assert pb1.available_balance == 0 # Check Product 2 - pb2 = business.balance.product_balances[1] + pb2 = gr_business.balance.product_balances[1] assert pb2.product_id == p2.uuid assert pb2.payout == 71 * 2 assert pb2.adjustment == 0 @@ -931,7 +939,7 @@ class TestBusinessBalance: assert pb2.available_balance == 107 # Check Business - bb1 = business.balance + bb1 = gr_business.balance assert isinstance(bb1, BusinessBalances) assert bb1.payout == (71 * 3) # Raw total of completes assert bb1.adjustment == -71 # 1 Complete >> Failure @@ -950,7 +958,7 @@ class TestBusinessBalance: def test_multi_product_multi_payout_adjustment_at_timestamp( self, - business: Business, + gr_business: Business, product_factory: Callable[..., Product], user_factory: Callable[..., User], mnt_filepath: GRLDatasets, @@ -1008,9 +1016,9 @@ class TestBusinessBalance: delete_df_collection(coll=ledger_collection) delete_df_collection(coll=task_adj_collection) - u1: User = user_factory(product=product_factory(business=business)) - u2: User = user_factory(product=product_factory(business=business)) - u3: User = user_factory(product=product_factory(business=business)) + u1: User = user_factory(product=product_factory(business=gr_business)) + u2: User = user_factory(product=product_factory(business=gr_business)) + u3: User = user_factory(product=product_factory(business=gr_business)) s1 = session_with_tx_factory( user=u1, @@ -1063,7 +1071,7 @@ class TestBusinessBalance: df = client_no_amm.compute(pop_ledger_merge.ddf(), sync=True) assert df.shape == (20, 28) - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1071,7 +1079,7 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, ) - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1079,9 +1087,9 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=1, hours=1), ) - day1_bal = business.balance + day1_bal = gr_business.balance - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1089,9 +1097,9 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=2, hours=1), ) - day2_bal = business.balance + day2_bal = gr_business.balance - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1099,9 +1107,9 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=3, hours=1), ) - day3_bal = business.balance + day3_bal = gr_business.balance - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1109,9 +1117,9 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=4, hours=1), ) - day4_bal = business.balance + day4_bal = gr_business.balance - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1119,9 +1127,9 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=5, hours=1), ) - day5_bal = business.balance + day5_bal = gr_business.balance - business.prebuild_balance( + gr_business.prebuild_balance( thl_pg_config=thl_web_rr, lm=ledger_manager, ds=mnt_filepath, @@ -1129,7 +1137,7 @@ class TestBusinessBalance: pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=6, hours=1), ) - day6_bal = business.balance + day6_bal = gr_business.balance assert isinstance(day1_bal, BusinessBalances) assert isinstance(day2_bal, BusinessBalances) @@ -1187,7 +1195,7 @@ class TestBusinessMethods: def test_set_cache( self, - business: Business, + gr_business: Business, gr_redis: RedisConfig, gr_db: PostgresConfig, thl_web_rr: PostgresConfig, @@ -1208,9 +1216,9 @@ class TestBusinessMethods: gr_redis_config: RedisConfig, mnt_gr_api_dir: Path, ): - assert gr_redis.get(name=business.cache_key) is None + assert gr_redis.get(name=gr_business.cache_key) is None - p1 = product_factory(team=team, business=business) + p1 = product_factory(team=team, business=gr_business) u1 = user_factory(product=p1) # Business needs tx & incite to build balance @@ -1221,7 +1229,7 @@ class TestBusinessMethods: ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) - business.set_cache( + gr_business.set_cache( pg_config=gr_db, thl_web_rr=thl_web_rr, redis_config=gr_redis_config, @@ -1234,14 +1242,14 @@ class TestBusinessMethods: mnt_gr_api=mnt_gr_api_dir, ) - assert gr_redis.hgetall(name=business.cache_key) is not None + assert gr_redis.hgetall(name=gr_business.cache_key) is not None from generalresearch.models.gr.business import Business # We're going to pull only a specific year, but make sure that # it's being assigned to the field regardless year = datetime.now(tz=UTC).year res = Business.from_redis( - uuid=business.uuid, + uuid=gr_business.uuid, fields=[f"pop_financial:{year}"], gr_redis_config=gr_redis_config, ) @@ -1249,7 +1257,7 @@ class TestBusinessMethods: def test_set_cache_business( self, - business: Business, + gr_business: Business, gr_db: PostgresConfig, thl_web_rr: PostgresConfig, product_factory: Callable[..., Product], @@ -1272,9 +1280,9 @@ class TestBusinessMethods: ): from generalresearch.models.gr.business import Business - p1 = product_factory(team=team, business=business) + p1 = product_factory(team=team, business=gr_business) u1 = user_factory(product=p1) - team_manager.add_business(team=team, business=business) + team_manager.add_business(team=team, business=gr_business) # Business needs tx & incite to build balance delete_ledger_db() @@ -1284,7 +1292,7 @@ class TestBusinessMethods: ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) - business.set_cache( + gr_business.set_cache( pg_config=gr_db, thl_web_rr=thl_web_rr, redis_config=gr_redis_config, @@ -1299,7 +1307,7 @@ class TestBusinessMethods: # keys: List = Business.required_fields() + ["products", "bp_accounts"] business2 = Business.from_redis( - uuid=business.uuid, + uuid=gr_business.uuid, fields=[ "id", "tax_number", @@ -1319,7 +1327,7 @@ class TestBusinessMethods: ) assert isinstance(business2, Business) - assert business.model_dump_json() == business2.model_dump_json() + assert gr_business.model_dump_json() == business2.model_dump_json() # assert isinstance(business2.balance, BusinessBalances) assert isinstance(business2.products, list) assert isinstance(business2.teams, list) @@ -1413,7 +1421,7 @@ class TestBusinessMethods: session_factory: Callable[..., Session], product_factory: Callable[..., Product], delete_df_collection: Callable[..., None], - business: Business, + gr_business: Business, mnt_filepath: GRLDatasets, mnt_gr_api_dir: Path, ): @@ -1421,8 +1429,8 @@ class TestBusinessMethods: delete_df_collection(coll=wall_collection) delete_df_collection(coll=session_collection) - p1 = product_factory(business=business) - p2 = product_factory(business=business) + p1 = product_factory(business=gr_business) + p2 = product_factory(business=gr_business) for p in [p1, p2]: u = user_factory(product=p) @@ -1443,7 +1451,7 @@ class TestBusinessMethods: pg_config=thl_web_rr, ) - business.prebuild_enriched_wall_parquet( + gr_business.prebuild_enriched_wall_parquet( thl_pg_config=thl_web_rr, ds=mnt_filepath, client=client_no_amm, @@ -1453,6 +1461,6 @@ class TestBusinessMethods: # Now try to read from path df = pd.read_parquet( - os.path.join(mnt_gr_api_dir, "pop_event", f"{business.file_key}.parquet") + os.path.join(mnt_gr_api_dir, "pop_event", f"{gr_business.file_key}.parquet") ) assert isinstance(df, pd.DataFrame) -- cgit v1.2.3