diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 6c8165357f9..fad00ba748b 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -50,9 +50,8 @@ body: attributes: label: Python version options: - - "3.9" - - "3.10" - "3.11" + - "3.12" - Not applicable - I don't know validations: diff --git a/.github/workflows/bump-python-package.yml b/.github/workflows/bump-python-package.yml index 305e38d99a4..59fc4bbb787 100644 --- a/.github/workflows/bump-python-package.yml +++ b/.github/workflows/bump-python-package.yml @@ -42,7 +42,7 @@ jobs: - name: Set up Python ${{ inputs.python-version }} uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: - python-version: "3.10" + python-version: "3.11" - name: Install uv run: pip install uv diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3d7892151fc..aaa48afaf2a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,7 +47,7 @@ jobs: steps: - id: set_matrix run: | - MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]'; fi) + MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "websocket", "dockerize", "py311", "py312"]'; fi) echo "matrix_config=${MATRIX_CONFIG}" >> $GITHUB_OUTPUT echo $GITHUB_OUTPUT @@ -123,13 +123,20 @@ jobs: # pull timeouts, 504/401 on push, ECONNRESET) that otherwise fail # the whole job. buildx reuses the buildkit layer cache from the # failed attempt, so a retry mostly re-does just the failed push. + # + # supersetbot's "dev"/"lean" presets pin their own --build-arg + # PY_VER, which lands ahead of --extra-flags on the assembled + # buildx command line; docker/buildx keeps the last value for a + # repeated --build-arg key, so appending PY_VER here overrides + # supersetbot's pin and keeps the build on the Dockerfile's own + # supported Python version. for attempt in 1 2 3; do if supersetbot docker \ $PUSH_OR_LOAD \ --preset "$BUILD_PRESET" \ --context "$EVENT" \ --context-ref "$RELEASE" $FORCE_LATEST \ - --extra-flags "--build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \ + --extra-flags "--build-arg PY_VER=3.11.14-slim-trixie --build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \ $PLATFORM_ARG; then break fi diff --git a/.github/workflows/scheduled-docker-image-refresh.yml b/.github/workflows/scheduled-docker-image-refresh.yml index 8b217d72134..126818a6bd0 100644 --- a/.github/workflows/scheduled-docker-image-refresh.yml +++ b/.github/workflows/scheduled-docker-image-refresh.yml @@ -98,7 +98,7 @@ jobs: # Mirror the same matrix the release publisher uses so every variant # operators consume from Docker Hub gets the refreshed base. matrix: - build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"] + build_preset: ["dev", "lean", "websocket", "dockerize", "py311", "py312"] fail-fast: false steps: - name: "Checkout release tag: ${{ needs.config.outputs.latest-release }}" diff --git a/.github/workflows/superset-frontend.yml b/.github/workflows/superset-frontend.yml index 7f411e3a857..8ba4cec3269 100644 --- a/.github/workflows/superset-frontend.yml +++ b/.github/workflows/superset-frontend.yml @@ -51,7 +51,7 @@ jobs: git show -s --format=raw HEAD docker buildx build \ -t $TAG \ - --cache-from=type=registry,ref=apache/superset-cache:3.10-slim-trixie \ + --cache-from=type=registry,ref=apache/superset-cache:3.11-slim-trixie \ --target superset-node-ci \ . diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml index f0782198edc..733a94223e4 100644 --- a/.github/workflows/tag-release.yml +++ b/.github/workflows/tag-release.yml @@ -56,7 +56,7 @@ jobs: strategy: matrix: build_preset: - ["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"] + ["dev", "lean", "websocket", "dockerize", "py311", "py312"] fail-fast: false steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" diff --git a/Makefile b/Makefile index b1db1d6bf9c..c6503b24762 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,8 @@ # limitations under the License. # -# Python version installed; we need 3.10-3.11 -PYTHON=`command -v python3.11 || command -v python3.10` +# Python version installed; we need 3.11-3.12 +PYTHON=`command -v python3.11 || command -v python3.12` .PHONY: install superset venv pre-commit up down logs ps nuke ports open @@ -76,7 +76,7 @@ update-js: venv: # Create a virtual environment and activate it (recommended) - if ! [ -x "${PYTHON}" ]; then echo "You need Python 3.10 or 3.11 installed"; exit 1; fi + if ! [ -x "${PYTHON}" ]; then echo "You need Python 3.11 or 3.12 installed"; exit 1; fi test -d venv || ${PYTHON} -m venv venv # setup a python3 virtualenv . venv/bin/activate diff --git a/RELEASING/Dockerfile.from_local_tarball b/RELEASING/Dockerfile.from_local_tarball index c56d75e87dc..e7ee676e12c 100644 --- a/RELEASING/Dockerfile.from_local_tarball +++ b/RELEASING/Dockerfile.from_local_tarball @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM python:3.10-slim-trixie +FROM python:3.11-slim-trixie RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset diff --git a/RELEASING/Dockerfile.from_svn_tarball b/RELEASING/Dockerfile.from_svn_tarball index 889724863a5..e858c7adacd 100644 --- a/RELEASING/Dockerfile.from_svn_tarball +++ b/RELEASING/Dockerfile.from_svn_tarball @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM python:3.10-slim-trixie +FROM python:3.11-slim-trixie RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset diff --git a/RELEASING/Dockerfile.make_docs b/RELEASING/Dockerfile.make_docs index e62faa89f8b..08817a462a6 100644 --- a/RELEASING/Dockerfile.make_docs +++ b/RELEASING/Dockerfile.make_docs @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM python:3.10-slim-trixie +FROM python:3.11-slim-trixie ARG VERSION RUN git clone --depth 1 --branch ${VERSION} https://github.com/apache/superset.git /superset diff --git a/RELEASING/Dockerfile.make_tarball b/RELEASING/Dockerfile.make_tarball index e3163273a5e..344bb064df0 100644 --- a/RELEASING/Dockerfile.make_tarball +++ b/RELEASING/Dockerfile.make_tarball @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM python:3.10-slim-trixie +FROM python:3.11-slim-trixie RUN apt-get update -y RUN apt-get install -y \ diff --git a/UPDATING.md b/UPDATING.md index a7662dc5728..a9cf040c603 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -24,6 +24,13 @@ assists people when migrating to a new version. ## Next +### Python 3.10 support removed + +Python 3.10 is no longer supported. Superset now requires **Python 3.11 or higher**. +Update your environment (virtualenv, Docker base image, CI configuration, etc.) to +Python 3.11+ before upgrading. The `apache/superset-cache:3.10-slim-trixie` and +`py310` Docker image variants are no longer published. + ### Owners, dashboard roles, and RLS roles replaced by Subjects Superset now uses subject-based access assignments for dashboards, charts, datasets, diff --git a/docker-compose-light.yml b/docker-compose-light.yml index 458708bd26a..3be24237eb9 100644 --- a/docker-compose-light.yml +++ b/docker-compose-light.yml @@ -71,7 +71,7 @@ x-common-build: &common-build context: . target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean` cache_from: - - apache/superset-cache:3.10-slim-trixie + - apache/superset-cache:3.11-slim-trixie args: DEV_MODE: "true" INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false} diff --git a/docker-compose-non-dev.yml b/docker-compose-non-dev.yml index cc80aea9d19..a939d4971e7 100644 --- a/docker-compose-non-dev.yml +++ b/docker-compose-non-dev.yml @@ -33,7 +33,7 @@ x-common-build: &common-build context: . target: dev cache_from: - - apache/superset-cache:3.10-slim-trixie + - apache/superset-cache:3.11-slim-trixie services: redis: diff --git a/docker-compose.yml b/docker-compose.yml index 1c0d1592d17..d522b66a664 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,7 @@ x-common-build: &common-build context: . target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean` cache_from: - - apache/superset-cache:3.10-slim-trixie + - apache/superset-cache:3.11-slim-trixie args: DEV_MODE: "true" INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false} diff --git a/docs/admin_docs/configuration/mcp-server.mdx b/docs/admin_docs/configuration/mcp-server.mdx index d14b323e760..f0f33c8e785 100644 --- a/docs/admin_docs/configuration/mcp-server.mdx +++ b/docs/admin_docs/configuration/mcp-server.mdx @@ -99,7 +99,7 @@ See [Connecting AI Clients](#connecting-ai-clients) for Claude Code, Claude Web, ## Prerequisites - Apache Superset 5.0+ running and accessible -- Python 3.10+ +- Python 3.11+ - The `fastmcp` package (`pip install fastmcp`) --- diff --git a/docs/developer_docs/contributing/development-setup.md b/docs/developer_docs/contributing/development-setup.md index c0ac0d165bb..1b6227b2597 100644 --- a/docs/developer_docs/contributing/development-setup.md +++ b/docs/developer_docs/contributing/development-setup.md @@ -379,7 +379,7 @@ functioning across environments. Make sure your machine meets the [OS dependencies](https://superset.apache.org/docs/installation/pypi#os-dependencies) before following these steps. You also need to install MySQL. -Ensure that you are using Python version 3.9, 3.10 or 3.11, then proceed with: +Ensure that you are using Python version 3.11 or 3.12, then proceed with: ```bash # Create a virtual environment and activate it (recommended) diff --git a/docs/developer_docs/contributing/issue-reporting.md b/docs/developer_docs/contributing/issue-reporting.md index 3bf1de8dc90..969a1b14757 100644 --- a/docs/developer_docs/contributing/issue-reporting.md +++ b/docs/developer_docs/contributing/issue-reporting.md @@ -82,7 +82,7 @@ If applicable, add screenshots or recordings. ### Environment - Superset version: [e.g., 3.0.0] -- Python version: [e.g., 3.9.7] +- Python version: [e.g., 3.11.7] - Node version: [e.g., 18.17.0] - Database: [e.g., PostgreSQL 14] - Browser: [e.g., Chrome 120] @@ -125,7 +125,7 @@ No error messages in browser console or server logs. ### Environment - Superset version: 3.0.0 -- Python version: 3.9.16 +- Python version: 3.11.16 - Database: PostgreSQL 14.9 - Browser: Chrome 120.0.6099.71 - OS: macOS 14.2 diff --git a/docs/developer_docs/index.md b/docs/developer_docs/index.md index 2bfc2bba9ca..de1a5f39f9d 100644 --- a/docs/developer_docs/index.md +++ b/docs/developer_docs/index.md @@ -52,7 +52,7 @@ Everything you need to contribute to the Apache Superset project. This section i ## Development Resources ### Prerequisites -- **Python**: 3.9, 3.10, or 3.11 +- **Python**: 3.11 or 3.12 - **Node.js**: 18.x or 20.x - **npm**: 9.x or 10.x - **Git**: Basic understanding diff --git a/pyproject.toml b/pyproject.toml index 1ebde2cf4e9..976b8d82ee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,13 +24,12 @@ name = "apache_superset" description = "A modern, enterprise-ready business intelligence web application" readme = "README.md" dynamic = ["version", "scripts", "entry-points"] -requires-python = ">=3.10" +requires-python = ">=3.11" license = { file="LICENSE.txt" } authors = [ { name = "Apache Software Foundation", email = "dev@superset.apache.org" }, ] classifiers = [ - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] @@ -167,7 +166,6 @@ gevent = ["gevent>=26.4.0"] gsheets = ["shillelagh[gsheetsapi]>=1.4.4, <2"] hana = ["hdbcli==2.29.25", "sqlalchemy_hana==3.0.3"] hive = [ - "pyhive[hive]>=0.6.5;python_version<'3.11'", "pyhive[hive_pure_sasl]>=0.7.0", "tableschema", "thrift>=0.23.0, <1.0.0", @@ -201,7 +199,6 @@ singlestore = ["sqlalchemy-singlestoredb>=1.2.1, <2"] snowflake = ["snowflake-sqlalchemy>=1.10.2, <2"] sqlite = ["syntaqlite>=0.7.0,<0.8.0"] spark = [ - "pyhive[hive]>=0.6.5;python_version<'3.11'", "pyhive[hive_pure_sasl]>=0.7", "tableschema", "thrift>=0.23.0, <1", @@ -344,8 +341,8 @@ exclude = [ line-length = 88 indent-width = 4 -# Assume Python 3.10 -target-version = "py310" +# Assume Python 3.11 +target-version = "py311" [tool.ruff.lint] # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. diff --git a/scripts/check-env.py b/scripts/check-env.py index e7816fb585d..830d7a3cc29 100755 --- a/scripts/check-env.py +++ b/scripts/check-env.py @@ -133,8 +133,8 @@ def main(docker: bool, frontend: bool, backend: bool) -> None: # noqa: C901 requirements = [ Requirement( "python", - (Version("3.10.0"), Version("3.10.999")), - (Version("3.9.0"), Version("3.11.999")), + (Version("3.11.0"), Version("3.11.999")), + (Version("3.11.0"), Version("3.12.999")), "backend", "python --version", ), diff --git a/superset-core/README.md b/superset-core/README.md index 61fefbac142..22961497fa5 100644 --- a/superset-core/README.md +++ b/superset-core/README.md @@ -21,7 +21,7 @@ under the License. [![PyPI version](https://badge.fury.io/py/apache-superset-core.svg)](https://badge.fury.io/py/apache-superset-core) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) +[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) The official core package for building Apache Superset backend extensions and integrations. This package provides essential building blocks including base classes, API utilities, type definitions, and decorators for both the host application and extensions. diff --git a/superset-core/pyproject.toml b/superset-core/pyproject.toml index 22b684f1947..74d178fc951 100644 --- a/superset-core/pyproject.toml +++ b/superset-core/pyproject.toml @@ -26,7 +26,7 @@ authors = [ ] license = "Apache-2.0" license-files = ["LICENSE.txt"] -requires-python = ">=3.10" +requires-python = ">=3.11" keywords = ["superset", "apache", "analytics", "business-intelligence", "extensions", "visualization"] classifiers = [ "Development Status :: 3 - Alpha", @@ -34,7 +34,6 @@ classifiers = [ "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Database", diff --git a/superset-extensions-cli/README.md b/superset-extensions-cli/README.md index a5143a80ba3..4750ece4db6 100644 --- a/superset-extensions-cli/README.md +++ b/superset-extensions-cli/README.md @@ -21,7 +21,7 @@ under the License. [![PyPI version](https://badge.fury.io/py/apache-superset-extensions-cli.svg)](https://badge.fury.io/py/apache-superset-extensions-cli) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) +[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) Official command-line interface for building, bundling, and managing Apache Superset extensions. This CLI tool provides developers with everything needed to create, develop, and package extensions for the Superset ecosystem. diff --git a/superset-extensions-cli/pyproject.toml b/superset-extensions-cli/pyproject.toml index 99f4ca0fd52..a7865556b70 100644 --- a/superset-extensions-cli/pyproject.toml +++ b/superset-extensions-cli/pyproject.toml @@ -25,7 +25,7 @@ authors = [ ] license = "Apache-2.0" license-files = ["LICENSE.txt"] -requires-python = ">=3.10" +requires-python = ">=3.11" keywords = ["superset", "apache", "cli", "extensions", "analytics", "business-intelligence", "development-tools"] classifiers = [ "Development Status :: 3 - Alpha", @@ -33,7 +33,6 @@ classifiers = [ "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Database", diff --git a/superset/app.py b/superset/app.py index 3b90d74b3d7..80bce030362 100644 --- a/superset/app.py +++ b/superset/app.py @@ -18,21 +18,12 @@ from __future__ import annotations import logging import os -import sys from typing import cast, Iterable, Optional +from wsgiref.types import StartResponse, WSGIApplication, WSGIEnvironment from alembic.config import Config from alembic.runtime.migration import MigrationContext from alembic.script import ScriptDirectory - -if sys.version_info >= (3, 11): - from wsgiref.types import StartResponse, WSGIApplication, WSGIEnvironment -else: - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment - from flask import Flask, Response from werkzeug.exceptions import NotFound diff --git a/superset/mcp_service/README.md b/superset/mcp_service/README.md index d1b4eed9e7b..b9599632fda 100644 --- a/superset/mcp_service/README.md +++ b/superset/mcp_service/README.md @@ -84,7 +84,7 @@ If Docker is not available, you can set up manually: git clone https://github.com/apache/superset.git cd superset -# 2. Set up Python environment (Python 3.10 or 3.11 required) +# 2. Set up Python environment (Python 3.11 or 3.12 required) python3 -m venv venv source venv/bin/activate diff --git a/superset/middleware/legacy_prefix_redirect.py b/superset/middleware/legacy_prefix_redirect.py index 523e8a193e6..0bd83bd798b 100644 --- a/superset/middleware/legacy_prefix_redirect.py +++ b/superset/middleware/legacy_prefix_redirect.py @@ -60,20 +60,12 @@ closed-set discipline. from __future__ import annotations import re -import sys from typing import Iterable, Optional from urllib.parse import quote +from wsgiref.types import StartResponse, WSGIApplication, WSGIEnvironment from werkzeug.wrappers import Response -if sys.version_info >= (3, 11): - from wsgiref.types import StartResponse, WSGIApplication, WSGIEnvironment -else: - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment - #: The legacy URL token the shim recognises. Hard-coded — not configurable. _LEGACY_PREFIX: str = "/superset" diff --git a/superset/utils/backports.py b/superset/utils/backports.py index b48f76d2353..14c705a235c 100644 --- a/superset/utils/backports.py +++ b/superset/utils/backports.py @@ -14,13 +14,4 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import sys -from enum import Enum - -if sys.version_info >= (3, 11): - # pylint: disable=unused-import - from enum import StrEnum # nopycln: import -else: - - class StrEnum(str, Enum): - pass +from enum import StrEnum # noqa: F401