fix(pling): pylance problems

This commit is contained in:
2026-04-13 18:13:19 +00:00
parent c108ccc8cf
commit 0928aa6d78
2 changed files with 181 additions and 107 deletions
+73 -30
View File
@@ -17,11 +17,11 @@ import time
from dataclasses import dataclass from dataclasses import dataclass
from html.parser import HTMLParser from html.parser import HTMLParser
from pathlib import Path from pathlib import Path
from typing import Dict, Iterable, Optional from typing import Any, Iterable, Optional, Protocol, cast
from urllib.parse import urljoin, urlparse from urllib.parse import urljoin, urlparse
try: try:
import niquests import niquests # pyright: ignore[reportMissingImports]
except ImportError as exc: # pragma: no cover - import guard except ImportError as exc: # pragma: no cover - import guard
print( print(
"ERROR: missing dependency 'niquests'. Install it first, e.g. 'uv add niquests'.", "ERROR: missing dependency 'niquests'. Install it first, e.g. 'uv add niquests'.",
@@ -63,7 +63,7 @@ class PlingUploaderError(RuntimeError):
@dataclass(frozen=True) @dataclass(frozen=True)
class LoginForm: class LoginForm:
action_url: str action_url: str
hidden_fields: Dict[str, str] hidden_fields: dict[str, str]
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -91,13 +91,35 @@ class EditContext:
file_server_owner_id: str file_server_owner_id: str
class ResponseLike(Protocol):
status_code: int | None
url: object
text: str | None
def json(self) -> object: ...
class SessionLike(Protocol):
headers: dict[str, str]
cookies: object
def request(
self,
method: str,
url: str,
*,
timeout: float,
**kwargs: Any,
) -> ResponseLike: ...
class _LoginFormParser(HTMLParser): class _LoginFormParser(HTMLParser):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
self._inside_form = False self._inside_form = False
self._form_action: Optional[str] = None self._form_action: Optional[str] = None
self._form_has_auth_fields = False self._form_has_auth_fields = False
self._form_hidden_inputs: Dict[str, str] = {} self._form_hidden_inputs: dict[str, str] = {}
self.login_form: Optional[LoginForm] = None self.login_form: Optional[LoginForm] = None
def handle_starttag(self, tag: str, attrs: list[tuple[str, Optional[str]]]) -> None: def handle_starttag(self, tag: str, attrs: list[tuple[str, Optional[str]]]) -> None:
@@ -147,7 +169,7 @@ def _redact(key: str, value: object) -> object:
def log_event(level: str, event: str, **fields: object) -> None: def log_event(level: str, event: str, **fields: object) -> None:
payload = { payload: dict[str, object] = {
"level": level.upper(), "level": level.upper(),
"event": event, "event": event,
} }
@@ -163,22 +185,24 @@ def normalize_base_url(base_url: str) -> str:
return normalized return normalized
def _safe_response_context(response: object) -> dict[str, object]: def _safe_response_context(response: ResponseLike) -> dict[str, object]:
status_code = getattr(response, "status_code", "unknown") status_code: object = response.status_code
url = getattr(response, "url", "unknown") if status_code is None:
status_code = "unknown"
url = response.url
return {"status_code": status_code, "url": str(url)} return {"status_code": status_code, "url": str(url)}
def request_with_retries( def request_with_retries(
session: "niquests.Session", session: SessionLike,
method: str, method: str,
url: str, url: str,
*, *,
timeout: float, timeout: float,
max_retries: int, max_retries: int,
retry_on_statuses: Iterable[int] = (429, 500, 502, 503, 504), retry_on_statuses: Iterable[int] = (429, 500, 502, 503, 504),
**kwargs: object, **kwargs: Any,
): ) -> ResponseLike:
attempt = 0 attempt = 0
last_error: Optional[Exception] = None last_error: Optional[Exception] = None
@@ -202,14 +226,15 @@ def request_with_retries(
time.sleep(min(0.5 * attempt, 2.0)) time.sleep(min(0.5 * attempt, 2.0))
continue continue
if response.status_code in retry_on_statuses and attempt <= max_retries: status_code = response.status_code
if isinstance(status_code, int) and status_code in retry_on_statuses and attempt <= max_retries:
log_event( log_event(
"warning", "warning",
"http_retryable_status", "http_retryable_status",
method=method, method=method,
url=url, url=url,
attempt=attempt, attempt=attempt,
status_code=response.status_code, status_code=status_code,
) )
time.sleep(min(0.5 * attempt, 2.0)) time.sleep(min(0.5 * attempt, 2.0))
continue continue
@@ -224,16 +249,26 @@ def request_with_retries(
raise PlingUploaderError(f"HTTP request failed after retries: {method} {url}") raise PlingUploaderError(f"HTTP request failed after retries: {method} {url}")
def parse_json_response(response: object, *, context: str) -> dict[str, object]: def parse_json_response(response: ResponseLike, *, context: str) -> dict[str, object]:
try: try:
data = response.json() # type: ignore[attr-defined] data = response.json()
except Exception as exc: except Exception as exc:
raise PlingUploaderError(f"{context}: expected JSON response.") from exc raise PlingUploaderError(f"{context}: expected JSON response.") from exc
if not isinstance(data, dict): if not isinstance(data, dict):
raise PlingUploaderError(f"{context}: response JSON shape is not an object.") raise PlingUploaderError(f"{context}: response JSON shape is not an object.")
return data normalized: dict[str, object] = {}
for key, value in data.items():
normalized[str(key)] = value
return normalized
def get_response_text(response: ResponseLike, *, context: str) -> str:
text = response.text
if isinstance(text, str):
return text
raise PlingUploaderError(f"{context}: expected text response.")
def parse_login_form(login_html: str, login_url: str) -> LoginForm: def parse_login_form(login_html: str, login_url: str) -> LoginForm:
@@ -476,8 +511,8 @@ def resolve_runtime_config(args: argparse.Namespace) -> RuntimeConfig:
) )
def create_session(base_url: str) -> "niquests.Session": def create_session(base_url: str) -> SessionLike:
session = niquests.Session() session = cast(SessionLike, cast(object, niquests.Session()))
session.headers.update( session.headers.update(
{ {
"User-Agent": ( "User-Agent": (
@@ -489,12 +524,14 @@ def create_session(base_url: str) -> "niquests.Session":
"Accept-Language": "en-US,en;q=0.9", "Accept-Language": "en-US,en;q=0.9",
} }
) )
session.cookies.set("verified", "1", domain=urlparse(base_url).hostname) cookie_setter = getattr(session.cookies, "set", None)
if callable(cookie_setter):
cookie_setter("verified", "1", domain=urlparse(base_url).hostname)
return session return session
def discover_edit_context( def discover_edit_context(
session: "niquests.Session", session: SessionLike,
config: RuntimeConfig, config: RuntimeConfig,
) -> tuple[str, EditContext]: ) -> tuple[str, EditContext]:
login_url = urljoin(config.base_url + "/", LOGIN_PATH.lstrip("/")) login_url = urljoin(config.base_url + "/", LOGIN_PATH.lstrip("/"))
@@ -520,7 +557,8 @@ def discover_edit_context(
) )
log_event("info", "login_page_fetched", **_safe_response_context(login_page)) log_event("info", "login_page_fetched", **_safe_response_context(login_page))
login_form = parse_login_form(login_page.text, login_url) login_page_html = get_response_text(login_page, context="login page")
login_form = parse_login_form(login_page_html, login_url)
form_payload = dict(login_form.hidden_fields) form_payload = dict(login_form.hidden_fields)
form_payload.update({"email": config.username, "password": config.password}) form_payload.update({"email": config.username, "password": config.password})
@@ -534,7 +572,8 @@ def discover_edit_context(
) )
log_event("info", "login_submitted", **_safe_response_context(auth_response)) log_event("info", "login_submitted", **_safe_response_context(auth_response))
if "incorrect login" in auth_response.text.lower(): auth_response_html = get_response_text(auth_response, context="login response")
if "incorrect login" in auth_response_html.lower():
raise PlingUploaderError("Authentication failed: incorrect username or password.") raise PlingUploaderError("Authentication failed: incorrect username or password.")
edit_page = request_with_retries( edit_page = request_with_retries(
@@ -546,7 +585,8 @@ def discover_edit_context(
) )
log_event("info", "edit_page_fetched", **_safe_response_context(edit_page)) log_event("info", "edit_page_fetched", **_safe_response_context(edit_page))
if looks_like_login_page(edit_page.text): edit_page_html = get_response_text(edit_page, context="edit page")
if looks_like_login_page(edit_page_html):
raise PlingUploaderError( raise PlingUploaderError(
"Authentication appears unsuccessful: redirected back to login page." "Authentication appears unsuccessful: redirected back to login page."
) )
@@ -554,7 +594,7 @@ def discover_edit_context(
if str(edit_page.url).rstrip("/") == normalize_base_url(login_url).rstrip("/"): if str(edit_page.url).rstrip("/") == normalize_base_url(login_url).rstrip("/"):
raise PlingUploaderError("Unable to access edit page; received login page URL.") raise PlingUploaderError("Unable to access edit page; received login page URL.")
attrs = extract_required_data_attrs(edit_page.text, project_id=config.project_id) attrs = extract_required_data_attrs(edit_page_html, project_id=config.project_id)
resolved: dict[str, str] = {} resolved: dict[str, str] = {}
for key, value in attrs.items(): for key, value in attrs.items():
@@ -564,9 +604,9 @@ def discover_edit_context(
else: else:
resolved[key] = replaced resolved[key] = replaced
client_id = extract_js_string_var(edit_page.text, "client_id") client_id = extract_js_string_var(edit_page_html, "client_id")
file_uri = extract_js_string_var(edit_page.text, "fileUri") file_uri = extract_js_string_var(edit_page_html, "fileUri")
owner_id = extract_form_append_literal(edit_page.text, "owner_id") owner_id = extract_form_append_literal(edit_page_html, "owner_id")
missing_runtime = [] missing_runtime = []
if not client_id: if not client_id:
@@ -581,6 +621,9 @@ def discover_edit_context(
"Edit page is missing required upload runtime values: " "Edit page is missing required upload runtime values: "
+ ", ".join(missing_runtime) + ", ".join(missing_runtime)
) )
assert client_id is not None
assert file_uri is not None
assert owner_id is not None
context = EditContext( context = EditContext(
add_file_url=resolved["data-addpploadfile-uri"], add_file_url=resolved["data-addpploadfile-uri"],
@@ -613,7 +656,7 @@ def discover_edit_context(
def delete_all_existing_files( def delete_all_existing_files(
session: "niquests.Session", session: SessionLike,
config: RuntimeConfig, config: RuntimeConfig,
edit_url: str, edit_url: str,
context: EditContext, context: EditContext,
@@ -646,7 +689,7 @@ def delete_all_existing_files(
def upload_to_file_server( def upload_to_file_server(
session: "niquests.Session", session: SessionLike,
config: RuntimeConfig, config: RuntimeConfig,
context: EditContext, context: EditContext,
artifact_path: Path, artifact_path: Path,
@@ -691,7 +734,7 @@ def upload_to_file_server(
def register_uploaded_file( def register_uploaded_file(
session: "niquests.Session", session: SessionLike,
config: RuntimeConfig, config: RuntimeConfig,
edit_url: str, edit_url: str,
context: EditContext, context: EditContext,
+108 -77
View File
@@ -1,43 +1,62 @@
import argparse import argparse
import importlib.util import importlib.util
import os
import sys import sys
import tempfile import tempfile
import unittest import unittest
from collections.abc import Callable
from pathlib import Path from pathlib import Path
from types import ModuleType
from typing import cast
SCRIPT_PATH = Path(__file__).resolve().parents[1] / "scripts" / "pling_upload.py" SCRIPT_PATH = Path(__file__).resolve().parents[1] / "scripts" / "pling_upload.py"
SPEC = importlib.util.spec_from_file_location("pling_upload", SCRIPT_PATH) SPEC = importlib.util.spec_from_file_location("pling_upload", SCRIPT_PATH)
assert SPEC is not None and SPEC.loader is not None assert SPEC is not None and SPEC.loader is not None
MOD = importlib.util.module_from_spec(SPEC) MOD = cast(ModuleType, importlib.util.module_from_spec(SPEC))
sys.modules[SPEC.name] = MOD sys.modules[SPEC.name] = MOD
SPEC.loader.exec_module(MOD) SPEC.loader.exec_module(MOD)
resolve_cli_or_env = cast(Callable[..., str | None], getattr(MOD, "resolve_cli_or_env"))
extract_required_data_attrs = cast(
Callable[..., dict[str, str]],
getattr(MOD, "extract_required_data_attrs"),
)
resolve_runtime_config = cast(Callable[[argparse.Namespace], object], getattr(MOD, "resolve_runtime_config"))
run_upload_mode = cast(Callable[[object], int], getattr(MOD, "run_upload_mode"))
delete_all_existing_files = cast(
Callable[[object, object, str, object], None],
getattr(MOD, "delete_all_existing_files"),
)
RuntimeConfig = cast(Callable[..., object], getattr(MOD, "RuntimeConfig"))
EditContext = cast(Callable[..., object], getattr(MOD, "EditContext"))
PlingUploaderError = cast(type[Exception], getattr(MOD, "PlingUploaderError"))
class DummyResponse: class DummyResponse:
def __init__(self, payload): def __init__(self, payload: dict[str, object]) -> None:
self._payload = payload self._payload = payload
def json(self): def json(self) -> dict[str, object]:
return self._payload return self._payload
class PlingUploadTests(unittest.TestCase): class PlingUploadTests(unittest.TestCase):
def test_resolve_cli_or_env_prefers_cli(self): def test_resolve_cli_or_env_prefers_cli(self) -> None:
old = MOD.os.environ.get("PLING_PROJECT_ID") old = os.environ.get("PLING_PROJECT_ID")
MOD.os.environ["PLING_PROJECT_ID"] = "from_env" os.environ["PLING_PROJECT_ID"] = "from_env"
try: try:
value = MOD.resolve_cli_or_env( value = resolve_cli_or_env(
cli_value="from_cli", cli_value="from_cli",
env_key="PLING_PROJECT_ID", env_key="PLING_PROJECT_ID",
) )
self.assertEqual(value, "from_cli") self.assertEqual(value, "from_cli")
finally: finally:
if old is None: if old is None:
MOD.os.environ.pop("PLING_PROJECT_ID", None) os.environ.pop("PLING_PROJECT_ID", None)
else: else:
MOD.os.environ["PLING_PROJECT_ID"] = old os.environ["PLING_PROJECT_ID"] = old
def test_extract_required_data_attrs_falls_back_product_id(self): def test_extract_required_data_attrs_falls_back_product_id(self) -> None:
html = ( html = (
'<div data-addpploadfile-uri="/p/@@project_id@@/addpploadfile/" ' '<div data-addpploadfile-uri="/p/@@project_id@@/addpploadfile/" '
'data-updatepploadfile-uri="/p/@@project_id@@/updatepploadfile/" ' 'data-updatepploadfile-uri="/p/@@project_id@@/updatepploadfile/" '
@@ -45,15 +64,15 @@ class PlingUploadTests(unittest.TestCase):
'data-deletepploadfiles-uri="/p/@@project_id@@/deletepploadfiles/" ' 'data-deletepploadfiles-uri="/p/@@project_id@@/deletepploadfiles/" '
'data-product-id="" data-ppload-collection-id="123"></div>' 'data-product-id="" data-ppload-collection-id="123"></div>'
) )
attrs = MOD.extract_required_data_attrs(html, project_id="42") attrs = extract_required_data_attrs(html, "42")
self.assertEqual(attrs["data-product-id"], "42") self.assertEqual(attrs["data-product-id"], "42")
def test_resolve_runtime_config_requires_files_in_upload_mode(self): def test_resolve_runtime_config_requires_files_in_upload_mode(self) -> None:
old_env = dict(MOD.os.environ) old_env = dict(os.environ)
try: try:
MOD.os.environ["PLING_PROJECT_ID"] = "1" os.environ["PLING_PROJECT_ID"] = "1"
MOD.os.environ["PLING_USERNAME"] = "u" os.environ["PLING_USERNAME"] = "u"
MOD.os.environ["PLING_PASSWORD"] = "p" os.environ["PLING_PASSWORD"] = "p"
args = argparse.Namespace( args = argparse.Namespace(
files=[], files=[],
project_id=None, project_id=None,
@@ -64,15 +83,15 @@ class PlingUploadTests(unittest.TestCase):
max_retries=None, max_retries=None,
dry_run=False, dry_run=False,
) )
with self.assertRaises(MOD.PlingUploaderError): with self.assertRaises(PlingUploaderError):
MOD.resolve_runtime_config(args) resolve_runtime_config(args)
finally: finally:
MOD.os.environ.clear() os.environ.clear()
MOD.os.environ.update(old_env) os.environ.update(old_env)
def test_run_upload_mode_calls_steps_in_order(self): def test_run_upload_mode_calls_steps_in_order(self) -> None:
with tempfile.NamedTemporaryFile(suffix=".md") as tmp: with tempfile.NamedTemporaryFile(suffix=".md") as tmp:
config = MOD.RuntimeConfig( config = RuntimeConfig(
project_id="1", project_id="1",
base_url="https://example.com", base_url="https://example.com",
username="u", username="u",
@@ -82,7 +101,7 @@ class PlingUploadTests(unittest.TestCase):
dry_run=False, dry_run=False,
artifact_paths=[Path(tmp.name)], artifact_paths=[Path(tmp.name)],
) )
context = MOD.EditContext( context = EditContext(
add_file_url="https://example.com/add", add_file_url="https://example.com/add",
update_file_url="https://example.com/update", update_file_url="https://example.com/update",
delete_file_url="https://example.com/delete", delete_file_url="https://example.com/delete",
@@ -94,45 +113,50 @@ class PlingUploadTests(unittest.TestCase):
file_server_owner_id="4", file_server_owner_id="4",
) )
calls = [] calls: list[str] = []
create_session_old = getattr(MOD, "create_session")
create_session_old = MOD.create_session discover_old = getattr(MOD, "discover_edit_context")
discover_old = MOD.discover_edit_context delete_old = getattr(MOD, "delete_all_existing_files")
delete_old = MOD.delete_all_existing_files upload_old = getattr(MOD, "upload_to_file_server")
upload_old = MOD.upload_to_file_server register_old = getattr(MOD, "register_uploaded_file")
register_old = MOD.register_uploaded_file
try: try:
MOD.create_session = lambda _base: object() setattr(MOD, "create_session", lambda _base: object())
MOD.discover_edit_context = lambda _s, _c: ("https://example.com/edit", context) setattr(MOD, "discover_edit_context", lambda _s, _c: ("https://example.com/edit", context))
def fake_delete(_s, _cfg, _edit, _ctx): def fake_delete(_s: object, _cfg: object, _edit: str, _ctx: object) -> None:
calls.append("delete") calls.append("delete")
def fake_upload(_s, _cfg, _ctx, _file): def fake_upload(_s: object, _cfg: object, _ctx: object, _file: Path) -> dict[str, object]:
calls.append("upload") calls.append("upload")
return {"id": "x"} return {"id": "x"}
def fake_register(_s, _cfg, _edit, _ctx, _file): def fake_register(
_s: object,
_cfg: object,
_edit: str,
_ctx: object,
_file: dict[str, object],
) -> dict[str, object]:
calls.append("register") calls.append("register")
return {"id": "x", "name": "test.md"} return {"id": "x", "name": "test.md"}
MOD.delete_all_existing_files = fake_delete setattr(MOD, "delete_all_existing_files", fake_delete)
MOD.upload_to_file_server = fake_upload setattr(MOD, "upload_to_file_server", fake_upload)
MOD.register_uploaded_file = fake_register setattr(MOD, "register_uploaded_file", fake_register)
rc = MOD.run_upload_mode(config) rc = run_upload_mode(config)
self.assertEqual(rc, 0) self.assertEqual(rc, 0)
self.assertEqual(calls, ["delete", "upload", "register"]) self.assertEqual(calls, ["delete", "upload", "register"])
finally: finally:
MOD.create_session = create_session_old setattr(MOD, "create_session", create_session_old)
MOD.discover_edit_context = discover_old setattr(MOD, "discover_edit_context", discover_old)
MOD.delete_all_existing_files = delete_old setattr(MOD, "delete_all_existing_files", delete_old)
MOD.upload_to_file_server = upload_old setattr(MOD, "upload_to_file_server", upload_old)
MOD.register_uploaded_file = register_old setattr(MOD, "register_uploaded_file", register_old)
def test_delete_all_existing_files_errors_on_non_ok(self): def test_delete_all_existing_files_errors_on_non_ok(self) -> None:
config = MOD.RuntimeConfig( config = RuntimeConfig(
project_id="1", project_id="1",
base_url="https://example.com", base_url="https://example.com",
username="u", username="u",
@@ -142,7 +166,7 @@ class PlingUploadTests(unittest.TestCase):
dry_run=False, dry_run=False,
artifact_paths=[Path("/tmp/does-not-matter")], artifact_paths=[Path("/tmp/does-not-matter")],
) )
context = MOD.EditContext( context = EditContext(
add_file_url="https://example.com/add", add_file_url="https://example.com/add",
update_file_url="https://example.com/update", update_file_url="https://example.com/update",
delete_file_url="https://example.com/delete", delete_file_url="https://example.com/delete",
@@ -154,19 +178,19 @@ class PlingUploadTests(unittest.TestCase):
file_server_owner_id="4", file_server_owner_id="4",
) )
old_request = MOD.request_with_retries old_request = getattr(MOD, "request_with_retries")
try: try:
MOD.request_with_retries = lambda *_a, **_kw: DummyResponse({"status": "error"}) setattr(MOD, "request_with_retries", lambda *_a, **_kw: DummyResponse({"status": "error"}))
with self.assertRaises(MOD.PlingUploaderError): with self.assertRaises(PlingUploaderError):
MOD.delete_all_existing_files(object(), config, "https://example.com/edit", context) delete_all_existing_files(object(), config, "https://example.com/edit", context)
finally: finally:
MOD.request_with_retries = old_request setattr(MOD, "request_with_retries", old_request)
def test_run_upload_mode_with_multiple_files(self): def test_run_upload_mode_with_multiple_files(self) -> None:
with tempfile.NamedTemporaryFile(suffix=".md") as tmp1, tempfile.NamedTemporaryFile( with tempfile.NamedTemporaryFile(suffix=".md") as tmp1, tempfile.NamedTemporaryFile(
suffix=".md" suffix=".md"
) as tmp2: ) as tmp2:
config = MOD.RuntimeConfig( config = RuntimeConfig(
project_id="1", project_id="1",
base_url="https://example.com", base_url="https://example.com",
username="u", username="u",
@@ -176,7 +200,7 @@ class PlingUploadTests(unittest.TestCase):
dry_run=False, dry_run=False,
artifact_paths=[Path(tmp1.name), Path(tmp2.name)], artifact_paths=[Path(tmp1.name), Path(tmp2.name)],
) )
context = MOD.EditContext( context = EditContext(
add_file_url="https://example.com/add", add_file_url="https://example.com/add",
update_file_url="https://example.com/update", update_file_url="https://example.com/update",
delete_file_url="https://example.com/delete", delete_file_url="https://example.com/delete",
@@ -188,30 +212,37 @@ class PlingUploadTests(unittest.TestCase):
file_server_owner_id="4", file_server_owner_id="4",
) )
calls = [] calls: list[str] = []
create_session_old = MOD.create_session create_session_old = getattr(MOD, "create_session")
discover_old = MOD.discover_edit_context discover_old = getattr(MOD, "discover_edit_context")
delete_old = MOD.delete_all_existing_files delete_old = getattr(MOD, "delete_all_existing_files")
upload_old = MOD.upload_to_file_server upload_old = getattr(MOD, "upload_to_file_server")
register_old = MOD.register_uploaded_file register_old = getattr(MOD, "register_uploaded_file")
try: try:
MOD.create_session = lambda _base: object() setattr(MOD, "create_session", lambda _base: object())
MOD.discover_edit_context = lambda _s, _c: ("https://example.com/edit", context) setattr(MOD, "discover_edit_context", lambda _s, _c: ("https://example.com/edit", context))
MOD.delete_all_existing_files = lambda *_a, **_kw: calls.append("delete") setattr(MOD, "delete_all_existing_files", lambda *_a, **_kw: calls.append("delete"))
def fake_upload(_s, _cfg, _ctx, file_path): def fake_upload(_s: object, _cfg: object, _ctx: object, file_path: Path) -> dict[str, object]:
calls.append(f"upload:{Path(file_path).name}") calls.append(f"upload:{Path(file_path).name}")
return {"id": Path(file_path).name} return {"id": Path(file_path).name}
def fake_register(_s, _cfg, _edit, _ctx, file_payload): def fake_register(
calls.append(f"register:{file_payload['id']}") _s: object,
return {"id": file_payload["id"], "name": file_payload["id"]} _cfg: object,
_edit: str,
_ctx: object,
file_payload: dict[str, object],
) -> dict[str, object]:
file_id = str(file_payload["id"])
calls.append(f"register:{file_id}")
return {"id": file_id, "name": file_id}
MOD.upload_to_file_server = fake_upload setattr(MOD, "upload_to_file_server", fake_upload)
MOD.register_uploaded_file = fake_register setattr(MOD, "register_uploaded_file", fake_register)
rc = MOD.run_upload_mode(config) rc = run_upload_mode(config)
self.assertEqual(rc, 0) self.assertEqual(rc, 0)
self.assertEqual( self.assertEqual(
calls, calls,
@@ -224,12 +255,12 @@ class PlingUploadTests(unittest.TestCase):
], ],
) )
finally: finally:
MOD.create_session = create_session_old setattr(MOD, "create_session", create_session_old)
MOD.discover_edit_context = discover_old setattr(MOD, "discover_edit_context", discover_old)
MOD.delete_all_existing_files = delete_old setattr(MOD, "delete_all_existing_files", delete_old)
MOD.upload_to_file_server = upload_old setattr(MOD, "upload_to_file_server", upload_old)
MOD.register_uploaded_file = register_old setattr(MOD, "register_uploaded_file", register_old)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() _ = unittest.main()