From 6cf7ccbaa8306700e64ada19d6f99807743b2865 Mon Sep 17 00:00:00 2001
From: Max Nanis
Date: Fri, 21 Aug 2026 17:19:41 -0700
Subject: Ruff auto updates to 3.14
---
test_utils/conftest.py | 91 ++++++++++++++++++++++++++++++++------------------
1 file changed, 58 insertions(+), 33 deletions(-)
(limited to 'test_utils/conftest.py')
diff --git a/test_utils/conftest.py b/test_utils/conftest.py
index 378b9cc..ffe458c 100644
--- a/test_utils/conftest.py
+++ b/test_utils/conftest.py
@@ -6,16 +6,17 @@ import stat
import subprocess
import sys
import tempfile
-from datetime import datetime, timedelta, timezone
+from collections.abc import Callable, Generator
+from datetime import UTC, datetime, timedelta, timezone
from os.path import join as pjoin
from pathlib import Path
-from typing import Callable, Generator
from uuid import uuid4
import pytest
from _pytest.config import Config
from dotenv import load_dotenv
from pydantic import MariaDBDsn, PostgresDsn, TypeAdapter
+from pytest import TempPathFactory
from generalresearch.config import GRLBaseSettings
from generalresearch.currency import USDCent
@@ -93,7 +94,7 @@ def postgres_instance(settings: GRLBaseSettings) -> Generator[PostgresDsn]:
from psycopg import connect
from psycopg.sql import SQL, Identifier
- now = datetime.now(timezone.utc)
+ now = datetime.now(UTC)
ts: str = now.strftime("%Y-%m-%d")
db_name = f"unittest-{ts}-{uuid4().hex[:6]}"
@@ -152,38 +153,48 @@ def postgres_instance_host(
yield value
-# @pytest.fixture(scope="session")
-# def git_key_path(settings: GRLBaseSettings) -> Path:
-# return Path('/tmp/')
-
-
@pytest.fixture(scope="session")
def git_key_path(
+ tmp_path_factory: TempPathFactory,
settings: GRLBaseSettings,
) -> Generator[Path]:
+ # We are using the tmp_path_factory because unlike the tmp_path (which
+ # is function scoped), this is session scoped.
- assert settings.git_creds
- with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix="_id_rsa") as f:
- f.write(settings.git_creds)
- key_path = f.name
-
- os.chmod(key_path, stat.S_IRUSR | stat.S_IWUSR)
+ assert settings.git_creds, "Must define key to download alternative models"
+ fn = tmp_path_factory.mktemp("keys") / "git_creds"
+ fn.write_text(settings.git_creds, encoding="utf-8")
+ os.chmod(fn, stat.S_IRUSR | stat.S_IWUSR)
- yield Path(key_path)
+ yield Path(fn)
- os.unlink(key_path)
+ os.unlink(fn)
@pytest.fixture(scope="session")
-def gr_repo(git_key_path: Path) -> Callable[..., Path]:
+def gr_repo(
+ git_key_path: Path,
+ tmp_path_factory: TempPathFactory,
+) -> Callable[..., Path | None]:
repo_url = "ssh://code.g-r-l.com/general-research/gr-carer.git"
- repo_path = Path("/tmp/gr-carer")
+
+ _ran = {}
+ if _ran.get(repo_url, False):
+ print(f"Already ran django_db_factory.{repo_url}")
+ return
+
+ _ran[repo_url] = True
+
+ fn = tmp_path_factory.mktemp("repos")
+ repo_path = fn / "gr-carer"
+ repo_path.mkdir(parents=True, exist_ok=True)
def _inner() -> Path:
+
ssh_cmd = (
f"ssh -i {git_key_path} "
"-o IdentitiesOnly=yes "
- "-o StrictHostKeyChecking=no " # or accept-new, see note below
+ "-o StrictHostKeyChecking=no "
)
env = {"GIT_SSH_COMMAND": ssh_cmd}
@@ -196,6 +207,11 @@ def gr_repo(git_key_path: Path) -> Callable[..., Path]:
env=env,
)
+ result = subprocess.run(
+ ["cat", git_key_path], capture_output=True, text=True, check=False
+ )
+ print(repr(result.stdout))
+
return repo_path
return _inner
@@ -206,21 +222,29 @@ def django_db_factory(
postgres_instance: PostgresDsn,
postgres_instance_dict: PostgresDict,
gr_repo: Callable[..., Path],
-) -> Callable[..., PostgresDsn]:
+) -> Callable[..., PostgresDsn | None]:
+
+ _ran = {}
import django
+ from django.apps import apps
from django.conf import settings as django_settings
from django.core.management import call_command
- def _inner(django_project: str = "generalresearch.thl_django"):
+ def _inner(
+ django_project: str = "generalresearch.thl_django",
+ ) -> PostgresDsn | None:
+
+ if _ran.get(django_project, False):
+ print(f"Already ran django_db_factory.{django_project}")
+ return
+ _ran[django_project] = True
if "gr" in django_project:
# We need model files that are NOT in this repo.
gr_path = gr_repo()
sys.path.insert(0, str(gr_path))
- print(sys.path)
-
# 1. Bootstrapping Django settings
if not django_settings.configured:
django_settings.configure(
@@ -242,10 +266,11 @@ def django_db_factory(
)
django.setup()
- # for model in apps.get_models():
- # print(f"Discovered model: {model._meta.label}")
+ for model in apps.get_models():
+ print(f"Discovered model: {model._meta.label}")
# 2. Run migrations directly during fixture activation
+ call_command("makemigrations", "gr", interactive=False)
call_command("migrate")
# 3. Return the Dsn so the factory gives a way to connect
@@ -276,37 +301,37 @@ def spectrum_rw(settings: GRLBaseSettings) -> SqlHelper:
@pytest.fixture
def start() -> datetime:
- return datetime(year=1900, month=1, day=1, tzinfo=timezone.utc)
+ return datetime(year=1900, month=1, day=1, tzinfo=UTC)
@pytest.fixture
def utc_now() -> datetime:
- return datetime.now(tz=timezone.utc)
+ return datetime.now(tz=UTC)
@pytest.fixture
def utc_hour_ago() -> datetime:
- return datetime.now(tz=timezone.utc) - timedelta(hours=1)
+ return datetime.now(tz=UTC) - timedelta(hours=1)
@pytest.fixture
def utc_day_ago() -> datetime:
- return datetime.now(tz=timezone.utc) - timedelta(hours=24)
+ return datetime.now(tz=UTC) - timedelta(hours=24)
@pytest.fixture
def utc_90days_ago() -> datetime:
- return datetime.now(tz=timezone.utc) - timedelta(days=90)
+ return datetime.now(tz=UTC) - timedelta(days=90)
@pytest.fixture
def utc_60days_ago() -> datetime:
- return datetime.now(tz=timezone.utc) - timedelta(days=60)
+ return datetime.now(tz=UTC) - timedelta(days=60)
@pytest.fixture
def utc_30days_ago() -> datetime:
- return datetime.now(tz=timezone.utc) - timedelta(days=30)
+ return datetime.now(tz=UTC) - timedelta(days=30)
# === Clean up ===
@@ -322,7 +347,7 @@ def delete_df_collection(
DFCollectionType,
)
- def _inner(coll: "DFCollection"):
+ def _inner(coll: DFCollection):
match coll.data_type:
case DFCollectionType.LEDGER:
for table in [
--
cgit v1.2.3
From e2c5de703be45746bacaea4136f24440ff5a291c Mon Sep 17 00:00:00 2001
From: Max Nanis
Date: Mon, 24 Aug 2026 12:35:35 -0700
Subject: Ruff std replacements
---
generalresearch/__init__.py | 2 +-
generalresearch/config.py | 2 +-
generalresearch/grliq/managers/event_plotter.py | 4 +-
generalresearch/grliq/managers/forensic_data.py | 4 +-
generalresearch/grliq/managers/forensic_events.py | 76 ++++++++++------------
generalresearch/grliq/managers/forensic_results.py | 7 +-
generalresearch/grliq/models/custom_types.py | 3 +-
generalresearch/grliq/models/forensic_data.py | 1 -
generalresearch/grliq/models/forensic_summary.py | 3 +-
generalresearch/grliq/utils.py | 2 +-
generalresearch/grpc.py | 2 +-
generalresearch/incite/base.py | 10 +--
generalresearch/incite/collections/__init__.py | 18 ++---
generalresearch/incite/defaults.py | 2 +-
.../incite/mergers/foundations/__init__.py | 2 +-
.../incite/mergers/foundations/enriched_session.py | 10 +--
.../mergers/foundations/enriched_task_adjust.py | 5 +-
.../incite/mergers/foundations/enriched_wall.py | 8 +--
generalresearch/incite/mergers/ym_survey_wall.py | 10 ++-
generalresearch/incite/mergers/ym_wall_summary.py | 3 +-
generalresearch/incite/schemas/thl_web.py | 2 +-
generalresearch/locales/setup_json.py | 1 +
generalresearch/locales/timezone.py | 1 -
generalresearch/managers/cint/survey.py | 2 +-
generalresearch/managers/criteria.py | 4 +-
generalresearch/managers/dynata/survey.py | 2 +-
generalresearch/managers/events.py | 4 +-
generalresearch/managers/gr/authentication.py | 5 +-
generalresearch/managers/gr/team.py | 2 +-
generalresearch/managers/innovate/survey.py | 2 +-
generalresearch/managers/leaderboard/__init__.py | 3 +-
generalresearch/managers/leaderboard/manager.py | 2 +-
generalresearch/managers/morning/survey.py | 2 +-
generalresearch/managers/network/label.py | 9 ++-
generalresearch/managers/network/tool_run.py | 22 +++----
generalresearch/managers/precision/survey.py | 10 +--
generalresearch/managers/prodege/survey.py | 2 +-
generalresearch/managers/repdata/survey.py | 4 +-
generalresearch/managers/sago/survey.py | 2 +-
generalresearch/managers/spectrum/survey.py | 2 +-
generalresearch/managers/survey.py | 2 -
generalresearch/managers/thl/buyer.py | 2 +-
generalresearch/managers/thl/cashout_method.py | 2 +-
generalresearch/managers/thl/contest_manager.py | 3 +-
.../managers/thl/ledger_manager/conditions.py | 4 +-
.../managers/thl/ledger_manager/exceptions.py | 5 --
.../managers/thl/ledger_manager/ledger.py | 15 ++---
.../managers/thl/ledger_manager/thl_ledger.py | 22 +++----
generalresearch/managers/thl/product.py | 10 +--
generalresearch/managers/thl/profiling/question.py | 2 +-
generalresearch/managers/thl/profiling/uqa.py | 2 +-
generalresearch/managers/thl/profiling/user_upk.py | 2 +-
generalresearch/managers/thl/session.py | 11 +---
generalresearch/managers/thl/survey.py | 25 ++++---
generalresearch/managers/thl/task_adjustment.py | 7 +-
generalresearch/managers/thl/user_compensate.py | 2 +-
.../thl/user_manager/mysql_user_manager.py | 2 +-
.../managers/thl/user_manager/user_manager.py | 1 -
generalresearch/managers/thl/userhealth.py | 2 +-
generalresearch/managers/thl/wall.py | 2 +-
generalresearch/managers/thl/wallet/tango.py | 2 +-
generalresearch/models/admin/request.py | 2 +-
generalresearch/models/custom_types.py | 3 +-
generalresearch/models/dynata/survey.py | 4 +-
generalresearch/models/gr/authentication.py | 5 +-
generalresearch/models/gr/business.py | 6 +-
generalresearch/models/gr/team.py | 7 +-
generalresearch/models/legacy/questions.py | 3 -
generalresearch/models/network/mtr/execute.py | 2 +-
generalresearch/models/network/nmap/parser.py | 2 +-
generalresearch/models/network/rdns/execute.py | 2 +-
generalresearch/models/spectrum/survey.py | 2 +-
generalresearch/models/string_utils.py | 1 -
generalresearch/models/thl/contest/contest.py | 4 +-
.../models/thl/contest/contest_entry.py | 2 +-
generalresearch/models/thl/contest/examples.py | 7 --
generalresearch/models/thl/contest/io.py | 2 +-
generalresearch/models/thl/contest/leaderboard.py | 2 +-
generalresearch/models/thl/contest/milestone.py | 3 +-
generalresearch/models/thl/contest/raffle.py | 2 +-
generalresearch/models/thl/finance.py | 5 +-
generalresearch/models/thl/ipinfo.py | 2 +-
generalresearch/models/thl/ledger_example.py | 2 +-
generalresearch/models/thl/offerwall/cache.py | 2 +-
generalresearch/models/thl/payout_format.py | 12 ++--
generalresearch/models/thl/product.py | 2 -
.../models/thl/profiling/marketplace.py | 2 +-
.../models/thl/profiling/upk_question.py | 2 +-
.../models/thl/profiling/upk_question_answer.py | 2 +-
.../models/thl/profiling/user_question_answer.py | 2 +-
generalresearch/models/thl/session.py | 2 +-
generalresearch/models/thl/survey/__init__.py | 3 -
generalresearch/models/thl/survey/buyer.py | 2 +-
generalresearch/models/thl/survey/model.py | 2 +-
generalresearch/models/thl/survey/penalty.py | 2 +-
generalresearch/models/thl/task_adjustment.py | 2 +-
generalresearch/models/thl/user.py | 2 +-
generalresearch/models/thl/user_iphistory.py | 3 +-
generalresearch/models/thl/wallet/payout.py | 2 +-
generalresearch/pg_helper.py | 12 ++--
generalresearch/schemas/survey_stats.py | 2 +-
generalresearch/sql_helper.py | 19 ++----
generalresearch/thl_django/apps.py | 14 ++--
generalresearch/thl_django/fields.py | 3 +-
.../thl_django/migrations/0001_initial.py | 3 +-
..._live_alter_surveycategory_strength_and_more.py | 2 +-
...rveystat_surveystat_live_survey_idx_and_more.py | 2 +-
...ssion_thl_session_status_d578b7_idx_and_more.py | 2 +-
...p_portscanport_iplabel_mtr_portscan_and_more.py | 5 +-
generalresearch/thl_django/network/models.py | 5 +-
generalresearch/utils/enum.py | 4 +-
generalresearch/wall_status_codes/lucid.py | 2 +-
generalresearch/wall_status_codes/morning.py | 2 +-
generalresearch/wall_status_codes/pollfish.py | 2 +-
generalresearch/wall_status_codes/precision.py | 2 +-
generalresearch/wall_status_codes/repdata.py | 2 +-
test_utils/conftest.py | 3 +-
test_utils/grliq/conftest.py | 2 +-
test_utils/incite/conftest.py | 2 +-
test_utils/managers/conftest.py | 2 -
test_utils/models/conftest.py | 9 +--
test_utils/models/contest/conftest.py | 2 +-
test_utils/models/network/conftest.py | 2 +-
test_utils/models/thl/conftest.py | 2 +-
test_utils/spectrum/conftest.py | 2 +-
.../incite/collections/test_df_collection_base.py | 3 +-
.../collections/test_df_collection_item_base.py | 2 +-
.../collections/test_df_collection_item_thl_web.py | 11 +---
.../test_df_collection_thl_marketplaces.py | 7 +-
.../collections/test_df_collection_thl_web.py | 2 -
.../mergers/foundations/test_enriched_session.py | 7 +-
.../foundations/test_enriched_task_adjust.py | 7 --
.../mergers/foundations/test_enriched_wall.py | 23 +------
.../mergers/foundations/test_user_id_product.py | 15 +----
tests/incite/mergers/test_merge_collection.py | 3 +-
tests/incite/mergers/test_merge_collection_item.py | 9 +--
tests/incite/mergers/test_pop_ledger.py | 8 +--
tests/incite/mergers/test_ym_survey_merge.py | 17 +----
tests/incite/test_collection_base.py | 3 +-
tests/incite/test_collection_base_item.py | 2 +-
tests/incite/test_grl_flow.py | 11 ++--
tests/incite/test_interval_idx.py | 3 +-
tests/managers/gr/test_authentication.py | 3 -
tests/managers/gr/test_business.py | 4 +-
tests/managers/gr/test_team.py | 2 -
tests/managers/leaderboard.py | 2 +-
tests/managers/network/test_label.py | 2 +-
tests/managers/test_events.py | 15 ++---
tests/managers/test_userpid.py | 4 +-
.../managers/thl/test_contest/test_leaderboard.py | 8 +--
tests/managers/thl/test_contest/test_milestone.py | 14 +---
tests/managers/thl/test_contest/test_raffle.py | 14 +---
tests/managers/thl/test_harmonized_uqa.py | 2 +-
tests/managers/thl/test_ipinfo.py | 2 +-
tests/managers/thl/test_ledger/test_lm_accounts.py | 6 --
tests/managers/thl/test_ledger/test_lm_tx_locks.py | 23 ++-----
.../thl/test_ledger/test_thl_lm_accounts.py | 32 ++++-----
.../thl/test_ledger/test_thl_lm_bp_payout.py | 10 +--
tests/managers/thl/test_ledger/test_thl_lm_tx.py | 64 +++---------------
.../test_ledger/test_thl_lm_tx__user_payouts.py | 3 +-
tests/managers/thl/test_ledger/test_thl_pem.py | 7 +-
tests/managers/thl/test_ledger/test_user_txs.py | 3 +-
tests/managers/thl/test_ledger/test_wallet.py | 2 +-
tests/managers/thl/test_product.py | 9 ++-
tests/managers/thl/test_product_prod.py | 2 -
tests/managers/thl/test_profiling/test_user_upk.py | 2 +-
tests/managers/thl/test_session_manager.py | 7 +-
tests/managers/thl/test_survey.py | 2 +-
tests/managers/thl/test_survey_penalty.py | 1 -
tests/managers/thl/test_task_adjustment.py | 2 +-
tests/managers/thl/test_task_status.py | 2 +-
tests/managers/thl/test_user_manager/test_base.py | 4 +-
tests/managers/thl/test_user_manager/test_mysql.py | 1 -
.../thl/test_user_manager/test_user_fetch.py | 1 -
.../thl/test_user_manager/test_user_metadata.py | 1 -
tests/managers/thl/test_user_streak.py | 2 +-
tests/managers/thl/test_userhealth.py | 2 +-
tests/managers/thl/test_wall_manager.py | 13 ++--
tests/models/admin/test_report_request.py | 2 +-
tests/models/custom_types/test_aware_datetime.py | 2 +-
tests/models/custom_types/test_dsn.py | 1 -
tests/models/dynata/test_eligbility.py | 2 +-
tests/models/gr/test_authentication.py | 2 +-
tests/models/gr/test_business.py | 3 +-
tests/models/innovate/test_question.py | 6 +-
.../models/legacy/test_user_question_answer_in.py | 4 +-
tests/models/morning/test.py | 2 +-
tests/models/network/test_mtr.py | 4 +-
tests/models/network/test_nmap_parser.py | 1 +
tests/models/prodege/test_survey_participation.py | 2 +-
tests/models/spectrum/test_question.py | 2 +-
tests/models/spectrum/test_survey.py | 2 +-
tests/models/spectrum/test_survey_manager.py | 2 +-
tests/models/test_finance.py | 2 +-
tests/models/thl/question/test_question_info.py | 2 +-
tests/models/thl/test_adjustments.py | 30 ++-------
.../thl/test_contest/test_leaderboard_contest.py | 2 +-
tests/models/thl/test_ledger.py | 2 +-
tests/models/thl/test_payout.py | 5 +-
tests/models/thl/test_product.py | 2 +-
tests/models/thl/test_upkquestion.py | 12 +---
tests/models/thl/test_user.py | 6 +-
tests/models/thl/test_user_iphistory.py | 2 +-
tests/models/thl/test_user_streak.py | 2 +-
tests/models/thl/test_wall.py | 2 +-
tests/models/thl/test_wall_session.py | 2 +-
tests/sql_helper.py | 4 +-
207 files changed, 398 insertions(+), 725 deletions(-)
(limited to 'test_utils/conftest.py')
diff --git a/generalresearch/__init__.py b/generalresearch/__init__.py
index 604b7e2..3b2ec3d 100644
--- a/generalresearch/__init__.py
+++ b/generalresearch/__init__.py
@@ -129,7 +129,7 @@ def synchronized(wrapped):
if lock is None:
lock = threading.RLock()
- setattr(context, "_synchronized_lock", lock)
+ context._synchronized_lock = lock
return lock
diff --git a/generalresearch/config.py b/generalresearch/config.py
index 76e3995..c6f41e8 100644
--- a/generalresearch/config.py
+++ b/generalresearch/config.py
@@ -1,7 +1,7 @@
from __future__ import annotations
import os
-from datetime import UTC, datetime, timezone
+from datetime import UTC, datetime
from pathlib import Path
from pydantic import DirectoryPath, Field, MariaDBDsn, PostgresDsn, RedisDsn
diff --git a/generalresearch/grliq/managers/event_plotter.py b/generalresearch/grliq/managers/event_plotter.py
index 0bba7c5..94b70ef 100644
--- a/generalresearch/grliq/managers/event_plotter.py
+++ b/generalresearch/grliq/managers/event_plotter.py
@@ -13,7 +13,7 @@ def make_events_svg(
mouse_events: list[MouseEvent], keyboard_events: list[KeyboardEvent]
) -> str:
if len(mouse_events) + len(keyboard_events) == 0:
- return f'"
+ return '"
t = np.array([pm.timeStamp for pm in mouse_events])
t_diff = t.max() - t.min()
@@ -88,7 +88,7 @@ def make_events_svg(
svg_elements.append(svg_multiline_text(text, cx + 5, cy - 5, font_size))
svg = (
- f'