From cf47e004c7437ca4a6015f599a91cc2edb569f9d Mon Sep 17 00:00:00 2001 From: dylan Date: Tue, 7 Oct 2025 13:13:50 -0700 Subject: [PATCH 01/13] ci: bump ci to 3.14 --- .github/workflows/test_be.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test_be.yaml b/.github/workflows/test_be.yaml index 30c733f72e2..c19e3429330 100644 --- a/.github/workflows/test_be.yaml +++ b/.github/workflows/test_be.yaml @@ -59,11 +59,15 @@ jobs: matrix: os: [ubuntu-latest, macos-latest, windows-latest] dependencies: ["core", "core,optional"] - python-version: ["3.9"] + python-version: ["3.10"] include: + # TODO: deprecate 3.9 after 2025-11-01 - os: ubuntu-latest - python-version: "3.10" + python-version: "3.9" dependencies: "core" + - os: ubuntu-latest + python-version: "3.10" + dependencies: "minimal" - os: ubuntu-latest python-version: "3.11" dependencies: "core" @@ -74,7 +78,7 @@ jobs: python-version: "3.13" dependencies: "core" - os: ubuntu-latest - python-version: "3.9" + python-version: "3.14" dependencies: "core,optional" - os: ubuntu-latest python-version: "3.10" @@ -89,8 +93,8 @@ jobs: python-version: "3.13" dependencies: "core,optional" - os: ubuntu-latest - python-version: "3.9" - dependencies: "minimal" + python-version: "3.14" + dependencies: "core,optional" steps: - name: 🛑 Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 From f1ee80b30ced8f45f701bc41c3bdd1cca2347aa3 Mon Sep 17 00:00:00 2001 From: dylan Date: Tue, 7 Oct 2025 13:28:04 -0700 Subject: [PATCH 02/13] comments: note where in the code base we mentione python 3.9 --- marimo/_messaging/ops.py | 2 +- marimo/_plugins/ui/_core/registry.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/marimo/_messaging/ops.py b/marimo/_messaging/ops.py index 6ffcb27cc7a..4f3844f3d67 100644 --- a/marimo/_messaging/ops.py +++ b/marimo/_messaging/ops.py @@ -614,7 +614,7 @@ class ColumnPreview(msgspec.Struct): # We shouldn't need to make table_name and column_name have default values. -# We can use kw_only=True once we drop support for Python 3.9. +# We can use kw_only=True once we drop support for Python 3.9 (25-11-01). class DataColumnPreview(Op, ColumnPreview, tag="data-column-preview"): """Preview of a column in a dataset.""" diff --git a/marimo/_plugins/ui/_core/registry.py b/marimo/_plugins/ui/_core/registry.py index bf3b20b3056..f6c742bb66e 100644 --- a/marimo/_plugins/ui/_core/registry.py +++ b/marimo/_plugins/ui/_core/registry.py @@ -22,7 +22,7 @@ T = TypeVar("T") -# Recursive types don't support | or dict[] in py3.8/3.9 +# Recursive types don't support | or dict[] in py3.8/3.9 (25-11-01) LensValue: TypeAlias = Union[T, dict[str, "LensValue[T]"]] From 24d107fa7bba8a314c774fc92c402612e9a84d19 Mon Sep 17 00:00:00 2001 From: dylan Date: Tue, 7 Oct 2025 14:18:47 -0700 Subject: [PATCH 03/13] bump: pyproject --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8f8449195b9..bcbb61fa422 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3 :: Only", ] @@ -206,7 +207,7 @@ extra-dependencies = [ ] [[tool.hatch.envs.test.matrix]] -python = ["3.9", "3.10", "3.11", "3.12", "3.13"] +python = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] [tool.hatch.envs.test.scripts] test = "pytest{env:HATCH_TEST_ARGS:} {args:tests}" @@ -282,7 +283,7 @@ extra-dependencies = [ ] [[tool.hatch.envs.test-optional.matrix]] -python = ["3.9", "3.10", "3.11", "3.12", "3.13"] +python = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] [tool.hatch.envs.docs] dependencies = [ From 8cd63a5b84c42283fb872d09ba4d3d09e621237b Mon Sep 17 00:00:00 2001 From: dylan Date: Sun, 12 Oct 2025 15:40:33 -0400 Subject: [PATCH 04/13] ci: fix setup for python 314 --- .github/workflows/test_be.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test_be.yaml b/.github/workflows/test_be.yaml index c19e3429330..bf33db8a952 100644 --- a/.github/workflows/test_be.yaml +++ b/.github/workflows/test_be.yaml @@ -119,6 +119,11 @@ jobs: if: ${{ matrix.python-version == '3.12' }} run: hatch run typecheck:check + # Required since python3.14 not pulled automatically for now. + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + # Test with base dependencies - name: Test with base dependencies if: ${{ matrix.dependencies == 'core' }} From 1aa4f6a60bb3521962f7246255f412d347412d35 Mon Sep 17 00:00:00 2001 From: dylan Date: Sun, 12 Oct 2025 16:22:27 -0400 Subject: [PATCH 05/13] bump: matplotlib --- .github/workflows/test_be.yaml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_be.yaml b/.github/workflows/test_be.yaml index bf33db8a952..5ba22b48f3a 100644 --- a/.github/workflows/test_be.yaml +++ b/.github/workflows/test_be.yaml @@ -79,7 +79,7 @@ jobs: dependencies: "core" - os: ubuntu-latest python-version: "3.14" - dependencies: "core,optional" + dependencies: "core" - os: ubuntu-latest python-version: "3.10" dependencies: "core,optional" diff --git a/pyproject.toml b/pyproject.toml index bcbb61fa422..f60ee59d91e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -196,7 +196,7 @@ extra-dependencies = [ "hypothesis~=6.102.1", # For server testing "httpx~=0.27.0", - "matplotlib~=3.9.2", + "matplotlib~=3.10.6", "pytest~=8.3.4", "pytest-timeout~=2.3.1", "pytest-codecov~=0.6.1", From 51cc52fbd63a980ccd03ec5e0503d45322cc12e4 Mon Sep 17 00:00:00 2001 From: dylan Date: Sun, 12 Oct 2025 16:26:38 -0400 Subject: [PATCH 06/13] bump: pillow --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f60ee59d91e..5dfc92320c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -197,6 +197,8 @@ extra-dependencies = [ # For server testing "httpx~=0.27.0", "matplotlib~=3.10.6", + # Forced for modern matplotlib. + "pillow>=9", "pytest~=8.3.4", "pytest-timeout~=2.3.1", "pytest-codecov~=0.6.1", From 282433342ecfb37e07a4d7ab9c45053bedfa6330 Mon Sep 17 00:00:00 2001 From: dylan Date: Sun, 12 Oct 2025 16:37:45 -0400 Subject: [PATCH 07/13] ci: remove 3.9 (only 2 weeks out) --- .github/workflows/test_be.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test_be.yaml b/.github/workflows/test_be.yaml index 5ba22b48f3a..6241956dfdf 100644 --- a/.github/workflows/test_be.yaml +++ b/.github/workflows/test_be.yaml @@ -61,10 +61,6 @@ jobs: dependencies: ["core", "core,optional"] python-version: ["3.10"] include: - # TODO: deprecate 3.9 after 2025-11-01 - - os: ubuntu-latest - python-version: "3.9" - dependencies: "core" - os: ubuntu-latest python-version: "3.10" dependencies: "minimal" From ff93a319d6a4c086608a2250d589e2b19400155d Mon Sep 17 00:00:00 2001 From: dylan Date: Sun, 12 Oct 2025 16:37:55 -0400 Subject: [PATCH 08/13] bump: codecov --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5dfc92320c0..c1ea6f405b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -196,12 +196,12 @@ extra-dependencies = [ "hypothesis~=6.102.1", # For server testing "httpx~=0.27.0", - "matplotlib~=3.10.6", + "matplotlib~=3.10.7", # Forced for modern matplotlib. "pillow>=9", "pytest~=8.3.4", "pytest-timeout~=2.3.1", - "pytest-codecov~=0.6.1", + "pytest-codecov~=0.7.0", "pytest-rerunfailures~=15.1", "pytest-asyncio~=0.26.0", "pytest-picked>=0.5.1", From 71393f4af1b7e8fc034cb29b6bb5f383ae0285a7 Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 13 Oct 2025 13:31:21 -0400 Subject: [PATCH 09/13] fix: bound loro requirement --- pixi.lock | 4 ++-- pyproject.toml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pixi.lock b/pixi.lock index 1dccd201342..fd64765305c 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1101,7 +1101,7 @@ packages: - pypi: ./ name: marimo version: 0.16.5 - sha256: 5558c60bca6ce981e35b3b1a108f3e8f289b0e9df1a04a4020be1edfc92f795b + sha256: b8561aba1c9a637dab6d94e436aaa8372325a3bef25d0b796efff990a60d4b66 requires_dist: - click>=8.0,<9 - jedi>=0.18.0 @@ -1113,7 +1113,7 @@ packages: - uvicorn>=0.22.0,<0.36.0 - starlette>=0.35.0,!=0.36.0 - websockets>=14.2.0 - - loro>=1.5.0 ; python_full_version >= '3.11' + - loro>=1.5.0 ; python_full_version >= '3.11' and python_full_version < '3.14' - typing-extensions>=4.4.0 ; python_full_version < '3.11' - docutils>=0.16.0 - psutil>=5.0 diff --git a/pyproject.toml b/pyproject.toml index a30df0d3272..231cf4b1e4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ dependencies = [ # websockets for use with starlette, and for lsp "websockets >= 14.2.0", # loro for collaborative editing - "loro>=1.5.0; python_version >= '3.11'", + "loro>=1.5.0; python_version >= '3.11' and python_version < '3.14'", # python <=3.10 compatibility "typing_extensions>=4.4.0; python_version < '3.11'", # for rst parsing; lowerbound determined by awscli requiring < 0.17, @@ -196,6 +196,7 @@ extra-dependencies = [ "hypothesis~=6.102.1", # For server testing "httpx~=0.27.0", + "urllib3~=2.5.0", "matplotlib~=3.10.7", # Forced for modern matplotlib. "pillow>=9", From 2b3debbbcf4bb48e360a0356f6847dab3c36ba67 Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 13 Oct 2025 13:57:19 -0400 Subject: [PATCH 10/13] bump: pygments --- pixi.lock | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pixi.lock b/pixi.lock index fd64765305c..12dcf9b355e 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1101,13 +1101,13 @@ packages: - pypi: ./ name: marimo version: 0.16.5 - sha256: b8561aba1c9a637dab6d94e436aaa8372325a3bef25d0b796efff990a60d4b66 + sha256: 00660bfd80ed86fe2742590ac0f59cbd50d764290e29293c6a16beb233d9632b requires_dist: - click>=8.0,<9 - jedi>=0.18.0 - markdown>=3.6,<4 - pymdown-extensions>=10.15,<11 - - pygments>=2.13,<3 + - pygments>=2.19,<3 - tomlkit>=0.12.0 - pyyaml>=6.0 - uvicorn>=0.22.0,<0.36.0 diff --git a/pyproject.toml b/pyproject.toml index 231cf4b1e4a..322676522ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ dependencies = [ # Pinned to specific version for introduction of codeblock handling. "pymdown-extensions>=10.15,<11", # syntax highlighting of code in markdown - "pygments>=2.13,<3", + "pygments>=2.19,<3", # for reading, writing configs "tomlkit>= 0.12.0", # for managing frontmatter headers in markdown From 309e11e88565053b842a25e14f8c4d3d0398400f Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 13 Oct 2025 14:07:30 -0400 Subject: [PATCH 11/13] fix: guard loro tests --- tests/_server/api/endpoints/test_ws_rtc.py | 6 +++--- tests/_server/rtc/test_rtc_doc.py | 24 ++++++++++------------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/tests/_server/api/endpoints/test_ws_rtc.py b/tests/_server/api/endpoints/test_ws_rtc.py index 760a6b1aaf2..9456bd9a0b4 100644 --- a/tests/_server/api/endpoints/test_ws_rtc.py +++ b/tests/_server/api/endpoints/test_ws_rtc.py @@ -110,7 +110,7 @@ def rtc_enabled(config: UserConfigManager): ws_2_sync = "/ws_sync?session_id=456&access_token=fake-token" -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_loro_sync(client: TestClient) -> None: """Test that Loro-CRDT sync works between multiple clients""" @@ -147,7 +147,7 @@ async def test_loro_sync(client: TestClient) -> None: client.post("/api/kernel/shutdown", headers=HEADERS) -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_loro_cleanup_on_session_close( client: TestClient, ) -> None: @@ -192,7 +192,7 @@ async def test_loro_cleanup_on_session_close( client.post("/api/kernel/shutdown", headers=HEADERS) -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_loro_persistence(client: TestClient) -> None: """Test that cell content persists between connections""" from loro import ExportMode, LoroDoc diff --git a/tests/_server/rtc/test_rtc_doc.py b/tests/_server/rtc/test_rtc_doc.py index c96cec72eb4..6d5d4f63e7c 100644 --- a/tests/_server/rtc/test_rtc_doc.py +++ b/tests/_server/rtc/test_rtc_doc.py @@ -9,7 +9,7 @@ from marimo._server.rtc.doc import LoroDocManager from marimo._types.ids import CellId_t -if sys.version_info >= (3, 11): +if sys.version_info >= (3, 11) and sys.version_info < (3, 14): from loro import LoroDoc, LoroText doc_manager = LoroDocManager() @@ -29,7 +29,7 @@ async def setup_doc_manager() -> AsyncGenerator[None, None]: doc_manager.loro_docs_cleaners.clear() -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_quick_reconnection(setup_doc_manager: None) -> None: """Test that quick reconnection properly handles cleanup task cancellation""" del setup_doc_manager @@ -65,7 +65,7 @@ async def test_quick_reconnection(setup_doc_manager: None) -> None: ) # Original client + reconnected client -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_two_users_sync(setup_doc_manager: None) -> None: """Test that two users can connect and sync text properly without duplicates""" del setup_doc_manager @@ -111,7 +111,7 @@ async def test_two_users_sync(setup_doc_manager: None) -> None: assert lang_text_typed.to_string() == "python" -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_concurrent_doc_creation(setup_doc_manager: None) -> None: """Test concurrent doc creation doesn't cause issues""" del setup_doc_manager @@ -130,7 +130,7 @@ async def test_concurrent_doc_creation(setup_doc_manager: None) -> None: assert len(doc_manager.loro_docs) == 1 -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_concurrent_client_operations( setup_doc_manager: None, ) -> None: @@ -157,7 +157,7 @@ async def client_operation(queue: asyncio.Queue[bytes]) -> None: assert len(doc_manager.loro_docs_clients[file_key]) == 0 -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_cleanup_task_management(setup_doc_manager: None) -> None: """Test cleanup task management and cancellation""" del setup_doc_manager @@ -189,7 +189,7 @@ async def test_cleanup_task_management(setup_doc_manager: None) -> None: await doc_manager.remove_client(file_key, new_queue) -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_broadcast_update(setup_doc_manager: None) -> None: """Test broadcast update functionality""" del setup_doc_manager @@ -215,7 +215,7 @@ async def test_broadcast_update(setup_doc_manager: None) -> None: assert await queue.get() == message -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_remove_nonexistent_doc(setup_doc_manager: None) -> None: """Test removing a doc that doesn't exist""" del setup_doc_manager @@ -226,7 +226,7 @@ async def test_remove_nonexistent_doc(setup_doc_manager: None) -> None: assert file_key not in doc_manager.loro_docs_cleaners -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_remove_nonexistent_client(setup_doc_manager: None) -> None: """Test removing a client that doesn't exist""" del setup_doc_manager @@ -236,7 +236,7 @@ async def test_remove_nonexistent_client(setup_doc_manager: None) -> None: assert file_key not in doc_manager.loro_docs_clients -@pytest.mark.skipif("sys.version_info < (3, 11)") +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_concurrent_doc_removal(setup_doc_manager: None) -> None: """Test concurrent doc removal doesn't cause issues""" del setup_doc_manager @@ -254,9 +254,7 @@ async def test_concurrent_doc_removal(setup_doc_manager: None) -> None: assert file_key not in doc_manager.loro_docs_cleaners -@pytest.mark.skipif( - sys.version_info < (3, 11), reason="Python 3.10+ required for Barrier" -) +@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") async def test_prevent_lock_deadlock(setup_doc_manager: None) -> None: """Test that our deadlock prevention measures work correctly. From a7f1e8fc3f2a2c0a54b3f20f801bff29d37adfa4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:08:32 +0000 Subject: [PATCH 12/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/_server/api/endpoints/test_ws_rtc.py | 12 +++++-- tests/_server/rtc/test_rtc_doc.py | 40 ++++++++++++++++------ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/tests/_server/api/endpoints/test_ws_rtc.py b/tests/_server/api/endpoints/test_ws_rtc.py index 9456bd9a0b4..0d74c2a5e1e 100644 --- a/tests/_server/api/endpoints/test_ws_rtc.py +++ b/tests/_server/api/endpoints/test_ws_rtc.py @@ -110,7 +110,9 @@ def rtc_enabled(config: UserConfigManager): ws_2_sync = "/ws_sync?session_id=456&access_token=fake-token" -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_loro_sync(client: TestClient) -> None: """Test that Loro-CRDT sync works between multiple clients""" @@ -147,7 +149,9 @@ async def test_loro_sync(client: TestClient) -> None: client.post("/api/kernel/shutdown", headers=HEADERS) -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_loro_cleanup_on_session_close( client: TestClient, ) -> None: @@ -192,7 +196,9 @@ async def test_loro_cleanup_on_session_close( client.post("/api/kernel/shutdown", headers=HEADERS) -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_loro_persistence(client: TestClient) -> None: """Test that cell content persists between connections""" from loro import ExportMode, LoroDoc diff --git a/tests/_server/rtc/test_rtc_doc.py b/tests/_server/rtc/test_rtc_doc.py index 6d5d4f63e7c..64831a70c88 100644 --- a/tests/_server/rtc/test_rtc_doc.py +++ b/tests/_server/rtc/test_rtc_doc.py @@ -29,7 +29,9 @@ async def setup_doc_manager() -> AsyncGenerator[None, None]: doc_manager.loro_docs_cleaners.clear() -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_quick_reconnection(setup_doc_manager: None) -> None: """Test that quick reconnection properly handles cleanup task cancellation""" del setup_doc_manager @@ -65,7 +67,9 @@ async def test_quick_reconnection(setup_doc_manager: None) -> None: ) # Original client + reconnected client -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_two_users_sync(setup_doc_manager: None) -> None: """Test that two users can connect and sync text properly without duplicates""" del setup_doc_manager @@ -111,7 +115,9 @@ async def test_two_users_sync(setup_doc_manager: None) -> None: assert lang_text_typed.to_string() == "python" -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_concurrent_doc_creation(setup_doc_manager: None) -> None: """Test concurrent doc creation doesn't cause issues""" del setup_doc_manager @@ -130,7 +136,9 @@ async def test_concurrent_doc_creation(setup_doc_manager: None) -> None: assert len(doc_manager.loro_docs) == 1 -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_concurrent_client_operations( setup_doc_manager: None, ) -> None: @@ -157,7 +165,9 @@ async def client_operation(queue: asyncio.Queue[bytes]) -> None: assert len(doc_manager.loro_docs_clients[file_key]) == 0 -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_cleanup_task_management(setup_doc_manager: None) -> None: """Test cleanup task management and cancellation""" del setup_doc_manager @@ -189,7 +199,9 @@ async def test_cleanup_task_management(setup_doc_manager: None) -> None: await doc_manager.remove_client(file_key, new_queue) -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_broadcast_update(setup_doc_manager: None) -> None: """Test broadcast update functionality""" del setup_doc_manager @@ -215,7 +227,9 @@ async def test_broadcast_update(setup_doc_manager: None) -> None: assert await queue.get() == message -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_remove_nonexistent_doc(setup_doc_manager: None) -> None: """Test removing a doc that doesn't exist""" del setup_doc_manager @@ -226,7 +240,9 @@ async def test_remove_nonexistent_doc(setup_doc_manager: None) -> None: assert file_key not in doc_manager.loro_docs_cleaners -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_remove_nonexistent_client(setup_doc_manager: None) -> None: """Test removing a client that doesn't exist""" del setup_doc_manager @@ -236,7 +252,9 @@ async def test_remove_nonexistent_client(setup_doc_manager: None) -> None: assert file_key not in doc_manager.loro_docs_clients -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_concurrent_doc_removal(setup_doc_manager: None) -> None: """Test concurrent doc removal doesn't cause issues""" del setup_doc_manager @@ -254,7 +272,9 @@ async def test_concurrent_doc_removal(setup_doc_manager: None) -> None: assert file_key not in doc_manager.loro_docs_cleaners -@pytest.mark.skipif("sys.version_info < (3, 11) or sys.version_info >= (3, 14)") +@pytest.mark.skipif( + "sys.version_info < (3, 11) or sys.version_info >= (3, 14)" +) async def test_prevent_lock_deadlock(setup_doc_manager: None) -> None: """Test that our deadlock prevention measures work correctly. From be5ddbea7efe5334d63d30a765ee7a4c078dc91c Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 13 Oct 2025 14:50:50 -0400 Subject: [PATCH 13/13] ci: remove 3.14 optional --- .github/workflows/test_be.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/test_be.yaml b/.github/workflows/test_be.yaml index 6241956dfdf..7ea6115430c 100644 --- a/.github/workflows/test_be.yaml +++ b/.github/workflows/test_be.yaml @@ -88,9 +88,7 @@ jobs: - os: ubuntu-latest python-version: "3.13" dependencies: "core,optional" - - os: ubuntu-latest - python-version: "3.14" - dependencies: "core,optional" + # TODO: Add in 3.14 optional once there is broader wheel support steps: - name: 🛑 Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1