aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-19 14:24:13 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-19 14:24:13 +0200
commit86188385cbdae1ee90c1dca7a7b9db2edef1ecd4 (patch)
treecc01153f05e84ad6cd34556caecd3f4bc335d0bd /packages/meshbay-hub/tests
parentd2495a2c4b89fbbfc18cefec83ae96cabdd745e2 (diff)
downloadmeshbay-86188385cbdae1ee90c1dca7a7b9db2edef1ecd4.tar.gz
style: ruff's own fixes, mechanically applied
`ruff check .` had gone unrun long enough to report 568 errors, which is the same as having no linter: the next real finding would have been invisible in the noise. This is the 521 it fixes by itself, in 173 files, and nothing else — the 98 it cannot fix are the next commit. What actually changed: import sorting (225), imports nobody used (87, none of them a re-export — no `__init__.py` is touched, which was the one way this could have broken an import elsewhere), `datetime.timezone.utc` to `datetime.UTC` (69) and `asyncio.TimeoutError` to `TimeoutError` (18), both plain aliases on the 3.12 this project requires, `Optional[X]` to `X | None` (24), and f-strings with nothing to interpolate (19). Checked rather than assumed: every module in the three packages still imports, and the suite is 2893 passed — the same count, test for test, as the merge before it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/tests')
-rw-r--r--packages/meshbay-hub/tests/conftest.py14
-rw-r--r--packages/meshbay-hub/tests/harness/chat_send_probe.py1
-rw-r--r--packages/meshbay-hub/tests/test_account_deletion.py3
-rw-r--r--packages/meshbay-hub/tests/test_account_pinning.py1
-rw-r--r--packages/meshbay-hub/tests/test_admin_views.py6
-rw-r--r--packages/meshbay-hub/tests/test_asset_versioning.py1
-rw-r--r--packages/meshbay-hub/tests/test_availability_between_members.py8
-rw-r--r--packages/meshbay-hub/tests/test_captcha_host_check.py2
-rw-r--r--packages/meshbay-hub/tests/test_device_auth.py2
-rw-r--r--packages/meshbay-hub/tests/test_group_hosting.py21
-rw-r--r--packages/meshbay-hub/tests/test_group_leave_and_quota.py7
-rw-r--r--packages/meshbay-hub/tests/test_group_membership.py3
-rw-r--r--packages/meshbay-hub/tests/test_group_purge.py13
-rw-r--r--packages/meshbay-hub/tests/test_groups_self_service.py8
-rw-r--r--packages/meshbay-hub/tests/test_hub_api.py29
-rw-r--r--packages/meshbay-hub/tests/test_login_lockout.py9
-rw-r--r--packages/meshbay-hub/tests/test_mail_is_not_a_relay.py13
-rw-r--r--packages/meshbay-hub/tests/test_migrations_reach_head.py3
-rw-r--r--packages/meshbay-hub/tests/test_node_auth.py2
-rw-r--r--packages/meshbay-hub/tests/test_node_ws_auth.py6
-rw-r--r--packages/meshbay-hub/tests/test_notification_dismissal.py1
-rw-r--r--packages/meshbay-hub/tests/test_notifications.py1
-rw-r--r--packages/meshbay-hub/tests/test_notifications_behaviour.py5
-rw-r--r--packages/meshbay-hub/tests/test_packaging_hub_unit.py1
-rw-r--r--packages/meshbay-hub/tests/test_password_change.py3
-rw-r--r--packages/meshbay-hub/tests/test_password_reset.py4
-rw-r--r--packages/meshbay-hub/tests/test_public_groups_toggle.py4
-rw-r--r--packages/meshbay-hub/tests/test_revocation.py4
-rw-r--r--packages/meshbay-hub/tests/test_session_lifetime.py13
-rw-r--r--packages/meshbay-hub/tests/test_session_renewal.py2
-rw-r--r--packages/meshbay-hub/tests/test_table_rows_measured.py3
31 files changed, 89 insertions, 104 deletions
diff --git a/packages/meshbay-hub/tests/conftest.py b/packages/meshbay-hub/tests/conftest.py
index bf94464..bb0ed28 100644
--- a/packages/meshbay-hub/tests/conftest.py
+++ b/packages/meshbay-hub/tests/conftest.py
@@ -1,12 +1,12 @@
"""Shared pytest fixtures for hub tests."""
import os
+from pathlib import Path
+
import pytest
import pytest_asyncio
-from pathlib import Path
-from unittest.mock import AsyncMock
-from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
# Force SQLite in-memory for all hub tests
os.environ.setdefault("MESHBAY_DATABASE_URL", "sqlite+aiosqlite:///:memory:")
@@ -28,7 +28,13 @@ def hub_key_path(tmp_path_factory) -> Path:
@pytest.fixture
def hub_config(hub_key_path, tmp_path):
- from meshbay_hub.config import HubConfig, DatabaseConfig, ServerConfig, HubIdentityConfig, JWTConfig
+ from meshbay_hub.config import (
+ DatabaseConfig,
+ HubConfig,
+ HubIdentityConfig,
+ JWTConfig,
+ ServerConfig,
+ )
cfg = HubConfig(
db=DatabaseConfig(url="sqlite+aiosqlite:///:memory:"),
server=ServerConfig(host="127.0.0.1", port=8000),
diff --git a/packages/meshbay-hub/tests/harness/chat_send_probe.py b/packages/meshbay-hub/tests/harness/chat_send_probe.py
index b6dd957..d343c50 100644
--- a/packages/meshbay-hub/tests/harness/chat_send_probe.py
+++ b/packages/meshbay-hub/tests/harness/chat_send_probe.py
@@ -96,7 +96,6 @@ def _page() -> str:
the page built itself would prove only that the page agrees with the page.
"""
import msgpack # noqa: F401 (imported for the failure it gives if absent)
-
from meshbay_common.groupbox import PURPOSE_CHAT_KEYS, seal
sealed = seal(GEK, PURPOSE_CHAT_KEYS, "chat_keys_resp", GROUP_ID,
diff --git a/packages/meshbay-hub/tests/test_account_deletion.py b/packages/meshbay-hub/tests/test_account_deletion.py
index 3d3fee4..2653f0d 100644
--- a/packages/meshbay-hub/tests/test_account_deletion.py
+++ b/packages/meshbay-hub/tests/test_account_deletion.py
@@ -12,9 +12,8 @@ command.
import hashlib
import pytest
-from sqlalchemy import select
-
from meshbay_hub.db.models import GroupMember, Notification, RefreshToken, User
+from sqlalchemy import select
def _auth_key(password: str, username: str) -> str:
diff --git a/packages/meshbay-hub/tests/test_account_pinning.py b/packages/meshbay-hub/tests/test_account_pinning.py
index 192bd25..a1419c3 100644
--- a/packages/meshbay-hub/tests/test_account_pinning.py
+++ b/packages/meshbay-hub/tests/test_account_pinning.py
@@ -23,7 +23,6 @@ from pathlib import Path
import pytest
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
-
from meshbay_common.device import device_add_transcript
STATIC = (Path(__file__).resolve().parents[1]
diff --git a/packages/meshbay-hub/tests/test_admin_views.py b/packages/meshbay-hub/tests/test_admin_views.py
index 5017b76..da2d3c9 100644
--- a/packages/meshbay-hub/tests/test_admin_views.py
+++ b/packages/meshbay-hub/tests/test_admin_views.py
@@ -11,9 +11,8 @@ import base64
import hashlib
import pytest
-from sqlalchemy import select
-
from meshbay_hub.db.models import User
+from sqlalchemy import select
def _auth_key(password: str, username: str) -> str:
@@ -109,9 +108,8 @@ async def test_a_node_is_recorded_at_the_address_it_announced_from(
import base64
import time
- from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
-
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from meshbay_hub.db.models import Node
admin = await _admin(client, db_session, "root4_test")
diff --git a/packages/meshbay-hub/tests/test_asset_versioning.py b/packages/meshbay-hub/tests/test_asset_versioning.py
index 0c93f5a..aa2dc6d 100644
--- a/packages/meshbay-hub/tests/test_asset_versioning.py
+++ b/packages/meshbay-hub/tests/test_asset_versioning.py
@@ -22,7 +22,6 @@ import re
import pytest
from fastapi.testclient import TestClient
-
from meshbay_hub.api.webapp import ASSET_V, STATIC_DIR, _asset_version
from meshbay_hub.app import create_app
diff --git a/packages/meshbay-hub/tests/test_availability_between_members.py b/packages/meshbay-hub/tests/test_availability_between_members.py
index 2be7c03..4f5cbfb 100644
--- a/packages/meshbay-hub/tests/test_availability_between_members.py
+++ b/packages/meshbay-hub/tests/test_availability_between_members.py
@@ -24,7 +24,6 @@ import time
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
@@ -158,8 +157,7 @@ async def test_one_node_cannot_spend_the_hubs_database_on_notifications():
without backpressure. The budget is what stops one group's node from
costing every other group on the instance.
"""
- from meshbay_hub.api.revocation import (
- NOTIFY_BURST, _notify_budget, _notify_window)
+ from meshbay_hub.api.revocation import NOTIFY_BURST, _notify_budget, _notify_window
node = "budget-node"
_notify_window.pop(node, None)
@@ -265,8 +263,7 @@ def test_a_node_cannot_answer_an_offer_it_was_never_sent():
"""
import asyncio
- from meshbay_hub.api.signaling import (
- _answer_owner, _webrtc_answers, handle_webrtc_answer)
+ from meshbay_hub.api.signaling import _answer_owner, _webrtc_answers, handle_webrtc_answer
loop = asyncio.new_event_loop()
try:
@@ -657,6 +654,7 @@ async def test_a_member_still_reaches_the_node_they_share_a_group_with(client):
class _AnsweringWS:
async def send_text(self, text):
import json as _json
+
from meshbay_hub.api.signaling import handle_webrtc_answer
msg = _json.loads(text)
answered.append(msg)
diff --git a/packages/meshbay-hub/tests/test_captcha_host_check.py b/packages/meshbay-hub/tests/test_captcha_host_check.py
index 68cad34..778009f 100644
--- a/packages/meshbay-hub/tests/test_captcha_host_check.py
+++ b/packages/meshbay-hub/tests/test_captcha_host_check.py
@@ -31,12 +31,10 @@ TOML list is a typo far more often than an intention.
import json
import pytest
-
from meshbay_hub.captcha import verify_captcha
from meshbay_hub.config import CaptchaConfig, load_config
-
class _Resp:
def __init__(self, payload):
self._payload = payload
diff --git a/packages/meshbay-hub/tests/test_device_auth.py b/packages/meshbay-hub/tests/test_device_auth.py
index e899f12..f9b172e 100644
--- a/packages/meshbay-hub/tests/test_device_auth.py
+++ b/packages/meshbay-hub/tests/test_device_auth.py
@@ -21,9 +21,7 @@ stopped being true.
import base64
import time
-import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
diff --git a/packages/meshbay-hub/tests/test_group_hosting.py b/packages/meshbay-hub/tests/test_group_hosting.py
index c571771..c6111f2 100644
--- a/packages/meshbay-hub/tests/test_group_hosting.py
+++ b/packages/meshbay-hub/tests/test_group_hosting.py
@@ -14,13 +14,12 @@ deleted every group during a hub restart.
import base64
import hashlib
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
import pytest
-from sqlalchemy import select
-
from meshbay_hub.db.models import Group, GroupMember
from meshbay_hub.tasks.cleanup import find_unhosted_groups, prune_unhosted_groups
+from sqlalchemy import select
def _auth_key(password: str, username: str) -> str:
@@ -49,7 +48,7 @@ async def _group(client, owner, name, visibility="private", join_policy=None):
async def _mark_hosted(db_session, group_id, when=None):
g = await db_session.get(Group, group_id)
- g.hosted_at = when or datetime.now(timezone.utc)
+ g.hosted_at = when or datetime.now(UTC)
await db_session.commit()
@@ -134,7 +133,7 @@ async def test_an_unhosted_group_past_the_grace_period_is_collected(client, db_s
gid = (await _group(client, owner, "abandoned")).json()["group_id"]
g = await db_session.get(Group, gid)
- g.created_at = datetime.now(timezone.utc) - timedelta(days=8)
+ g.created_at = datetime.now(UTC) - timedelta(days=8)
await db_session.commit()
gone = await prune_unhosted_groups(db_session)
@@ -149,8 +148,8 @@ async def test_an_old_group_that_was_hosted_is_never_collected(client, db_sessio
gid = (await _group(client, owner, "long-lived")).json()["group_id"]
g = await db_session.get(Group, gid)
- g.created_at = datetime.now(timezone.utc) - timedelta(days=400)
- g.hosted_at = datetime.now(timezone.utc) - timedelta(days=399)
+ g.created_at = datetime.now(UTC) - timedelta(days=400)
+ g.hosted_at = datetime.now(UTC) - timedelta(days=399)
await db_session.commit()
assert await find_unhosted_groups(db_session) == []
@@ -161,7 +160,7 @@ async def test_dry_run_reports_without_deleting(client, db_session):
owner = await _user(client, "reaper4_test")
gid = (await _group(client, owner, "still-here")).json()["group_id"]
g = await db_session.get(Group, gid)
- g.created_at = datetime.now(timezone.utc) - timedelta(days=30)
+ g.created_at = datetime.now(UTC) - timedelta(days=30)
await db_session.commit()
gone = await prune_unhosted_groups(db_session, dry_run=True)
@@ -178,7 +177,7 @@ async def test_collecting_a_group_takes_its_memberships_with_it(client, db_sessi
await client.post(f"/v1/groups/{gid}/members/tagalong", json={}, headers=owner)
g = await db_session.get(Group, gid)
- g.created_at = datetime.now(timezone.utc) - timedelta(days=9)
+ g.created_at = datetime.now(UTC) - timedelta(days=9)
await db_session.commit()
await prune_unhosted_groups(db_session)
@@ -247,7 +246,7 @@ async def test_the_stamp_is_not_moved_by_a_later_reconnection(client, db_session
owner = await _user(client, "stamped2")
gid = (await _group(client, owner, "steady")).json()["group_id"]
- first = datetime.now(timezone.utc) - timedelta(days=30)
+ first = datetime.now(UTC) - timedelta(days=30)
await _mark_hosted([gid])
g = await db_session.get(Group, gid)
g.hosted_at = first
@@ -259,7 +258,7 @@ async def test_the_stamp_is_not_moved_by_a_later_reconnection(client, db_session
await db_session.refresh(g)
# SQLite hands back a naive datetime where PostgreSQL keeps the offset, so
# the comparison is made on common ground rather than on the driver.
- stored = g.hosted_at.replace(tzinfo=timezone.utc) if g.hosted_at.tzinfo is None \
+ stored = g.hosted_at.replace(tzinfo=UTC) if g.hosted_at.tzinfo is None \
else g.hosted_at
assert abs((stored - first).total_seconds()) < 1, "the stamp moved"
diff --git a/packages/meshbay-hub/tests/test_group_leave_and_quota.py b/packages/meshbay-hub/tests/test_group_leave_and_quota.py
index 4431f53..8af830d 100644
--- a/packages/meshbay-hub/tests/test_group_leave_and_quota.py
+++ b/packages/meshbay-hub/tests/test_group_leave_and_quota.py
@@ -14,13 +14,12 @@ removes them, and whoever left still holds the group key they were served.
import base64
import hashlib
-from datetime import datetime, timezone
+from datetime import UTC, datetime
import pytest
-from sqlalchemy import select
-
from meshbay_hub.api.groups import MAX_PUBLIC_GROUPS
from meshbay_hub.db.models import Group, GroupMember, User
+from sqlalchemy import select
def _auth_key(password: str, username: str) -> str:
@@ -61,7 +60,7 @@ async def test_a_member_can_leave(client, db_session):
# Marked hosted, or the member would not see the group in the first place
# and the assertion below would hold whether or not leaving worked.
g = await db_session.get(Group, gid)
- g.hosted_at = datetime.now(timezone.utc)
+ g.hosted_at = datetime.now(UTC)
await db_session.commit()
before = await client.get("/v1/groups/mine", headers=member)
diff --git a/packages/meshbay-hub/tests/test_group_membership.py b/packages/meshbay-hub/tests/test_group_membership.py
index 2761595..ad1b3ab 100644
--- a/packages/meshbay-hub/tests/test_group_membership.py
+++ b/packages/meshbay-hub/tests/test_group_membership.py
@@ -11,10 +11,9 @@ import base64
import hashlib
import pytest
+from meshbay_hub.db.models import GroupMember, User
from sqlalchemy import select
-from meshbay_hub.db.models import Group, GroupMember, User
-
def _auth_key(password: str, username: str) -> str:
salt = hashlib.sha256(f"meshbay:auth:v1:{username}".encode()).digest()
diff --git a/packages/meshbay-hub/tests/test_group_purge.py b/packages/meshbay-hub/tests/test_group_purge.py
index 0611dba..e729297 100644
--- a/packages/meshbay-hub/tests/test_group_purge.py
+++ b/packages/meshbay-hub/tests/test_group_purge.py
@@ -21,13 +21,18 @@ from datetime import UTC, datetime, timedelta
import jwt
import pytest
-from sqlalchemy import delete, func, select, text
-from sqlalchemy.exc import IntegrityError
-
from meshbay_hub.db.models import (
- ContentReport, EmailVerification, Group, GroupMember, IPLog, Notification, User,
+ ContentReport,
+ EmailVerification,
+ Group,
+ GroupMember,
+ IPLog,
+ Notification,
+ User,
)
from meshbay_hub.db.purge import _referencing
+from sqlalchemy import delete, func, select, text
+from sqlalchemy.exc import IntegrityError
SEEDED = {"group_members", "notifications", "email_verifications", "content_reports"}
diff --git a/packages/meshbay-hub/tests/test_groups_self_service.py b/packages/meshbay-hub/tests/test_groups_self_service.py
index f9346c1..a3a8f2d 100644
--- a/packages/meshbay-hub/tests/test_groups_self_service.py
+++ b/packages/meshbay-hub/tests/test_groups_self_service.py
@@ -1,9 +1,10 @@
"""Integration tests for group self-service: create, join, members."""
+from datetime import UTC
+
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
@@ -43,10 +44,11 @@ async def _create_group(client, token, name="test-group", visibility="public",
async def _mark_hosted(db_session, *group_ids):
"""Pretend a node announced these groups, as /v1/nodes/ws would."""
- from datetime import datetime, timezone
+ from datetime import datetime
+
from meshbay_hub.db.models import Group
for gid in group_ids:
- (await db_session.get(Group, gid)).hosted_at = datetime.now(timezone.utc)
+ (await db_session.get(Group, gid)).hosted_at = datetime.now(UTC)
await db_session.commit()
diff --git a/packages/meshbay-hub/tests/test_hub_api.py b/packages/meshbay-hub/tests/test_hub_api.py
index 37e8e4f..9b73701 100644
--- a/packages/meshbay-hub/tests/test_hub_api.py
+++ b/packages/meshbay-hub/tests/test_hub_api.py
@@ -3,13 +3,11 @@ Integration tests for the Hub API.
Uses SQLite in-memory + httpx.AsyncClient — no PostgreSQL, no network.
"""
-import base64
+from datetime import UTC
+
import pytest
-import pytest_asyncio
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-from cryptography.hazmat.primitives import serialization
-
from meshbay_common.crypto import pk_to_b64
from meshbay_hub.api.deps import set_admin_usernames
@@ -32,7 +30,8 @@ async def _announce_signed(client, token: str) -> tuple[str, str]:
The node key is independent of the user's identity key, so this mints a fresh
one and signs the domain-separated announce message with it.
"""
- import base64 as _b64, time as _t
+ import base64 as _b64
+ import time as _t
me = await client.get("/v1/users/me",
headers={"Authorization": f"Bearer {token}"})
@@ -399,9 +398,10 @@ async def test_my_groups(client, db_session):
# A group no node has announced is shown to its owner only — a member would
# otherwise see a name they cannot open. Stamped here so the rest of this
# test is about membership, which is what it was written for.
- from datetime import datetime, timezone
+ from datetime import datetime
+
from meshbay_hub.db.models import Group
- (await db_session.get(Group, group_id)).hosted_at = datetime.now(timezone.utc)
+ (await db_session.get(Group, group_id)).hosted_at = datetime.now(UTC)
await db_session.commit()
# Re-login to get fresh token with group claims
@@ -434,7 +434,6 @@ async def test_my_groups(client, db_session):
@pytest.mark.asyncio
async def test_group_online_nodes(client):
"""GET /v1/groups/{id}/nodes returns online nodes serving the group."""
- import json
from meshbay_hub.api.revocation import _connected_nodes, _node_groups
pk_ed, pk_x, _ = _gen_user_keys()
@@ -541,7 +540,7 @@ async def test_admin_can_revoke(client):
@pytest.mark.asyncio
async def test_email_encrypted_at_rest(client):
"""Email stored in DB must not contain plaintext address."""
- from meshbay_hub.auth import encrypt_email, decrypt_email
+ from meshbay_hub.auth import decrypt_email, encrypt_email
encrypted = encrypt_email("test@example.com")
assert "@" not in encrypted
assert decrypt_email(encrypted) == "test@example.com"
@@ -589,9 +588,10 @@ async def test_password_rehash_on_login(client, app):
user = result.scalar_one()
user.pw_version = 1
# Re-hash with v1 params so verify_password(version=1) succeeds
- from meshbay_hub.auth import _ARGON2_VERSIONS, _ARGON2_KEY_LEN, _ARGON2_LANES
- from cryptography.hazmat.primitives.kdf.argon2 import Argon2id
import os
+
+ from cryptography.hazmat.primitives.kdf.argon2 import Argon2id
+ from meshbay_hub.auth import _ARGON2_KEY_LEN, _ARGON2_LANES, _ARGON2_VERSIONS
salt = os.urandom(16)
params = _ARGON2_VERSIONS[1]
pw_hash = Argon2id(
@@ -760,13 +760,14 @@ async def test_webrtc_signaling_roundtrip(client, app):
@pytest.mark.asyncio
async def test_ip_log_cleanup(app):
"""Old IP log entries are purged by cleanup task."""
- from datetime import datetime, timezone, timedelta
+ from datetime import datetime, timedelta
+
from meshbay_hub.db.engine import get_db
from meshbay_hub.db.models import IPLog
from meshbay_hub.tasks.cleanup import purge_old_ip_logs
async for db in get_db():
- old_ts = datetime.now(timezone.utc) - timedelta(days=400)
+ old_ts = datetime.now(UTC) - timedelta(days=400)
db.add(IPLog(event="test_old", ip_address="1.2.3.4", timestamp=old_ts))
db.add(IPLog(event="test_recent", ip_address="5.6.7.8"))
await db.commit()
@@ -774,7 +775,7 @@ async def test_ip_log_cleanup(app):
deleted = await purge_old_ip_logs(db, retention_days=365)
assert deleted == 1
- from sqlalchemy import select, func
+ from sqlalchemy import func, select
count = (await db.execute(
select(func.count()).where(IPLog.event.in_(["test_old", "test_recent"]))
)).scalar_one()
diff --git a/packages/meshbay-hub/tests/test_login_lockout.py b/packages/meshbay-hub/tests/test_login_lockout.py
index 6f17d98..601edbd 100644
--- a/packages/meshbay-hub/tests/test_login_lockout.py
+++ b/packages/meshbay-hub/tests/test_login_lockout.py
@@ -18,14 +18,13 @@ is `test_availability_between_members.py`, because it takes two accounts.
"""
import asyncio
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
import pytest
-from sqlalchemy import select, update
-
from meshbay_hub.api.deps import set_admin_usernames
from meshbay_hub.db.models import LoginThrottle
from meshbay_hub.login_throttle import _key
+from sqlalchemy import select, update
RIGHT = "r" * 44
WRONG = "w" * 44
@@ -94,7 +93,7 @@ async def test_a_lockout_ends_when_its_window_does(client, db_session):
await db_session.execute(
update(LoginThrottle).where(LoginThrottle.key == _key("dave_test"))
- .values(last_failure_at=datetime.now(timezone.utc) - timedelta(minutes=61)))
+ .values(last_failure_at=datetime.now(UTC) - timedelta(minutes=61)))
await db_session.commit()
assert (await _login(client, "dave_test", RIGHT)).status_code == 200
@@ -106,7 +105,7 @@ async def test_old_failures_do_not_carry_into_a_new_window(client, db_session):
await _fail(client, "erin_test", 3)
await db_session.execute(
update(LoginThrottle).where(LoginThrottle.key == _key("erin_test"))
- .values(last_failure_at=datetime.now(timezone.utc) - timedelta(minutes=61)))
+ .values(last_failure_at=datetime.now(UTC) - timedelta(minutes=61)))
await db_session.commit()
# One stale window of three, then one fresh failure: a count of one, not four.
diff --git a/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py b/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py
index fe6a5ee..a3f9a21 100644
--- a/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py
+++ b/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py
@@ -28,7 +28,6 @@ import base64
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
from meshbay_hub import mail as mail_mod
from meshbay_hub.api import users as users_mod
@@ -316,9 +315,8 @@ async def _signed_in(client, db_session, username: str, email: str) -> dict:
genuinely `pending` here, exactly as it would be in production, and a
pending account cannot log in.
"""
- from sqlalchemy import select, update
-
from meshbay_hub.db.models import User
+ from sqlalchemy import select, update
r = await _register(client, username, email)
assert r.status_code == 201, r.text
@@ -406,9 +404,8 @@ async def test_the_delay_survives_the_verification_row_being_deleted(
json={"email": "c-first@example.test"})
assert r.status_code == 200, r.text
- from sqlalchemy import delete
-
from meshbay_hub.db.models import EmailVerification
+ from sqlalchemy import delete
await db_session.execute(delete(EmailVerification))
await db_session.commit()
@@ -421,9 +418,8 @@ async def test_the_delay_survives_the_verification_row_being_deleted(
# ── The operator's controls ──────────────────────────────────────────────────
async def _admin(client, db_session, username: str) -> dict:
- from sqlalchemy import update
-
from meshbay_hub.db.models import User
+ from sqlalchemy import update
headers = await _signed_in(client, db_session, username,
f"{username}@example.test")
@@ -491,9 +487,8 @@ async def test_an_unknown_mail_setting_is_refused(client, db_session):
@pytest.mark.asyncio
async def test_a_moderator_may_read_the_bounds_but_not_change_them(
client, db_session):
- from sqlalchemy import update
-
from meshbay_hub.db.models import User
+ from sqlalchemy import update
headers = await _signed_in(client, db_session, "mailmod_test",
"mailmod@example.test")
diff --git a/packages/meshbay-hub/tests/test_migrations_reach_head.py b/packages/meshbay-hub/tests/test_migrations_reach_head.py
index 13c5590..7f0d5df 100644
--- a/packages/meshbay-hub/tests/test_migrations_reach_head.py
+++ b/packages/meshbay-hub/tests/test_migrations_reach_head.py
@@ -30,9 +30,8 @@ from pathlib import Path
import pytest
from alembic import command
from alembic.config import Config
-from sqlalchemy import create_engine, inspect
-
from meshbay_hub.db.models import Base
+from sqlalchemy import create_engine, inspect
HUB = Path(__file__).resolve().parents[1]
diff --git a/packages/meshbay-hub/tests/test_node_auth.py b/packages/meshbay-hub/tests/test_node_auth.py
index 4137932..09816de 100644
--- a/packages/meshbay-hub/tests/test_node_auth.py
+++ b/packages/meshbay-hub/tests/test_node_auth.py
@@ -8,9 +8,9 @@ import base64
import time
import pytest
+from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-from cryptography.hazmat.primitives import serialization
def _gen_ed25519():
diff --git a/packages/meshbay-hub/tests/test_node_ws_auth.py b/packages/meshbay-hub/tests/test_node_ws_auth.py
index f3ac3a2..7d96851 100644
--- a/packages/meshbay-hub/tests/test_node_ws_auth.py
+++ b/packages/meshbay-hub/tests/test_node_ws_auth.py
@@ -16,7 +16,6 @@ import base64
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
@@ -405,7 +404,10 @@ async def test_empty_node_cannot_shadow_another_members_group(client):
source for that group, because it is the one clients would reach first.
"""
from meshbay_hub.api.revocation import (
- _authorize_node_ws, _node_groups, get_online_nodes_for_group)
+ _authorize_node_ws,
+ _node_groups,
+ get_online_nodes_for_group,
+ )
host = await _make_user(client, "hoster_test")
guest = await _make_user(client, "guest_test")
diff --git a/packages/meshbay-hub/tests/test_notification_dismissal.py b/packages/meshbay-hub/tests/test_notification_dismissal.py
index 1c9c7b3..d498b4d 100644
--- a/packages/meshbay-hub/tests/test_notification_dismissal.py
+++ b/packages/meshbay-hub/tests/test_notification_dismissal.py
@@ -32,7 +32,6 @@ from pathlib import Path
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
from meshbay_hub.api.deps import set_admin_usernames
diff --git a/packages/meshbay-hub/tests/test_notifications.py b/packages/meshbay-hub/tests/test_notifications.py
index 02aca1c..b87e1d5 100644
--- a/packages/meshbay-hub/tests/test_notifications.py
+++ b/packages/meshbay-hub/tests/test_notifications.py
@@ -3,7 +3,6 @@
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
from meshbay_hub.api.deps import set_admin_usernames
diff --git a/packages/meshbay-hub/tests/test_notifications_behaviour.py b/packages/meshbay-hub/tests/test_notifications_behaviour.py
index a247508..67fd99e 100644
--- a/packages/meshbay-hub/tests/test_notifications_behaviour.py
+++ b/packages/meshbay-hub/tests/test_notifications_behaviour.py
@@ -7,13 +7,12 @@ browser's localStorage and nothing read it), and there was no way to clear the
list.
"""
-import hashlib
import base64
+import hashlib
import pytest
-from sqlalchemy import select
-
from meshbay_hub.db.models import GroupMember, Notification, User
+from sqlalchemy import select
def _auth_key(password: str, username: str) -> str:
diff --git a/packages/meshbay-hub/tests/test_packaging_hub_unit.py b/packages/meshbay-hub/tests/test_packaging_hub_unit.py
index 7d8f5d2..e29164e 100644
--- a/packages/meshbay-hub/tests/test_packaging_hub_unit.py
+++ b/packages/meshbay-hub/tests/test_packaging_hub_unit.py
@@ -85,7 +85,6 @@ def test_the_command_resolves_from_the_installed_package_not_the_checkout():
"""Derived from `meshbay_hub.__file__`, so it is correct in a venv, an RPM
and a checkout alike — which is the whole point of not writing it down."""
import meshbay_hub
-
from meshbay_hub.daemon import migrations_dir
assert migrations_dir() == (
diff --git a/packages/meshbay-hub/tests/test_password_change.py b/packages/meshbay-hub/tests/test_password_change.py
index b2fe586..bfe0c97 100644
--- a/packages/meshbay-hub/tests/test_password_change.py
+++ b/packages/meshbay-hub/tests/test_password_change.py
@@ -11,9 +11,8 @@ import base64
import hashlib
import pytest
-from sqlalchemy import select
-
from meshbay_hub.db.models import IPLog, RefreshToken, User
+from sqlalchemy import select
def _auth_key(password: str, username: str) -> str:
diff --git a/packages/meshbay-hub/tests/test_password_reset.py b/packages/meshbay-hub/tests/test_password_reset.py
index 823807c..b07f77c 100644
--- a/packages/meshbay-hub/tests/test_password_reset.py
+++ b/packages/meshbay-hub/tests/test_password_reset.py
@@ -9,7 +9,7 @@ the recovery key and is not exercised here.
import base64
import time
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
@@ -126,7 +126,7 @@ async def test_an_expired_code_is_refused(client, db_session):
select(User.id).where(User.username == "carol_test"))).scalar_one()
row = (await db_session.execute(select(EmailVerification).where(
EmailVerification.user_id == uid))).scalars().one()
- row.expires_at = datetime.now(timezone.utc) - timedelta(minutes=1)
+ row.expires_at = datetime.now(UTC) - timedelta(minutes=1)
await db_session.commit()
r = await client.post("/v1/users/password/reset", json={
diff --git a/packages/meshbay-hub/tests/test_public_groups_toggle.py b/packages/meshbay-hub/tests/test_public_groups_toggle.py
index 96e3383..dbc6a38 100644
--- a/packages/meshbay-hub/tests/test_public_groups_toggle.py
+++ b/packages/meshbay-hub/tests/test_public_groups_toggle.py
@@ -17,7 +17,7 @@ and their access — plan A, not a purge.
import base64
import hashlib
-from datetime import datetime, timezone
+from datetime import UTC, datetime
import pytest
from meshbay_hub.api.deps import set_admin_usernames
@@ -61,7 +61,7 @@ async def _create_public(client, owner, name):
async def _mark_hosted(db_session, *group_ids):
"""Pretend a node announced these groups, as /v1/nodes/ws would."""
for gid in group_ids:
- (await db_session.get(Group, gid)).hosted_at = datetime.now(timezone.utc)
+ (await db_session.get(Group, gid)).hosted_at = datetime.now(UTC)
await db_session.commit()
diff --git a/packages/meshbay-hub/tests/test_revocation.py b/packages/meshbay-hub/tests/test_revocation.py
index ad9caf4..e2ca5e7 100644
--- a/packages/meshbay-hub/tests/test_revocation.py
+++ b/packages/meshbay-hub/tests/test_revocation.py
@@ -1,11 +1,9 @@
"""Tests for revocation — admin endpoint + token signing."""
-import time
-import pytest
import jwt
+import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
-
from meshbay_common.crypto import pk_to_b64
from meshbay_hub.api.deps import set_admin_usernames
diff --git a/packages/meshbay-hub/tests/test_session_lifetime.py b/packages/meshbay-hub/tests/test_session_lifetime.py
index af73767..3a1f47a 100644
--- a/packages/meshbay-hub/tests/test_session_lifetime.py
+++ b/packages/meshbay-hub/tests/test_session_lifetime.py
@@ -6,13 +6,12 @@ maximum — plus a sign-out the hub honours and "sign out everywhere". The
browser half is `test_browser_idle_signout.py`; this is the hub's.
"""
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
import pytest
-from sqlalchemy import select, update
-
from meshbay_hub.api.deps import set_admin_usernames
from meshbay_hub.db.models import RefreshToken, User
+from sqlalchemy import select, update
AUTH_KEY = "s" * 44
@@ -40,7 +39,7 @@ async def _refresh(client, token):
def _aware(dt):
- return dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc)
+ return dt if dt.tzinfo else dt.replace(tzinfo=UTC)
async def _expiry(db_session, username):
@@ -66,7 +65,7 @@ async def test_the_defaults_are_in_the_panel_and_the_browser_delay_is_public(cli
async def test_a_refresh_token_lasts_the_idle_window(client, db_session):
await _register(client, "idle_window")
await _login(client, "idle_window")
- left = await _expiry(db_session, "idle_window") - datetime.now(timezone.utc)
+ left = await _expiry(db_session, "idle_window") - datetime.now(UTC)
assert timedelta(hours=23, minutes=58) < left <= timedelta(hours=24)
@@ -78,7 +77,7 @@ async def test_the_idle_window_never_undercuts_the_access_token(client, db_sessi
json={"session": {"refresh_idle_hours": 1}})
await _register(client, "short_idle")
await _login(client, "short_idle")
- left = await _expiry(db_session, "short_idle") - datetime.now(timezone.utc)
+ left = await _expiry(db_session, "short_idle") - datetime.now(UTC)
# The test hub's access token lives 3600 s; the floor is that plus an hour.
assert left > timedelta(hours=1, minutes=58)
@@ -98,7 +97,7 @@ async def test_no_session_renews_past_its_maximum(client, db_session):
select(User.id).where(User.username == "long_session"))).scalar_one()
await db_session.execute(
update(RefreshToken).where(RefreshToken.user_id == uid)
- .values(created_at=datetime.now(timezone.utc) - timedelta(hours=721)))
+ .values(created_at=datetime.now(UTC) - timedelta(hours=721)))
await db_session.commit()
r = await _refresh(client, current)
diff --git a/packages/meshbay-hub/tests/test_session_renewal.py b/packages/meshbay-hub/tests/test_session_renewal.py
index 5d4bcfd..7b8c108 100644
--- a/packages/meshbay-hub/tests/test_session_renewal.py
+++ b/packages/meshbay-hub/tests/test_session_renewal.py
@@ -26,9 +26,9 @@ broken client.
"""
import json
+import re
import shutil
import subprocess
-import re
from pathlib import Path
import pytest
diff --git a/packages/meshbay-hub/tests/test_table_rows_measured.py b/packages/meshbay-hub/tests/test_table_rows_measured.py
index 60ec878..f203624 100644
--- a/packages/meshbay-hub/tests/test_table_rows_measured.py
+++ b/packages/meshbay-hub/tests/test_table_rows_measured.py
@@ -16,11 +16,10 @@ rectangles show it does not — which is what this file is for.
"""
import json
+import shutil
import subprocess
from pathlib import Path
-import shutil
-
import pytest
HARNESS = Path(__file__).parent / "harness" / "layout_probe.py"