Przeglądaj źródła

feat: stop supporting python 3.8

trgiangdo 8 miesięcy temu
rodzic
commit
0b53b0c500

+ 1 - 1
.github/workflows/dependencies-management.yml

@@ -22,7 +22,7 @@ jobs:
     timeout-minutes: 20
     timeout-minutes: 20
     strategy:
     strategy:
       matrix:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest]
         os: [ubuntu-latest]
     permissions:
     permissions:
       contents: write
       contents: write

+ 2 - 2
.github/workflows/overall-tests.yml

@@ -52,7 +52,7 @@ jobs:
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest, windows-latest, macos-13]
         os: [ubuntu-latest, windows-latest, macos-13]
         pipfile-version: ['min', 'max']
         pipfile-version: ['min', 'max']
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
@@ -80,7 +80,7 @@ jobs:
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest, windows-latest, macos-13]
         os: [ubuntu-latest, windows-latest, macos-13]
         orchestrator: ['orchestrator_dispatcher', 'standalone']
         orchestrator: ['orchestrator_dispatcher', 'standalone']
         pipfile-version: ['min', 'max']
         pipfile-version: ['min', 'max']

+ 1 - 1
.github/workflows/packaging.yml

@@ -20,7 +20,7 @@ jobs:
     timeout-minutes: 30
     timeout-minutes: 30
     strategy:
     strategy:
       matrix:
       matrix:
-        python-versions: [ '3.8', '3.9', '3.10', '3.11', '3.12']
+        python-versions: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest, macos-13, windows-latest]
         os: [ubuntu-latest, macos-13, windows-latest]
 
 
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}

+ 3 - 3
.github/workflows/partial-tests.yml

@@ -23,7 +23,7 @@ jobs:
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest, windows-latest, macos-13]
         os: [ubuntu-latest, windows-latest, macos-13]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     steps:
     steps:
@@ -143,7 +143,7 @@ jobs:
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest, windows-latest, macos-13]
         os: [ubuntu-latest, windows-latest, macos-13]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     steps:
     steps:
@@ -186,7 +186,7 @@ jobs:
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
         os: [ubuntu-latest, windows-latest, macos-13]
         os: [ubuntu-latest, windows-latest, macos-13]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     steps:
     steps:

+ 2 - 2
.github/workflows/publish.yml

@@ -15,7 +15,7 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
       - uses: actions/setup-python@v5
         with:
         with:
-          python-version: 3.8
+          python-version: 3.9
 
 
       - name: Extract Github Tag Version
       - name: Extract Github Tag Version
         id: vars
         id: vars
@@ -104,7 +104,7 @@ jobs:
     timeout-minutes: 30
     timeout-minutes: 30
     strategy:
     strategy:
       matrix:
       matrix:
-        python-versions: ['3.8','3.9','3.10', '3.11', '3.12']
+        python-versions: ['3.9','3.10', '3.11', '3.12']
         os: [ubuntu-latest,windows-latest,macos-13]
         os: [ubuntu-latest,windows-latest,macos-13]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     steps:
     steps:

+ 1 - 1
INSTALLATION.md

@@ -5,7 +5,7 @@ There are different ways to install Taipy, depending on how you plan to use it.
 If your goal is to look into the code, modify and improve it, go straight
 If your goal is to look into the code, modify and improve it, go straight
 to the [source installation](#installing-for-development) section.
 to the [source installation](#installing-for-development) section.
 
 
-Taipy needs your system to have Python 3.8 or above installed.
+Taipy needs your system to have Python 3.9 or above installed.
 
 
 ## Installing from PyPI
 ## Installing from PyPI
 
 

+ 0 - 1
Pipfile

@@ -6,7 +6,6 @@ name = "pypi"
 [packages]
 [packages]
 apispec = {extras = ["yaml"], version = "==6.3"}
 apispec = {extras = ["yaml"], version = "==6.3"}
 apispec-webframeworks = "==0.5.2"
 apispec-webframeworks = "==0.5.2"
-"backports.zoneinfo" = {version="==0.2.1", markers="python_version < '3.9'", extras=["tzdata"]}
 cookiecutter = "==2.1.1"
 cookiecutter = "==2.1.1"
 deepdiff = "==6.7.1"
 deepdiff = "==6.7.1"
 flask = "==3.0.0"
 flask = "==3.0.0"

+ 1 - 1
doc/gui/extension/README.md

@@ -45,7 +45,7 @@ This section explains how to build the custom extension library.
 
 
 To complete the build of the extension library, we need the following tools:
 To complete the build of the extension library, we need the following tools:
 
 
-- Python 3.8 or higher;
+- Python 3.9 or higher;
 - Taipy GUI 2.2 or higher;
 - Taipy GUI 2.2 or higher;
 - [Node.js](https://nodejs.org/en/) 18.0 or higher: a JavaScript runtime.<br/>
 - [Node.js](https://nodejs.org/en/) 18.0 or higher: a JavaScript runtime.<br/>
   This embeds [npm](https://www.npmjs.com/), the Node Package Manager.
   This embeds [npm](https://www.npmjs.com/), the Node Package Manager.

+ 1 - 2
doc/gui/extension/pyproject.toml

@@ -7,7 +7,7 @@ version = "1.0.0"
 authors = [ { name = "Taipy" } ]
 authors = [ { name = "Taipy" } ]
 description = "A Taipy GUI extension library example."
 description = "A Taipy GUI extension library example."
 readme = { file = "README.md", content-type = "text/markdown" }
 readme = { file = "README.md", content-type = "text/markdown" }
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 keywords = [ "taipy" ]
 keywords = [ "taipy" ]
 license = { text = "Apache License 2.0" }
 license = { text = "Apache License 2.0" }
 classifiers = [
 classifiers = [
@@ -15,7 +15,6 @@ classifiers = [
     # "License :: OSI Approved :: Apache Software License",
     # "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 1 - 2
pyproject.toml

@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
 name = "taipy"
 name = "taipy"
 description = "A 360° open-source platform from Python pilots to production-ready web apps."
 description = "A 360° open-source platform from Python pilots to production-ready web apps."
 readme = "package_desc.md"
 readme = "package_desc.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 license = {text = "Apache License 2.0"}
 license = {text = "Apache License 2.0"}
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 keywords = ["taipy"]
 keywords = ["taipy"]
@@ -15,7 +15,6 @@ classifiers = [
     "License :: OSI Approved :: Apache Software License",
     "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 1 - 2
taipy/config/pyproject.toml

@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
 name = "taipy-config"
 name = "taipy-config"
 description = "A Taipy package dedicated to easily configure a Taipy application."
 description = "A Taipy package dedicated to easily configure a Taipy application."
 readme = "package_desc.md"
 readme = "package_desc.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 license = {text = "Apache License 2.0"}
 license = {text = "Apache License 2.0"}
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 keywords = ["taipy-config"]
 keywords = ["taipy-config"]
@@ -15,7 +15,6 @@ classifiers = [
     "License :: OSI Approved :: Apache Software License",
     "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 2 - 10
taipy/core/_entity/_dag.py

@@ -8,8 +8,8 @@
 # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # specific language governing permissions and limitations under the License.
 # specific language governing permissions and limitations under the License.
+
 import math
 import math
-from functools import reduce
 from typing import Any, Dict, List, Tuple
 from typing import Any, Dict, List, Tuple
 
 
 import networkx as nx
 import networkx as nx
@@ -60,7 +60,7 @@ class _DAG:
         if self._width == 1:
         if self._width == 1:
             grd_wdt = 1
             grd_wdt = 1
         else:
         else:
-            grd_wdt = self.__lcm(*[len(i) + 1 if len(i) != self._width else len(i) - 1 for i in self._sorted_nodes]) + 1
+            grd_wdt = math.lcm(*[len(i) + 1 if len(i) != self._width else len(i) - 1 for i in self._sorted_nodes]) + 1
         return len(self._sorted_nodes), grd_wdt
         return len(self._sorted_nodes), grd_wdt
 
 
     def __compute_nodes(self) -> Dict[str, _Node]:
     def __compute_nodes(self) -> Dict[str, _Node]:
@@ -81,11 +81,3 @@ class _DAG:
 
 
     def __compute_edges(self, dag) -> List[_Edge]:
     def __compute_edges(self, dag) -> List[_Edge]:
         return [_Edge(self.nodes[edge[0].id], self.nodes[edge[1].id]) for edge in dag.edges()]
         return [_Edge(self.nodes[edge[0].id], self.nodes[edge[1].id]) for edge in dag.edges()]
-
-    @staticmethod
-    def __lcm(*integers) -> int:
-        # Function math.lcm is only implemented for Python 3.9+
-        # For compatibility with Python 3.8 it has been re implemented.
-        if 0 in integers:
-            return 0
-        return reduce(lambda x, y: (x * y) // math.gcd(x, y), integers)

+ 1 - 2
taipy/core/pyproject.toml

@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
 name = "taipy-core"
 name = "taipy-core"
 description = "A Python library to build powerful and customized data-driven back-end applications."
 description = "A Python library to build powerful and customized data-driven back-end applications."
 readme = "package_desc.md"
 readme = "package_desc.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 license = {text = "Apache License 2.0"}
 license = {text = "Apache License 2.0"}
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 keywords = ["taipy-core"]
 keywords = ["taipy-core"]
@@ -15,7 +15,6 @@ classifiers = [
     "License :: OSI Approved :: Apache Software License",
     "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 1 - 1
taipy/gui/INSTALLATION.md

@@ -12,7 +12,7 @@ you plan to use it:
 - [Debugging the JavaScript bundle](#debugging-the-javascript-bundle)
 - [Debugging the JavaScript bundle](#debugging-the-javascript-bundle)
 - [Running the tests](#running-the-tests)
 - [Running the tests](#running-the-tests)
 
 
-Taipy GUI needs your system to have **Python 3.8** or above installed.
+Taipy GUI needs your system to have **Python 3.9** or above installed.
 
 
 ## Installing the latest release
 ## Installing the latest release
 
 

+ 1 - 12
taipy/gui/builder/_element.py

@@ -14,9 +14,7 @@ from __future__ import annotations
 import ast
 import ast
 import copy
 import copy
 import inspect
 import inspect
-import io
 import re
 import re
-import sys
 import typing as t
 import typing as t
 import uuid
 import uuid
 from abc import ABC, abstractmethod
 from abc import ABC, abstractmethod
@@ -25,9 +23,6 @@ from types import FrameType, FunctionType
 
 
 from .._warnings import _warn
 from .._warnings import _warn
 from ..utils import _getscopeattr
 from ..utils import _getscopeattr
-
-if sys.version_info < (3, 9):
-    from ..utils.unparse import _Unparser
 from ._context_manager import _BuilderContextManager
 from ._context_manager import _BuilderContextManager
 from ._factory import _BuilderFactory
 from ._factory import _BuilderFactory
 from ._utils import _LambdaByName, _python_builtins, _TransformVarToValue
 from ._utils import _LambdaByName, _python_builtins, _TransformVarToValue
@@ -129,13 +124,7 @@ class _Element(ABC):
             ]
             ]
             tree = _TransformVarToValue(self.__calling_frame, args + targets + _python_builtins).visit(lambda_fn)
             tree = _TransformVarToValue(self.__calling_frame, args + targets + _python_builtins).visit(lambda_fn)
             ast.fix_missing_locations(tree)
             ast.fix_missing_locations(tree)
-            if sys.version_info < (3, 9):  # python 3.8 ast has no unparse
-                string_fd = io.StringIO()
-                _Unparser(tree, string_fd)
-                string_fd.seek(0)
-                lambda_text = string_fd.read()
-            else:
-                lambda_text = ast.unparse(tree)
+            lambda_text = ast.unparse(tree)
             lambda_name = f"__lambda_{uuid.uuid4().hex}"
             lambda_name = f"__lambda_{uuid.uuid4().hex}"
             self._lambdas[lambda_name] = lambda_text
             self._lambdas[lambda_name] = lambda_text
             return f'{{{lambda_name}({", ".join(args)})}}'
             return f'{{{lambda_name}({", ".join(args)})}}'

+ 1 - 1
taipy/gui/package_desc.md

@@ -35,7 +35,7 @@ you plan to use it:
 - [Debugging the JavaScript bundle](#debugging-the-javascript-bundle)
 - [Debugging the JavaScript bundle](#debugging-the-javascript-bundle)
 - [Running the tests](#running-the-tests)
 - [Running the tests](#running-the-tests)
 
 
-Taipy GUI needs your system to have **Python 3.8** or above installed.
+Taipy GUI needs your system to have **Python 3.9** or above installed.
 
 
 ### Installing the latest release
 ### Installing the latest release
 
 

+ 1 - 2
taipy/gui/pyproject.toml

@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
 name = "taipy-gui"
 name = "taipy-gui"
 description = "Low-code library to create graphical user interfaces on the Web for your Python applications."
 description = "Low-code library to create graphical user interfaces on the Web for your Python applications."
 readme = "package_desc.md"
 readme = "package_desc.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 license = {text = "Apache License 2.0"}
 license = {text = "Apache License 2.0"}
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 keywords = ["taipy-gui"]
 keywords = ["taipy-gui"]
@@ -15,7 +15,6 @@ classifiers = [
     "License :: OSI Approved :: Apache Software License",
     "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 0 - 731
taipy/gui/utils/unparse.py

@@ -1,731 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-#        http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
-# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations under the License.
-
-# from https://github.com/python/cpython/blob/3.8/Tools/parser/unparse.py to unparse an ast tree with python < 3.9
-
-import ast
-import io
-import sys
-
-# Large float and imaginary literals get turned into infinities in the AST.
-# We unparse those infinities to INFSTR.
-_INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
-
-
-def _interleave(inter, f, seq):
-    """Call f on each item in seq, calling inter() in between."""
-    seq = iter(seq)
-    try:
-        f(next(seq))
-    except StopIteration:
-        pass
-    else:
-        for x in seq:
-            inter()
-            f(x)
-
-
-class _Unparser:
-    """Methods in this class recursively traverse an AST and
-    output source code for the abstract syntax; original formatting
-    is disregarded."""
-
-    def __init__(self, tree, file=sys.stdout):
-        """Unparser(tree, file=sys.stdout) -> None.
-        Print the source for tree to file."""
-        self.f = file
-        self._indent = 0
-        self.dispatch(tree)
-        print("", file=self.f)
-        self.f.flush()
-
-    def fill(self, text=""):
-        "Indent a piece of text, according to the current indentation level"
-        self.f.write("\n" + "    " * self._indent + text)
-
-    def write(self, text):
-        "Append a piece of text to the current line."
-        self.f.write(text)
-
-    def enter(self):
-        "Print ':', and increase the indentation."
-        self.write(":")
-        self._indent += 1
-
-    def leave(self):
-        "Decrease the indentation level."
-        self._indent -= 1
-
-    def dispatch(self, tree):
-        "Dispatcher function, dispatching tree type T to method _T."
-        if isinstance(tree, list):
-            for t in tree:
-                self.dispatch(t)
-            return
-        meth = getattr(self, "_" + tree.__class__.__name__)
-        meth(tree)
-
-    ############### Unparsing methods ######################
-    # There should be one method per concrete grammar type #
-    # Constructors should be grouped by sum type. Ideally, #
-    # this would follow the order in the grammar, but      #
-    # currently doesn't.                                   #
-    ########################################################
-
-    def _Module(self, tree):
-        for stmt in tree.body:
-            self.dispatch(stmt)
-
-    # stmt
-    def _Expr(self, tree):
-        self.fill()
-        self.dispatch(tree.value)
-
-    def _NamedExpr(self, tree):
-        self.write("(")
-        self.dispatch(tree.target)
-        self.write(" := ")
-        self.dispatch(tree.value)
-        self.write(")")
-
-    def _Import(self, t):
-        self.fill("import ")
-        _interleave(lambda: self.write(", "), self.dispatch, t.names)
-
-    def _ImportFrom(self, t):
-        self.fill("from ")
-        self.write("." * t.level)
-        if t.module:
-            self.write(t.module)
-        self.write(" import ")
-        _interleave(lambda: self.write(", "), self.dispatch, t.names)
-
-    def _Assign(self, t):
-        self.fill()
-        for target in t.targets:
-            self.dispatch(target)
-            self.write(" = ")
-        self.dispatch(t.value)
-
-    def _AugAssign(self, t):
-        self.fill()
-        self.dispatch(t.target)
-        self.write(" " + self.binop[t.op.__class__.__name__] + "= ")
-        self.dispatch(t.value)
-
-    def _AnnAssign(self, t):
-        self.fill()
-        if not t.simple and isinstance(t.target, ast.Name):
-            self.write("(")
-        self.dispatch(t.target)
-        if not t.simple and isinstance(t.target, ast.Name):
-            self.write(")")
-        self.write(": ")
-        self.dispatch(t.annotation)
-        if t.value:
-            self.write(" = ")
-            self.dispatch(t.value)
-
-    def _Return(self, t):
-        self.fill("return")
-        if t.value:
-            self.write(" ")
-            self.dispatch(t.value)
-
-    def _Pass(self, t):
-        self.fill("pass")
-
-    def _Break(self, t):
-        self.fill("break")
-
-    def _Continue(self, t):
-        self.fill("continue")
-
-    def _Delete(self, t):
-        self.fill("del ")
-        _interleave(lambda: self.write(", "), self.dispatch, t.targets)
-
-    def _Assert(self, t):
-        self.fill("assert ")
-        self.dispatch(t.test)
-        if t.msg:
-            self.write(", ")
-            self.dispatch(t.msg)
-
-    def _Global(self, t):
-        self.fill("global ")
-        _interleave(lambda: self.write(", "), self.write, t.names)
-
-    def _Nonlocal(self, t):
-        self.fill("nonlocal ")
-        _interleave(lambda: self.write(", "), self.write, t.names)
-
-    def _Await(self, t):
-        self.write("(")
-        self.write("await")
-        if t.value:
-            self.write(" ")
-            self.dispatch(t.value)
-        self.write(")")
-
-    def _Yield(self, t):
-        self.write("(")
-        self.write("yield")
-        if t.value:
-            self.write(" ")
-            self.dispatch(t.value)
-        self.write(")")
-
-    def _YieldFrom(self, t):
-        self.write("(")
-        self.write("yield from")
-        if t.value:
-            self.write(" ")
-            self.dispatch(t.value)
-        self.write(")")
-
-    def _Raise(self, t):
-        self.fill("raise")
-        if not t.exc:
-            assert not t.cause
-            return
-        self.write(" ")
-        self.dispatch(t.exc)
-        if t.cause:
-            self.write(" from ")
-            self.dispatch(t.cause)
-
-    def _Try(self, t):
-        self.fill("try")
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-        for ex in t.handlers:
-            self.dispatch(ex)
-        if t.orelse:
-            self.fill("else")
-            self.enter()
-            self.dispatch(t.orelse)
-            self.leave()
-        if t.finalbody:
-            self.fill("finally")
-            self.enter()
-            self.dispatch(t.finalbody)
-            self.leave()
-
-    def _ExceptHandler(self, t):
-        self.fill("except")
-        if t.type:
-            self.write(" ")
-            self.dispatch(t.type)
-        if t.name:
-            self.write(" as ")
-            self.write(t.name)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-
-    def _ClassDef(self, t):
-        self.write("\n")
-        for deco in t.decorator_list:
-            self.fill("@")
-            self.dispatch(deco)
-        self.fill("class " + t.name)
-        self.write("(")
-        comma = False
-        for e in t.bases:
-            if comma:
-                self.write(", ")
-            else:
-                comma = True
-            self.dispatch(e)
-        for e in t.keywords:
-            if comma:
-                self.write(", ")
-            else:
-                comma = True
-            self.dispatch(e)
-        self.write(")")
-
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-
-    def _FunctionDef(self, t):
-        self.__FunctionDef_helper(t, "def")
-
-    def _AsyncFunctionDef(self, t):
-        self.__FunctionDef_helper(t, "async def")
-
-    def __FunctionDef_helper(self, t, fill_suffix):
-        self.write("\n")
-        for deco in t.decorator_list:
-            self.fill("@")
-            self.dispatch(deco)
-        def_str = fill_suffix + " " + t.name + "("
-        self.fill(def_str)
-        self.dispatch(t.args)
-        self.write(")")
-        if t.returns:
-            self.write(" -> ")
-            self.dispatch(t.returns)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-
-    def _For(self, t):
-        self.__For_helper("for ", t)
-
-    def _AsyncFor(self, t):
-        self.__For_helper("async for ", t)
-
-    def __For_helper(self, fill, t):
-        self.fill(fill)
-        self.dispatch(t.target)
-        self.write(" in ")
-        self.dispatch(t.iter)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-        if t.orelse:
-            self.fill("else")
-            self.enter()
-            self.dispatch(t.orelse)
-            self.leave()
-
-    def _If(self, t):
-        self.fill("if ")
-        self.dispatch(t.test)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-        # collapse nested ifs into equivalent elifs.
-        while t.orelse and len(t.orelse) == 1 and isinstance(t.orelse[0], ast.If):
-            t = t.orelse[0]
-            self.fill("elif ")
-            self.dispatch(t.test)
-            self.enter()
-            self.dispatch(t.body)
-            self.leave()
-        # final else
-        if t.orelse:
-            self.fill("else")
-            self.enter()
-            self.dispatch(t.orelse)
-            self.leave()
-
-    def _While(self, t):
-        self.fill("while ")
-        self.dispatch(t.test)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-        if t.orelse:
-            self.fill("else")
-            self.enter()
-            self.dispatch(t.orelse)
-            self.leave()
-
-    def _With(self, t):
-        self.fill("with ")
-        _interleave(lambda: self.write(", "), self.dispatch, t.items)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-
-    def _AsyncWith(self, t):
-        self.fill("async with ")
-        _interleave(lambda: self.write(", "), self.dispatch, t.items)
-        self.enter()
-        self.dispatch(t.body)
-        self.leave()
-
-    # expr
-    def _JoinedStr(self, t):
-        self.write("f")
-        string = io.StringIO()
-        self._fstring_JoinedStr(t, string.write)
-        self.write(repr(string.getvalue()))
-
-    def _FormattedValue(self, t):
-        self.write("f")
-        string = io.StringIO()
-        self._fstring_FormattedValue(t, string.write)
-        self.write(repr(string.getvalue()))
-
-    def _fstring_JoinedStr(self, t, write):
-        for value in t.values:
-            meth = getattr(self, "_fstring_" + type(value).__name__)
-            meth(value, write)
-
-    def _fstring_Constant(self, t, write):
-        assert isinstance(t.value, str)
-        value = t.value.replace("{", "{{").replace("}", "}}")
-        write(value)
-
-    def _fstring_FormattedValue(self, t, write):
-        write("{")
-        expr = io.StringIO()
-        _Unparser(t.value, expr)
-        expr = expr.getvalue().rstrip("\n")
-        if expr.startswith("{"):
-            write(" ")  # Separate pair of opening brackets as "{ {"
-        write(expr)
-        if t.conversion != -1:
-            conversion = chr(t.conversion)
-            assert conversion in "sra"
-            write(f"!{conversion}")
-        if t.format_spec:
-            write(":")
-            meth = getattr(self, "_fstring_" + type(t.format_spec).__name__)
-            meth(t.format_spec, write)
-        write("}")
-
-    def _Name(self, t):
-        self.write(t.id)
-
-    def _write_constant(self, value):
-        if isinstance(value, (float, complex)):
-            # Substitute overflowing decimal literal for AST infinities.
-            self.write(repr(value).replace("inf", _INFSTR))
-        else:
-            self.write(repr(value))
-
-    def _Constant(self, t):
-        value = t.value
-        if isinstance(value, tuple):
-            self.write("(")
-            if len(value) == 1:
-                self._write_constant(value[0])
-                self.write(",")
-            else:
-                _interleave(lambda: self.write(", "), self._write_constant, value)
-            self.write(")")
-        elif value is ...:
-            self.write("...")
-        else:
-            if t.kind == "u":
-                self.write("u")
-            self._write_constant(t.value)
-
-    def _List(self, t):
-        self.write("[")
-        _interleave(lambda: self.write(", "), self.dispatch, t.elts)
-        self.write("]")
-
-    def _ListComp(self, t):
-        self.write("[")
-        self.dispatch(t.elt)
-        for gen in t.generators:
-            self.dispatch(gen)
-        self.write("]")
-
-    def _GeneratorExp(self, t):
-        self.write("(")
-        self.dispatch(t.elt)
-        for gen in t.generators:
-            self.dispatch(gen)
-        self.write(")")
-
-    def _SetComp(self, t):
-        self.write("{")
-        self.dispatch(t.elt)
-        for gen in t.generators:
-            self.dispatch(gen)
-        self.write("}")
-
-    def _DictComp(self, t):
-        self.write("{")
-        self.dispatch(t.key)
-        self.write(": ")
-        self.dispatch(t.value)
-        for gen in t.generators:
-            self.dispatch(gen)
-        self.write("}")
-
-    def _comprehension(self, t):
-        if t.is_async:
-            self.write(" async for ")
-        else:
-            self.write(" for ")
-        self.dispatch(t.target)
-        self.write(" in ")
-        self.dispatch(t.iter)
-        for if_clause in t.ifs:
-            self.write(" if ")
-            self.dispatch(if_clause)
-
-    def _IfExp(self, t):
-        self.write("(")
-        self.dispatch(t.body)
-        self.write(" if ")
-        self.dispatch(t.test)
-        self.write(" else ")
-        self.dispatch(t.orelse)
-        self.write(")")
-
-    def _Set(self, t):
-        assert t.elts  # should be at least one element
-        self.write("{")
-        _interleave(lambda: self.write(", "), self.dispatch, t.elts)
-        self.write("}")
-
-    def _Dict(self, t):
-        self.write("{")
-
-        def write_key_value_pair(k, v):
-            self.dispatch(k)
-            self.write(": ")
-            self.dispatch(v)
-
-        def write_item(item):
-            k, v = item
-            if k is None:
-                # for dictionary unpacking operator in dicts {**{'y': 2}}
-                # see PEP 448 for details
-                self.write("**")
-                self.dispatch(v)
-            else:
-                write_key_value_pair(k, v)
-
-        _interleave(lambda: self.write(", "), write_item, zip(t.keys, t.values))
-        self.write("}")
-
-    def _Tuple(self, t):
-        self.write("(")
-        if len(t.elts) == 1:
-            elt = t.elts[0]
-            self.dispatch(elt)
-            self.write(",")
-        else:
-            _interleave(lambda: self.write(", "), self.dispatch, t.elts)
-        self.write(")")
-
-    unop = {"Invert": "~", "Not": "not", "UAdd": "+", "USub": "-"}
-
-    def _UnaryOp(self, t):
-        self.write("(")
-        self.write(self.unop[t.op.__class__.__name__])
-        self.write(" ")
-        self.dispatch(t.operand)
-        self.write(")")
-
-    binop = {
-        "Add": "+",
-        "Sub": "-",
-        "Mult": "*",
-        "MatMult": "@",
-        "Div": "/",
-        "Mod": "%",
-        "LShift": "<<",
-        "RShift": ">>",
-        "BitOr": "|",
-        "BitXor": "^",
-        "BitAnd": "&",
-        "FloorDiv": "//",
-        "Pow": "**",
-    }
-
-    def _BinOp(self, t):
-        self.write("(")
-        self.dispatch(t.left)
-        self.write(" " + self.binop[t.op.__class__.__name__] + " ")
-        self.dispatch(t.right)
-        self.write(")")
-
-    cmpops = {
-        "Eq": "==",
-        "NotEq": "!=",
-        "Lt": "<",
-        "LtE": "<=",
-        "Gt": ">",
-        "GtE": ">=",
-        "Is": "is",
-        "IsNot": "is not",
-        "In": "in",
-        "NotIn": "not in",  # codespell:ignore
-    }
-
-    def _Compare(self, t):
-        self.write("(")
-        self.dispatch(t.left)
-        for o, e in zip(t.ops, t.comparators):
-            self.write(" " + self.cmpops[o.__class__.__name__] + " ")
-            self.dispatch(e)
-        self.write(")")
-
-    boolops = {ast.And: "and", ast.Or: "or"}
-
-    def _BoolOp(self, t):
-        self.write("(")
-        s = " %s " % self.boolops[t.op.__class__]
-        _interleave(lambda: self.write(s), self.dispatch, t.values)
-        self.write(")")
-
-    def _Attribute(self, t):
-        self.dispatch(t.value)
-        # Special case: 3.__abs__() is a syntax error, so if t.value
-        # is an integer literal then we need to either parenthesize
-        # it or add an extra space to get 3 .__abs__().
-        if isinstance(t.value, ast.Constant) and isinstance(t.value.value, int):
-            self.write(" ")
-        self.write(".")
-        self.write(t.attr)
-
-    def _Call(self, t):
-        self.dispatch(t.func)
-        self.write("(")
-        comma = False
-        for e in t.args:
-            if comma:
-                self.write(", ")
-            else:
-                comma = True
-            self.dispatch(e)
-        for e in t.keywords:
-            if comma:
-                self.write(", ")
-            else:
-                comma = True
-            self.dispatch(e)
-        self.write(")")
-
-    def _Subscript(self, t):
-        self.dispatch(t.value)
-        self.write("[")
-        if isinstance(t.slice, ast.Index) and isinstance(t.slice.value, ast.Tuple) and t.slice.value.elts:
-            if len(t.slice.value.elts) == 1:
-                elt = t.slice.value.elts[0]
-                self.dispatch(elt)
-                self.write(",")
-            else:
-                _interleave(lambda: self.write(", "), self.dispatch, t.slice.value.elts)
-        else:
-            self.dispatch(t.slice)
-        self.write("]")
-
-    def _Starred(self, t):
-        self.write("*")
-        self.dispatch(t.value)
-
-    # slice
-    def _Ellipsis(self, t):
-        self.write("...")
-
-    def _Index(self, t):
-        self.dispatch(t.value)
-
-    def _Slice(self, t):
-        if t.lower:
-            self.dispatch(t.lower)
-        self.write(":")
-        if t.upper:
-            self.dispatch(t.upper)
-        if t.step:
-            self.write(":")
-            self.dispatch(t.step)
-
-    def _ExtSlice(self, t):
-        if len(t.dims) == 1:
-            elt = t.dims[0]
-            self.dispatch(elt)
-            self.write(",")
-        else:
-            _interleave(lambda: self.write(", "), self.dispatch, t.dims)
-
-    # argument
-    def _arg(self, t):
-        self.write(t.arg)
-        if t.annotation:
-            self.write(": ")
-            self.dispatch(t.annotation)
-
-    # others
-    def _arguments(self, t):
-        first = True
-        # normal arguments
-        all_args = t.posonlyargs + t.args
-        defaults = [None] * (len(all_args) - len(t.defaults)) + t.defaults
-        for index, elements in enumerate(zip(all_args, defaults), 1):
-            a, d = elements
-            if first:
-                first = False
-            else:
-                self.write(", ")
-            self.dispatch(a)
-            if d:
-                self.write("=")
-                self.dispatch(d)
-            if index == len(t.posonlyargs):
-                self.write(", /")
-
-        # varargs, or bare '*' if no varargs but keyword-only arguments present
-        if t.vararg or t.kwonlyargs:
-            if first:
-                first = False
-            else:
-                self.write(", ")
-            self.write("*")
-            if t.vararg:
-                self.write(t.vararg.arg)
-                if t.vararg.annotation:
-                    self.write(": ")
-                    self.dispatch(t.vararg.annotation)
-
-        # keyword-only arguments
-        if t.kwonlyargs:
-            for a, d in zip(t.kwonlyargs, t.kw_defaults):
-                if first:
-                    first = False
-                else:
-                    self.write(", ")
-                (self.dispatch(a),)
-                if d:
-                    self.write("=")
-                    self.dispatch(d)
-
-        # kwargs
-        if t.kwarg:
-            if first:
-                first = False
-            else:
-                self.write(", ")
-            self.write("**" + t.kwarg.arg)
-            if t.kwarg.annotation:
-                self.write(": ")
-                self.dispatch(t.kwarg.annotation)
-
-    def _keyword(self, t):
-        if t.arg is None:
-            self.write("**")
-        else:
-            self.write(t.arg)
-            self.write("=")
-        self.dispatch(t.value)
-
-    def _Lambda(self, t):
-        self.write("(")
-        self.write("lambda ")
-        self.dispatch(t.args)
-        self.write(": ")
-        self.dispatch(t.body)
-        self.write(")")
-
-    def _alias(self, t):
-        self.write(t.name)
-        if t.asname:
-            self.write(" as " + t.asname)
-
-    def _withitem(self, t):
-        self.dispatch(t.context_expr)
-        if t.optional_vars:
-            self.write(" as ")
-            self.dispatch(t.optional_vars)

+ 2 - 6
taipy/gui_core/_context.py

@@ -12,16 +12,12 @@
 import datetime
 import datetime
 import json
 import json
 import typing as t
 import typing as t
+import zoneinfo
 from collections import defaultdict
 from collections import defaultdict
 from numbers import Number
 from numbers import Number
 from pathlib import Path
 from pathlib import Path
 from threading import Lock
 from threading import Lock
 
 
-try:
-    import zoneinfo
-except ImportError:
-    from backports import zoneinfo  # type: ignore[no-redef]
-
 import pandas as pd
 import pandas as pd
 from dateutil import parser
 from dateutil import parser
 
 
@@ -715,7 +711,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 )
                 )
             else:
             else:
                 if isinstance(scenarios, (list, tuple)) and len(scenarios) > 1:
                 if isinstance(scenarios, (list, tuple)) and len(scenarios) > 1:
-                    base_list = scenarios
+                    base_list = list(scenarios)
                 else:
                 else:
                     if self.data_nodes_by_owner:
                     if self.data_nodes_by_owner:
                         owners = scenarios if isinstance(scenarios, (list, tuple)) else [scenarios]
                         owners = scenarios if isinstance(scenarios, (list, tuple)) else [scenarios]

+ 1 - 2
taipy/rest/pyproject.toml

@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
 name = "taipy-rest"
 name = "taipy-rest"
 description = "Library to expose taipy-core REST APIs."
 description = "Library to expose taipy-core REST APIs."
 readme = "package_desc.md"
 readme = "package_desc.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 license = {text = "Apache License 2.0"}
 license = {text = "Apache License 2.0"}
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 keywords = ["taipy-rest"]
 keywords = ["taipy-rest"]
@@ -15,7 +15,6 @@ classifiers = [
     "License :: OSI Approved :: Apache Software License",
     "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 1 - 2
taipy/templates/pyproject.toml

@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
 name = "taipy-templates"
 name = "taipy-templates"
 description = "An open-source package holding Taipy application templates."
 description = "An open-source package holding Taipy application templates."
 readme = "package_desc.md"
 readme = "package_desc.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 license = {text = "Apache License 2.0"}
 license = {text = "Apache License 2.0"}
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 authors = [{name = "Avaiga", email = "dev@taipy.io"}]
 keywords = ["taipy-templates"]
 keywords = ["taipy-templates"]
@@ -15,7 +15,6 @@ classifiers = [
     "License :: OSI Approved :: Apache Software License",
     "License :: OSI Approved :: Apache Software License",
     "Natural Language :: English",
     "Natural Language :: English",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.11",

+ 0 - 1
tools/packages/pipfiles/Pipfile3.10.max

@@ -58,7 +58,6 @@ version = "==4.2.13"
 "sqlalchemy" = {version="==2.0.30"}
 "sqlalchemy" = {version="==2.0.30"}
 "toml" = {version="==0.10.2"}
 "toml" = {version="==0.10.2"}
 "boto3" = {version="==1.34.113"}
 "boto3" = {version="==1.34.113"}
-"backports.zoneinfo" = {version="==0.2.1", markers="python_version<'3.9'"}
 "cookiecutter" = {version="==2.6.0"}
 "cookiecutter" = {version="==2.6.0"}
 "flask" = {version="==3.0.3"}
 "flask" = {version="==3.0.3"}
 "flask-cors" = {version="==5.0.0"}
 "flask-cors" = {version="==5.0.0"}

+ 0 - 1
tools/packages/pipfiles/Pipfile3.11.max

@@ -58,7 +58,6 @@ version = "==4.2.13"
 "sqlalchemy" = {version="==2.0.30"}
 "sqlalchemy" = {version="==2.0.30"}
 "toml" = {version="==0.10.2"}
 "toml" = {version="==0.10.2"}
 "boto3" = {version="==1.34.113"}
 "boto3" = {version="==1.34.113"}
-"backports.zoneinfo" = {version="==0.2.1", markers="python_version<'3.9'"}
 "cookiecutter" = {version="==2.6.0"}
 "cookiecutter" = {version="==2.6.0"}
 "flask" = {version="==3.0.3"}
 "flask" = {version="==3.0.3"}
 "flask-cors" = {version="==5.0.0"}
 "flask-cors" = {version="==5.0.0"}

+ 0 - 1
tools/packages/pipfiles/Pipfile3.12.max

@@ -58,7 +58,6 @@ version = "==4.2.13"
 "sqlalchemy" = {version="==2.0.30"}
 "sqlalchemy" = {version="==2.0.30"}
 "toml" = {version="==0.10.2"}
 "toml" = {version="==0.10.2"}
 "boto3" = {version="==1.34.113"}
 "boto3" = {version="==1.34.113"}
-"backports.zoneinfo" = {version="==0.2.1", markers="python_version<'3.9'"}
 "cookiecutter" = {version="==2.6.0"}
 "cookiecutter" = {version="==2.6.0"}
 "flask" = {version="==3.0.3"}
 "flask" = {version="==3.0.3"}
 "flask-cors" = {version="==5.0.0"}
 "flask-cors" = {version="==5.0.0"}

+ 0 - 83
tools/packages/pipfiles/Pipfile3.8.max

@@ -1,83 +0,0 @@
-[[source]]
-url = "https://pypi.org/simple"
-verify_ssl = true
-name = "pypi"
-
-[dev-packages]
-freezegun = "*"
-ipython = "*"
-ipykernel = "*"
-mkdocs = "*"
-mkdocs-autorefs = "*"
-mkdocs-include-markdown-plugin = "*"
-mkdocs-macros-plugin = "*"
-mkdocs-material = "==7.3.0"
-mkdocs-material-extensions = "*"
-mkdocstrings = "*"
-mongomock = "*"
-requests = "*"
-ruff = "*"
-pandas-stubs = "*"
-playwright = "*"
-pre-commit = "*"
-pyopenssl = "*"
-pytest = "==7.4.3"
-pytest-cov = "*"
-pytest-mock = "*"
-pytest-playwright = "*"
-pytest-timeout = "*"
-python-dotenv = "*"
-testbook = "*"
-tox = "*"
-twine = "*"
-types-flask = "*"
-types-Flask-Cors = "*"
-types-Markdown = "*"
-types-python-dateutil = "*"
-types-pytz = "*"
-types-toml = ">=0.10.0"
-types-tzlocal = "*"
-
-[requires]
-python_version = "3"
-
-[pipenv]
-allow_prereleases = true
-
-[dev-packages.moto]
-extras = [ "s3",]
-version = "==4.2.13"
-
-
-[packages]
-"pyarrow" = {version="==17.0.0"}
-"networkx" = {version="==3.1", markers="python_version<'3.9'"}
-"openpyxl" = {version="==3.1.2"}
-"pandas" = {version="==2.0.3", markers="python_version<'3.9'"}
-"pymongo" = {version="==4.7.2", extras=["srv"]}
-"sqlalchemy" = {version="==2.0.30"}
-"toml" = {version="==0.10.2"}
-"boto3" = {version="==1.34.113"}
-"backports.zoneinfo" = {version="==0.2.1", markers="python_version<'3.9'"}
-"cookiecutter" = {version="==2.6.0"}
-"flask" = {version="==3.0.3"}
-"flask-cors" = {version="==5.0.0"}
-"flask-socketio" = {version="==5.3.6"}
-"markdown" = {version="==3.6"}
-"python-dotenv" = {version="==1.0.1"}
-"pytz" = {version="==2024.1"}
-"tzlocal" = {version="==5.2"}
-"gevent" = {version="==24.2.1"}
-"gevent-websocket" = {version="==0.10.1"}
-"kthread" = {version="==0.2.3"}
-"gitignore-parser" = {version="==0.1.11"}
-"simple-websocket" = {version="==1.0.0"}
-"twisted" = {version="==24.7.0"}
-"deepdiff" = {version="==7.0.1"}
-"flask-restful" = {version="==0.3.10"}
-"passlib" = {version="==1.7.4"}
-"marshmallow" = {version="==3.21.2"}
-"apispec" = {version="==6.6.1", extras=["yaml"]}
-"apispec-webframeworks" = {version="==1.1.0"}
-"watchdog" = {version="==4.0.1"}
-"charset-normalizer" = {version="==3.3.2"}

+ 0 - 1
tools/packages/pipfiles/Pipfile3.9.max

@@ -58,7 +58,6 @@ version = "==4.2.13"
 "sqlalchemy" = {version="==2.0.30"}
 "sqlalchemy" = {version="==2.0.30"}
 "toml" = {version="==0.10.2"}
 "toml" = {version="==0.10.2"}
 "boto3" = {version="==1.34.113"}
 "boto3" = {version="==1.34.113"}
-"backports.zoneinfo" = {version="==0.2.1", markers="python_version<'3.9'"}
 "cookiecutter" = {version="==2.6.0"}
 "cookiecutter" = {version="==2.6.0"}
 "flask" = {version="==3.0.3"}
 "flask" = {version="==3.0.3"}
 "flask-cors" = {version="==5.0.0"}
 "flask-cors" = {version="==5.0.0"}

+ 0 - 1
tools/packages/taipy-gui/setup.requirements.txt

@@ -1,4 +1,3 @@
-backports.zoneinfo>=0.2.1,<=0.2.1;python_version<'3.9'
 charset-normalizer>=3.3.2,<=3.3.2
 charset-normalizer>=3.3.2,<=3.3.2
 flask>=3.0.0,<=3.0.3
 flask>=3.0.0,<=3.0.3
 flask-cors>=5.0.0,<5.1
 flask-cors>=5.0.0,<5.1

+ 0 - 1
tools/packages/taipy/setup.requirements.txt

@@ -1,4 +1,3 @@
-backports.zoneinfo>=0.2.1,<=0.2.1;python_version<'3.9'
 cookiecutter>=2.1.1,<=2.6.0
 cookiecutter>=2.1.1,<=2.6.0
 taipy-gui
 taipy-gui
 taipy-rest
 taipy-rest