fix: restore Python 3.10/3.11 support and report MCP version
Testing / test (3.10) (push) Successful in 48s
Testing / test (3.12) (push) Successful in 47s
Testing / test (3.14) (push) Successful in 1m7s
Testing / remote-protocol-compat (0.15.0) (push) Successful in 6m59s
Testing / remote-protocol-compat (0.16.0) (push) Successful in 6m47s
Testing / test (3.15) (push) Successful in 6m20s
Testing / test (3.10) (push) Successful in 48s
Testing / test (3.12) (push) Successful in 47s
Testing / test (3.14) (push) Successful in 1m7s
Testing / remote-protocol-compat (0.15.0) (push) Successful in 6m59s
Testing / remote-protocol-compat (0.16.0) (push) Successful in 6m47s
Testing / test (3.15) (push) Successful in 6m20s
- Drop backslash from f-string expression in markdown/html.py - That syntax needs 3.12+ (PEP 701) and broke import on 3.10/3.11 - Add Python matrix 3.10/3.12/3.14/3.15 to the Gitea testing workflow - Pass project_version() to MCPServer; serverInfo.version was empty - Cover the reported version with an in-memory MCP client test - Swap deprecated click.get_text_stream for sys.stdin.isatty() - Add explicit encoding to native host shim and manifest writes - Add explicit encoding to the registry lock file open - Add explicit encoding to every read_text/write_text call in tests - Bump version to 0.16.10 in pyproject.toml and extension/manifest.json - Move .python-version to 3.15 and refresh uv.lock Extension code is unchanged; only the manifest version string moved. Verified with 778 tests on 3.10 through 3.15, plus a strict run using -X warn_default_encoding with EncodingWarning and DeprecationWarning as errors.
This commit is contained in:
@@ -8,14 +8,14 @@ def read_built_background() -> str:
|
||||
background_path = ROOT / "extension" / "background.js"
|
||||
if not background_path.exists():
|
||||
pytest.skip("extension/background.js is a generated build artifact; run npm run build:extension")
|
||||
return background_path.read_text()
|
||||
return background_path.read_text(encoding="utf-8")
|
||||
|
||||
def test_extension_retries_error_page_script_injection_before_failing():
|
||||
# core.ts was split into a core/ subfolder during the structure refactor:
|
||||
# the URL/error classifiers live in core/errors.ts and the executeScript
|
||||
# retry wrapper (which calls isTransientScriptError) lives in core/scripting.ts.
|
||||
errors = (ROOT / "extension" / "src" / "core" / "errors.ts").read_text()
|
||||
scripting = (ROOT / "extension" / "src" / "core" / "scripting.ts").read_text()
|
||||
errors = (ROOT / "extension" / "src" / "core" / "errors.ts").read_text(encoding="utf-8")
|
||||
scripting = (ROOT / "extension" / "src" / "core" / "scripting.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "isBrowserErrorUrl" in errors
|
||||
assert "isErrorPageScriptError" in errors
|
||||
@@ -27,7 +27,7 @@ def test_extension_retries_error_page_script_injection_before_failing():
|
||||
assert "isTransientScriptError(e)" in scripting
|
||||
|
||||
def test_read_only_dom_commands_have_error_page_fallbacks():
|
||||
dom = (ROOT / "extension" / "src" / "commands" / "dom.ts").read_text()
|
||||
dom = (ROOT / "extension" / "src" / "commands" / "dom.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "fallbackForErrorPageDomOp" in dom
|
||||
assert 'case "domExists":' in dom
|
||||
@@ -40,8 +40,8 @@ def test_read_only_dom_commands_have_error_page_fallbacks():
|
||||
def test_navigation_and_tabs_report_browser_error_pages():
|
||||
# tabs.watch_url (which reports tab error pages) moved into the read-only
|
||||
# TabsQueryCommands class in tabs-query.ts during the structure refactor.
|
||||
tabs = (ROOT / "extension" / "src" / "commands" / "tabs-query.ts").read_text()
|
||||
navigation = (ROOT / "extension" / "src" / "commands" / "navigation.ts").read_text()
|
||||
tabs = (ROOT / "extension" / "src" / "commands" / "tabs-query.ts").read_text(encoding="utf-8")
|
||||
navigation = (ROOT / "extension" / "src" / "commands" / "navigation.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "lastUrl" in tabs
|
||||
assert "lastStatus" in tabs
|
||||
@@ -56,10 +56,10 @@ def test_large_extension_operations_yield_between_batches():
|
||||
# batch loop (cancel-check -> batch call -> progress -> yield) was then
|
||||
# centralized into the processInBatches() helper in core/throttle.ts, so the
|
||||
# command modules call that instead of inlining the loop.
|
||||
core = (ROOT / "extension" / "src" / "core" / "throttle.ts").read_text()
|
||||
tabs = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text()
|
||||
groups = (ROOT / "extension" / "src" / "commands" / "groups.ts").read_text()
|
||||
session = (ROOT / "extension" / "src" / "commands" / "session.ts").read_text()
|
||||
core = (ROOT / "extension" / "src" / "core" / "throttle.ts").read_text(encoding="utf-8")
|
||||
tabs = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text(encoding="utf-8")
|
||||
groups = (ROOT / "extension" / "src" / "commands" / "groups.ts").read_text(encoding="utf-8")
|
||||
session = (ROOT / "extension" / "src" / "commands" / "session.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "yieldForLargeOperation" in core
|
||||
assert "getLargeOperationThrottle" in core
|
||||
@@ -105,10 +105,10 @@ def test_large_extension_operations_yield_between_batches():
|
||||
# and the command registry/groups during the class-based refactor. The
|
||||
# behavior is identical; assert the defining patterns still exist in their
|
||||
# new homes.
|
||||
jobs_module = (ROOT / "extension" / "src" / "classes" / "JobManager.ts").read_text()
|
||||
connection = (ROOT / "extension" / "src" / "classes" / "NativeConnection.ts").read_text()
|
||||
perf = (ROOT / "extension" / "src" / "commands" / "perf.ts").read_text()
|
||||
tabs_module = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text()
|
||||
jobs_module = (ROOT / "extension" / "src" / "classes" / "JobManager.ts").read_text(encoding="utf-8")
|
||||
connection = (ROOT / "extension" / "src" / "classes" / "NativeConnection.ts").read_text(encoding="utf-8")
|
||||
perf = (ROOT / "extension" / "src" / "commands" / "perf.ts").read_text(encoding="utf-8")
|
||||
tabs_module = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "background: true" in tabs_module # background command flag (was BACKGROUND_COMMANDS)
|
||||
assert "persistJobs" in jobs_module
|
||||
@@ -120,8 +120,8 @@ def test_large_extension_operations_yield_between_batches():
|
||||
assert "__background" in connection
|
||||
|
||||
def test_tab_activation_open_and_merge_do_not_steal_audible_video_window():
|
||||
tabs = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text()
|
||||
navigation = (ROOT / "extension" / "src" / "commands" / "navigation.ts").read_text()
|
||||
tabs = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text(encoding="utf-8")
|
||||
navigation = (ROOT / "extension" / "src" / "commands" / "navigation.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "await chrome.windows.update(tab.windowId, { focused: true });" not in tabs
|
||||
assert "active: Boolean(focus) && !background" in navigation
|
||||
@@ -151,8 +151,8 @@ def test_session_autosave_is_debounced_and_non_overlapping():
|
||||
# AutoSaveManager (autosave.ts) during the structure refactor; the shared
|
||||
# snapshot/signature helpers live in session-snapshot.ts. Behavior is
|
||||
# identical — the defining patterns just live in their new homes.
|
||||
autosave = (ROOT / "extension" / "src" / "commands" / "autosave.ts").read_text()
|
||||
snapshot = (ROOT / "extension" / "src" / "commands" / "session-snapshot.ts").read_text()
|
||||
autosave = (ROOT / "extension" / "src" / "commands" / "autosave.ts").read_text(encoding="utf-8")
|
||||
snapshot = (ROOT / "extension" / "src" / "commands" / "session-snapshot.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "autoSaveTimer" in autosave
|
||||
assert "autoSaveInFlight" in autosave
|
||||
@@ -172,12 +172,12 @@ def test_session_autosave_is_debounced_and_non_overlapping():
|
||||
assert "clearTimeout(this.autoSaveTimer)" in autosave
|
||||
|
||||
def test_cli_and_sdk_expose_gentle_restore_controls():
|
||||
session_cli = (ROOT / "browser_cli" / "commands" / "session.py").read_text()
|
||||
tabs_cli = (ROOT / "browser_cli" / "commands" / "tabs.py").read_text()
|
||||
groups_cli = (ROOT / "browser_cli" / "commands" / "groups.py").read_text()
|
||||
commands_init = (ROOT / "browser_cli" / "commands" / "__init__.py").read_text()
|
||||
sdk_session = (ROOT / "browser_cli" / "sdk" / "session.py").read_text()
|
||||
sdk_perf = (ROOT / "browser_cli" / "sdk" / "perf.py").read_text()
|
||||
session_cli = (ROOT / "browser_cli" / "commands" / "session.py").read_text(encoding="utf-8")
|
||||
tabs_cli = (ROOT / "browser_cli" / "commands" / "tabs.py").read_text(encoding="utf-8")
|
||||
groups_cli = (ROOT / "browser_cli" / "commands" / "groups.py").read_text(encoding="utf-8")
|
||||
commands_init = (ROOT / "browser_cli" / "commands" / "__init__.py").read_text(encoding="utf-8")
|
||||
sdk_session = (ROOT / "browser_cli" / "sdk" / "session.py").read_text(encoding="utf-8")
|
||||
sdk_perf = (ROOT / "browser_cli" / "sdk" / "perf.py").read_text(encoding="utf-8")
|
||||
|
||||
# The --gentle-mode flag is defined once via the shared gentle_mode_option helper.
|
||||
assert '"--gentle-mode"' in commands_init
|
||||
@@ -200,8 +200,8 @@ def test_cli_and_sdk_expose_gentle_restore_controls():
|
||||
assert "def status" in sdk_perf
|
||||
assert "def set_profile" in sdk_perf
|
||||
|
||||
perf_cli = (ROOT / "browser_cli" / "commands" / "perf.py").read_text()
|
||||
root_cli = (ROOT / "browser_cli" / "cli.py").read_text()
|
||||
perf_cli = (ROOT / "browser_cli" / "commands" / "perf.py").read_text(encoding="utf-8")
|
||||
root_cli = (ROOT / "browser_cli" / "cli.py").read_text(encoding="utf-8")
|
||||
assert "perf_group" in perf_cli
|
||||
assert "perf.status" in perf_cli
|
||||
assert "perf.set_profile" in perf_cli
|
||||
|
||||
Reference in New Issue
Block a user