From 5ff7386356fc40875bd0de5ca64ad81712ab3328 Mon Sep 17 00:00:00 2001 From: Brandon Schabell Date: Fri, 2 Oct 2026 19:29:31 -0500 Subject: [PATCH] Remove unnecessary python version checks. --- CHANGELOG.md | 1 + .../tests/integration/store/test_store_data.py | 5 ----- dash/_hooks.py | 8 +++----- dash/_jupyter.py | 3 +-- dash/development/component_generator.py | 18 +----------------- .../tools/tool_get_dash_component.py | 4 ++-- dash/resources.py | 3 +-- dash/types.py | 4 ++-- requirements/ci.txt | 2 +- .../test_async_background_callbacks.py | 5 ----- .../test_basic_long_callback001.py | 5 ----- .../test_basic_long_callback002.py | 6 ------ .../test_basic_long_callback003.py | 5 ----- .../test_basic_long_callback004.py | 6 ------ .../test_basic_long_callback005.py | 4 ---- .../test_basic_long_callback006.py | 5 ----- .../test_basic_long_callback007.py | 6 ------ .../test_basic_long_callback008.py | 7 ------- .../test_basic_long_callback009.py | 5 ----- .../test_basic_long_callback010.py | 7 ------- .../test_basic_long_callback011.py | 7 ------- .../test_basic_long_callback012.py | 5 ----- .../test_basic_long_callback013.py | 7 ------- .../test_basic_long_callback014.py | 7 ------- .../test_basic_long_callback015.py | 7 ------- .../test_basic_long_callback016.py | 6 ------ tests/unit/test_app_runners.py | 4 ---- 27 files changed, 12 insertions(+), 140 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fb24b979c..4f523a7126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Removed - [#3646](https://github.com/plotly/dash/pull/3646) Remove React 16 support (`16.14.0` is no longer an accepted value for `REACT_VERSION` / `_set_react_version`). +- [#4039](https://github.com/plotly/dash/pull/4039) Remove unnecessary Python version checks (pre 3.9). ### Changed - [#3987](https://github.com/plotly/dash/pull/3987) Forward FastAPI reload scope options (`reload_dirs`, `reload_excludes`, and `reload_includes`) to Uvicorn when reloading. diff --git a/components/dash-core-components/tests/integration/store/test_store_data.py b/components/dash-core-components/tests/integration/store/test_store_data.py index 7b5465463f..41689cb072 100644 --- a/components/dash-core-components/tests/integration/store/test_store_data.py +++ b/components/dash-core-components/tests/integration/store/test_store_data.py @@ -1,4 +1,3 @@ -import sys import json import hashlib import itertools @@ -120,10 +119,6 @@ def on_ts(ts, data): assert dash_dcc.get_logs() == [] -@pytest.mark.skipif( - sys.version_info < (3, 6), - reason="tests requires dependency only available in 3.6+", -) @pytest.mark.parametrize("storage_type", ("memory", "local", "session")) def test_stda003_large_data_size(storage_type, csv_5mb, dash_dcc): def fingerprint(data): diff --git a/dash/_hooks.py b/dash/_hooks.py index f260b1fcb0..c70e8210cd 100644 --- a/dash/_hooks.py +++ b/dash/_hooks.py @@ -2,8 +2,6 @@ from importlib import metadata as _importlib_metadata -import typing_extensions as _tx - from .exceptions import HookError from .resources import ResourceType from ._callback import ClientsideFuncType @@ -20,12 +18,12 @@ Dash = None -HookDataType = _tx.TypeVar("HookDataType") -DevtoolPosition = _tx.Literal["right", "left"] +HookDataType = _t.TypeVar("HookDataType") +DevtoolPosition = _t.Literal["right", "left"] # pylint: disable=too-few-public-methods -class _Hook(_tx.Generic[HookDataType]): +class _Hook(_t.Generic[HookDataType]): def __init__( self, func, priority=0, final=False, data: _t.Optional[HookDataType] = None ): diff --git a/dash/_jupyter.py b/dash/_jupyter.py index 85668127df..9ae361a0d2 100644 --- a/dash/_jupyter.py +++ b/dash/_jupyter.py @@ -9,8 +9,7 @@ import threading import time -from typing import Optional, Any -from typing_extensions import Literal +from typing import Optional, Any, Literal from werkzeug.serving import make_server diff --git a/dash/development/component_generator.py b/dash/development/component_generator.py index 660d9986ab..a9e9a70bbc 100644 --- a/dash/development/component_generator.py +++ b/dash/development/component_generator.py @@ -173,10 +173,7 @@ def generate_components( def safe_json_loads(s): - jsondata_unicode = json.loads(s, object_pairs_hook=OrderedDict) - if sys.version_info[0] >= 3: - return jsondata_unicode - return byteify(jsondata_unicode) + return json.loads(s, object_pairs_hook=OrderedDict) def component_build_arg_parser(): @@ -282,18 +279,5 @@ def cli(): ) -# pylint: disable=undefined-variable -def byteify(input_object): - if isinstance(input_object, dict): - return OrderedDict( - [(byteify(key), byteify(value)) for key, value in input_object.items()] - ) - if isinstance(input_object, list): - return [byteify(element) for element in input_object] - if isinstance(input_object, str): # noqa:F821 - return input_object.encode(encoding="utf-8") - return input_object - - if __name__ == "__main__": cli() diff --git a/dash/mcp/primitives/tools/tool_get_dash_component.py b/dash/mcp/primitives/tools/tool_get_dash_component.py index b3f43bd063..caaa0ab206 100644 --- a/dash/mcp/primitives/tools/tool_get_dash_component.py +++ b/dash/mcp/primitives/tools/tool_get_dash_component.py @@ -3,10 +3,10 @@ from __future__ import annotations import json -from typing import Any +from typing import Annotated, Any from pydantic import Field, TypeAdapter -from typing_extensions import Annotated, NotRequired, TypedDict +from typing_extensions import NotRequired, TypedDict from dash import get_app from dash._layout_utils import find_component diff --git a/dash/resources.py b/dash/resources.py index bb55328b3b..337cb55887 100644 --- a/dash/resources.py +++ b/dash/resources.py @@ -3,14 +3,13 @@ import os import typing as _t -import typing_extensions as _tx from .development.base_component import ComponentRegistry from . import exceptions # ResourceType has `async` key, use the init form to be able to provide it. -ResourceType = _tx.TypedDict( +ResourceType = _t.TypedDict( "ResourceType", { "namespace": str, diff --git a/dash/types.py b/dash/types.py index 175a1f61ca..c3297a5147 100644 --- a/dash/types.py +++ b/dash/types.py @@ -1,9 +1,9 @@ import typing -from typing import Any, Dict, List, Union +from typing import Annotated, Any, Dict, List, Union from pydantic import Field, GetCoreSchemaHandler, GetJsonSchemaHandler from pydantic_core import core_schema -from typing_extensions import Annotated, TypedDict, NotRequired +from typing_extensions import TypedDict, NotRequired class _NumberSchema: # pylint: disable=too-few-public-methods diff --git a/requirements/ci.txt b/requirements/ci.txt index db3c682712..0d1067d6be 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -22,5 +22,5 @@ xlrd>=2.0.1 pytest-rerunfailures pytest-timeout jupyterlab<4.0.0 -pyright==1.1.411;python_version>="3.7" +pyright==1.1.411 mypy==1.15.0;python_version>="3.12" diff --git a/tests/async_tests/test_async_background_callbacks.py b/tests/async_tests/test_async_background_callbacks.py index 2efcf0b030..7db69d7c1a 100644 --- a/tests/async_tests/test_async_background_callbacks.py +++ b/tests/async_tests/test_async_background_callbacks.py @@ -1,8 +1,6 @@ -import sys import time from multiprocessing import Lock -import pytest from flaky import flaky from tests.utils import is_dash_async @@ -34,9 +32,6 @@ def test_001ab_arbitrary(dash_duo, manager): dash_duo.wait_for_text_to_equal("#no-output", "completed") -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_002ab_basic(dash_duo, manager): """ diff --git a/tests/background_callback/test_basic_long_callback001.py b/tests/background_callback/test_basic_long_callback001.py index af8c80d3ee..49d5def35b 100644 --- a/tests/background_callback/test_basic_long_callback001.py +++ b/tests/background_callback/test_basic_long_callback001.py @@ -1,15 +1,10 @@ -import sys from multiprocessing import Lock -import pytest from flaky import flaky from .utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc001_fast_input(dash_duo, manager): """ diff --git a/tests/background_callback/test_basic_long_callback002.py b/tests/background_callback/test_basic_long_callback002.py index 0a3c1dd315..1430fb4d70 100644 --- a/tests/background_callback/test_basic_long_callback002.py +++ b/tests/background_callback/test_basic_long_callback002.py @@ -1,14 +1,8 @@ -import sys - -import pytest from flaky import flaky from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc002_long_callback_running(dash_duo, manager): with setup_background_callback_app(manager, "app2") as app: diff --git a/tests/background_callback/test_basic_long_callback003.py b/tests/background_callback/test_basic_long_callback003.py index f6194a139e..6eee46d50f 100644 --- a/tests/background_callback/test_basic_long_callback003.py +++ b/tests/background_callback/test_basic_long_callback003.py @@ -1,15 +1,10 @@ -import sys from multiprocessing import Lock -import pytest from flaky import flaky from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc003_long_callback_running_cancel(dash_duo, manager): lock = Lock() diff --git a/tests/background_callback/test_basic_long_callback004.py b/tests/background_callback/test_basic_long_callback004.py index 8b3d646225..24cfe3a557 100644 --- a/tests/background_callback/test_basic_long_callback004.py +++ b/tests/background_callback/test_basic_long_callback004.py @@ -1,14 +1,8 @@ -import sys - -import pytest from flaky import flaky from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc004_long_callback_progress(dash_duo, manager): with setup_background_callback_app(manager, "app4") as app: diff --git a/tests/background_callback/test_basic_long_callback005.py b/tests/background_callback/test_basic_long_callback005.py index 5dabf2c14a..7b3dbd7630 100644 --- a/tests/background_callback/test_basic_long_callback005.py +++ b/tests/background_callback/test_basic_long_callback005.py @@ -1,4 +1,3 @@ -import sys from multiprocessing import Lock import pytest @@ -6,9 +5,6 @@ from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @pytest.mark.skip(reason="Timeout often") def test_lcbc005_long_callback_caching(dash_duo, manager): lock = Lock() diff --git a/tests/background_callback/test_basic_long_callback006.py b/tests/background_callback/test_basic_long_callback006.py index 24121d4e3e..e500af1111 100644 --- a/tests/background_callback/test_basic_long_callback006.py +++ b/tests/background_callback/test_basic_long_callback006.py @@ -1,15 +1,10 @@ -import sys from multiprocessing import Lock -import pytest from flaky import flaky from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc006_long_callback_caching_multi(dash_duo, manager): lock = Lock() diff --git a/tests/background_callback/test_basic_long_callback007.py b/tests/background_callback/test_basic_long_callback007.py index 93bbaa2eec..ace823366e 100644 --- a/tests/background_callback/test_basic_long_callback007.py +++ b/tests/background_callback/test_basic_long_callback007.py @@ -1,14 +1,8 @@ -import sys - -import pytest from flaky import flaky from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc007_validation_layout(dash_duo, manager): with setup_background_callback_app(manager, "app7") as app: diff --git a/tests/background_callback/test_basic_long_callback008.py b/tests/background_callback/test_basic_long_callback008.py index dcd70420f8..ad22833830 100644 --- a/tests/background_callback/test_basic_long_callback008.py +++ b/tests/background_callback/test_basic_long_callback008.py @@ -1,13 +1,6 @@ -import sys - -import pytest - from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc008_long_callbacks_error(dash_duo, manager): with setup_background_callback_app(manager, "app_error") as app: dash_duo.start_server( diff --git a/tests/background_callback/test_basic_long_callback009.py b/tests/background_callback/test_basic_long_callback009.py index a78e82a203..7fdef57468 100644 --- a/tests/background_callback/test_basic_long_callback009.py +++ b/tests/background_callback/test_basic_long_callback009.py @@ -1,14 +1,9 @@ -import sys import time -import pytest from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc009_short_interval(dash_duo, manager): with setup_background_callback_app(manager, "app_short_interval") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback010.py b/tests/background_callback/test_basic_long_callback010.py index ff51221a8b..80e94137f2 100644 --- a/tests/background_callback/test_basic_long_callback010.py +++ b/tests/background_callback/test_basic_long_callback010.py @@ -1,13 +1,6 @@ -import sys - -import pytest - from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc010_side_updates(dash_duo, manager): with setup_background_callback_app(manager, "app_side_update") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback011.py b/tests/background_callback/test_basic_long_callback011.py index 54b7a3a1f8..29975e4e07 100644 --- a/tests/background_callback/test_basic_long_callback011.py +++ b/tests/background_callback/test_basic_long_callback011.py @@ -1,13 +1,6 @@ -import sys - -import pytest - from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc011_long_pattern_matching(dash_duo, manager): with setup_background_callback_app(manager, "app_pattern_matching") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback012.py b/tests/background_callback/test_basic_long_callback012.py index acde983d5f..5e15302df7 100644 --- a/tests/background_callback/test_basic_long_callback012.py +++ b/tests/background_callback/test_basic_long_callback012.py @@ -1,14 +1,9 @@ import json -import sys -import pytest from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc012_long_callback_ctx(dash_duo, manager): with setup_background_callback_app(manager, "app_callback_ctx") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback013.py b/tests/background_callback/test_basic_long_callback013.py index e3f2715286..2fc36b8971 100644 --- a/tests/background_callback/test_basic_long_callback013.py +++ b/tests/background_callback/test_basic_long_callback013.py @@ -1,13 +1,6 @@ -import sys - -import pytest - from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc013_unordered_state_input(dash_duo, manager): with setup_background_callback_app(manager, "app_unordered") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback014.py b/tests/background_callback/test_basic_long_callback014.py index 927cbe4373..52e602854b 100644 --- a/tests/background_callback/test_basic_long_callback014.py +++ b/tests/background_callback/test_basic_long_callback014.py @@ -1,13 +1,6 @@ -import sys - -import pytest - from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc014_progress_delete(dash_duo, manager): with setup_background_callback_app(manager, "app_progress_delete") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback015.py b/tests/background_callback/test_basic_long_callback015.py index a4e3cae426..cd0c57531e 100644 --- a/tests/background_callback/test_basic_long_callback015.py +++ b/tests/background_callback/test_basic_long_callback015.py @@ -1,13 +1,6 @@ -import sys - -import pytest - from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="Python 3.6 long callbacks tests hangs up" -) def test_lcbc015_diff_outputs_same_func(dash_duo, manager): with setup_background_callback_app(manager, "app_diff_outputs") as app: dash_duo.start_server(app) diff --git a/tests/background_callback/test_basic_long_callback016.py b/tests/background_callback/test_basic_long_callback016.py index 952a74dae3..be4ab6309f 100644 --- a/tests/background_callback/test_basic_long_callback016.py +++ b/tests/background_callback/test_basic_long_callback016.py @@ -1,14 +1,8 @@ -import sys - -import pytest from flaky import flaky from tests.background_callback.utils import setup_background_callback_app -@pytest.mark.skipif( - sys.version_info < (3, 9), reason="Python 3.8 long callbacks tests hangs up" -) @flaky(max_runs=3) def test_lcbc016_multi_page_cancel(dash_duo, manager): with setup_background_callback_app(manager, "app_page_cancel") as app: diff --git a/tests/unit/test_app_runners.py b/tests/unit/test_app_runners.py index 76cf4e0ac2..841603f505 100644 --- a/tests/unit/test_app_runners.py +++ b/tests/unit/test_app_runners.py @@ -1,5 +1,4 @@ import os -import sys import time from types import SimpleNamespace from unittest.mock import Mock @@ -58,9 +57,6 @@ def run(**options): runner.stop() -@pytest.mark.skipif( - sys.version_info < (3,), reason="requires python3 for process testing" -) def test_process_server_smoke(dash_process_server): cwd = os.getcwd() this_dir = os.path.dirname(__file__)