diff --git a/.github/py-shiny/setup/action.yaml b/.github/py-shiny/setup/action.yaml index dfa398f9f..0c50c616e 100644 --- a/.github/py-shiny/setup/action.yaml +++ b/.github/py-shiny/setup/action.yaml @@ -4,7 +4,7 @@ inputs: python-version: description: 'Python version to use' required: false - default: "3.12" + default: "3.13" runs: using: "composite" steps: @@ -39,12 +39,6 @@ runs: run: | make ci-install-wheel - - name: Install backports.tarfile - if: ${{ startsWith(inputs.python-version, '3.8') }} - shell: bash - run: | - uv pip install backports.tarfile - - name: Pip list shell: bash run: | diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 818fe47e1..8d1d3c037 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.12"] + python-version: ["3.13"] fail-fast: false steps: diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index c726b458d..714caf0b0 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -17,7 +17,7 @@ jobs: strategy: matrix: # "3.10" must be a string; otherwise it is interpreted as 3.1. - python-version: ["3.12", "3.11", "3.10", "3.9"] + python-version: ["3.13", "3.12", "3.11", "3.10", "3.9"] os: [ubuntu-latest, windows-latest, macOS-latest] exclude: - python-version: ${{ github.event.pull_request.draft && '3.11' }} @@ -73,7 +73,7 @@ jobs: with: fetch-depth: 0 - name: "Set up Python 3.10" - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" - name: Install dependencies @@ -107,7 +107,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.12", "3.11", "3.10", "3.9"] + python-version: ["3.13", "3.12", "3.11", "3.10", "3.9"] browser: ["chromium", "firefox", "webkit"] exclude: - python-version: ${{ github.event.pull_request.draft && '3.11' }} @@ -117,8 +117,6 @@ jobs: - browser: ${{ github.event.pull_request.draft && 'webkit' }} # There are many unexplained tests that fail on webkit w/ python 3.8, 3.9 # Given the more recent versions of python work, we will exclude this combination - - browser: "webkit" - python-version: "3.8" - browser: "webkit" python-version: "3.9" fail-fast: false @@ -157,7 +155,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.12", "3.11", "3.10", "3.9"] + python-version: ["3.13", "3.12", "3.11", "3.10", "3.9"] browser: ["chromium", "firefox", "webkit"] exclude: - python-version: ${{ github.event.pull_request.draft && '3.11' }} diff --git a/pyproject.toml b/pyproject.toml index c92d781e0..307d230e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dependencies = [ "typing-extensions>=4.10.0", @@ -54,8 +55,8 @@ theme = ["libsass>=0.23.0", "brand_yml>=0.1.0"] test = [ "pytest>=6.2.4", "pytest-asyncio>=0.17.2", - "pytest-playwright>=0.3.0", - "playwright>=1.43.0", + "pytest-playwright>=0.5.2", + "playwright>=1.48.0", "pytest-xdist", "pytest-timeout", "pytest-rerunfailures", @@ -86,7 +87,6 @@ test = [ "faicons", "ridgeplot", "great_tables", - "modin[all]", "polars", "dask[dataframe]", "pyarrow", diff --git a/shiny/_datastructures.py b/shiny/_datastructures.py index f2ac287ef..2a243d418 100644 --- a/shiny/_datastructures.py +++ b/shiny/_datastructures.py @@ -15,8 +15,6 @@ class PriorityQueueFIFO(Generic[T]): """ def __init__(self) -> None: - # Using Tuple instead of tuple because in Python 3.8 and earlier, tuple isn't - # generic self._pq: PriorityQueue[tuple[int, int, T]] = PriorityQueue() self._counter: int = 0 diff --git a/shiny/_utils.py b/shiny/_utils.py index fc0eaa21f..728fd94ec 100644 --- a/shiny/_utils.py +++ b/shiny/_utils.py @@ -72,7 +72,7 @@ def sort_keys_length(x: dict[str, T], descending: bool = False) -> dict[str, T]: def guess_mime_type( - url: "str | os.PathLike[str]", + url: str | os.PathLike[str], default: str = "application/octet-stream", strict: bool = True, ) -> str: @@ -80,8 +80,6 @@ def guess_mime_type( Guess the MIME type of a file. This is a wrapper for mimetypes.guess_type, but it only returns the type (and not encoding), and it allows a default value. """ - # Note that in the parameters above, "os.PathLike[str]" is in quotes to avoid - # "TypeError: 'ABCMeta' object is not subscriptable", in Python<=3.8. if url: # Work around issue #1601, some installations of Windows 10 return text/plain # as the mime type for .js files diff --git a/shiny/render/_render.py b/shiny/render/_render.py index 5cd608f6a..88c796bfc 100644 --- a/shiny/render/_render.py +++ b/shiny/render/_render.py @@ -4,9 +4,6 @@ import os import sys import typing - -# `typing.Dict` sed for python 3.8 compatibility -# Can use `dict` in python >= 3.9 from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, Union, cast from htmltools import Tag, TagAttrValue, TagChild diff --git a/shiny/render/renderer/_renderer.py b/shiny/render/renderer/_renderer.py index b79009c91..ce3cf3e26 100644 --- a/shiny/render/renderer/_renderer.py +++ b/shiny/render/renderer/_renderer.py @@ -336,9 +336,6 @@ def _auto_register(self) -> None: self._auto_registered = True -# Not inheriting from `WrapAsync[[], IT]` as python 3.8 needs typing extensions that -# doesn't support `[]` for a ParamSpec definition. :-( Would be minimal/clean if we -# could do `class AsyncValueFn(WrapAsync[[], IT]):` class AsyncValueFn(Generic[IT]): """ App-supplied output value function which returns type `IT`. diff --git a/tests/playwright/shiny/components/data_frame/data_type/app.py b/tests/playwright/shiny/components/data_frame/data_type/app.py index 50c76b952..ffcee1ff0 100644 --- a/tests/playwright/shiny/components/data_frame/data_type/app.py +++ b/tests/playwright/shiny/components/data_frame/data_type/app.py @@ -1,6 +1,5 @@ from __future__ import annotations -import modin.pandas as mpd # pyright: ignore[reportMissingTypeStubs] import narwhals.stable.v1 as nw import palmerpenguins # pyright: ignore[reportMissingTypeStubs] import polars as pl @@ -12,7 +11,6 @@ nw_df = nw.from_native(pd_df, eager_only=True) pa_df = pa.table(pd_df) # pyright: ignore[reportUnknownMemberType] -mpd_df = mpd.DataFrame(pd_df) pl_df = pl.DataFrame(pd_df) @@ -138,46 +136,6 @@ def pa_data_view(): def pa_data_view_selected(): return str(type(pa_df_original.data_view(selected=True))) - with ui.card(): - ui.h2("Modin Data") - - @render.data_frame - def mpd_df_original(): - return render.DataGrid( - data=mpd_df, - selection_mode="row", - ) - - "Selected row:" - - @render.data_frame - def selected_mpd_row(): - return mpd_df_original.data_view(selected=True) - - "Data type:" - - @render.code - def mpd_type(): - return str(type(mpd_df)) - - ui.markdown("`.data()` type:") - - @render.code - def mpd_data(): - return str(type(mpd_df_original.data())) - - ui.markdown("`.data_view()` type:") - - @render.code - def mpd_data_view(): - return str(type(mpd_df_original.data_view())) - - ui.markdown("`.data_view(selected=True)` type:") - - @render.code - def mpd_data_view_selected(): - return str(type(mpd_df_original.data_view(selected=True))) - with ui.card(): ui.h2("Polars Data") diff --git a/tests/playwright/shiny/components/data_frame/data_type/test_df_data_type.py b/tests/playwright/shiny/components/data_frame/data_type/test_df_data_type.py index d3c24e130..c2dc8a1fe 100644 --- a/tests/playwright/shiny/components/data_frame/data_type/test_df_data_type.py +++ b/tests/playwright/shiny/components/data_frame/data_type/test_df_data_type.py @@ -30,12 +30,6 @@ "df_original": "pl_df_original", "selected_row": "selected_pl_row", }, - { - "name": "modin", - "prefix": "mpd", - "df_original": "mpd_df_original", - "selected_row": "selected_mpd_row", - }, ] diff --git a/tests/playwright/shiny/components/table/app.py b/tests/playwright/shiny/components/table/app.py index 1a2a2a4e9..d2a5ee0e4 100644 --- a/tests/playwright/shiny/components/table/app.py +++ b/tests/playwright/shiny/components/table/app.py @@ -1,6 +1,5 @@ from __future__ import annotations -import modin.pandas as md # pyright: ignore[reportMissingTypeStubs] import narwhals.stable.v1 as nw import palmerpenguins # pyright: ignore[reportMissingTypeStubs] @@ -10,8 +9,6 @@ nw_df = nw.from_native(pd_df, eager_only=True) -md_df = md.DataFrame(pd_df) - with ui.card(): ui.h2("Polars Pandas Data") @@ -29,14 +26,14 @@ def nw_df_type(): with ui.card(): - ui.h2("Modin dataframe Data") + ui.h2("Pandas dataframe Data") @render.table - def md_table(): - return md_df + def pd_table(): + return pd_df "Data type:" @render.code - def md_df_type(): - return str(type(md_df)) + def pd_df_type(): + return str(type(pd_df)) diff --git a/tests/playwright/shiny/components/table/test_table.py b/tests/playwright/shiny/components/table/test_table.py index d04bcd39d..f86d56e18 100644 --- a/tests/playwright/shiny/components/table/test_table.py +++ b/tests/playwright/shiny/components/table/test_table.py @@ -12,5 +12,5 @@ def test_table_data_support(page: Page, local_app: ShinyAppProc) -> None: controller.OutputTable(page, "nw_table").expect_nrow(2) controller.OutputCode(page, "nw_df_type").expect_value(re.compile("narwhals")) - controller.OutputTable(page, "md_table").expect_nrow(2) - controller.OutputCode(page, "md_df_type").expect_value(re.compile("modin")) + controller.OutputTable(page, "pd_table").expect_nrow(2) + controller.OutputCode(page, "pd_df_type").expect_value(re.compile("pandas"))