浏览代码

FIx flask-cors and pymongo vulnerabilities (#1954)

* FIx flask-cors and pymongo vulnerabilities

* ruff checks

* ruff checks

* ruff checks

* deppdiff for np.float?

* pandas 2.0 issue

* Numpy for Python 3.8

* Numpy for Python 3.12

* #2 attempt for supporting numpy for Python 3.12

* Stop supporting 3.8

* Per Fred

* fix test

* Update version to 3.1.2

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Jean-Robin 7 月之前
父节点
当前提交
14c72b4cd9

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

@@ -12,7 +12,7 @@ jobs:
     timeout-minutes: 20
     strategy:
       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]
     permissions:
       contents: write

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

@@ -17,7 +17,7 @@ jobs:
     strategy:
       fail-fast: false
       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-latest]
         pipfile-version: ['min', 'max']
     runs-on: ${{ matrix.os }}
@@ -52,7 +52,7 @@ jobs:
     strategy:
       fail-fast: false
       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-latest]
         orchestrator: ['orchestrator_dispatcher', 'standalone']
         pipfile-version: ['min', 'max']

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

@@ -17,7 +17,7 @@ jobs:
     timeout-minutes: 30
     strategy:
       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-latest] #, windows-latest]
 
     runs-on: ${{ matrix.os }}

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

@@ -25,7 +25,7 @@ jobs:
     strategy:
       fail-fast: false
       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-latest]
     runs-on: ${{ matrix.os }}
     steps:
@@ -120,7 +120,7 @@ jobs:
     strategy:
       fail-fast: false
       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-latest]
     runs-on: ${{ matrix.os }}
     steps:
@@ -159,7 +159,7 @@ jobs:
     strategy:
       fail-fast: false
       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-latest]
     runs-on: ${{ matrix.os }}
     steps:

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

@@ -15,7 +15,7 @@ jobs:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
         with:
-          python-version: 3.8
+          python-version: 3.9
 
       - name: Extract Github Tag Version
         id: vars
@@ -104,7 +104,7 @@ jobs:
     timeout-minutes: 30
     strategy:
       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-latest]
     runs-on: ${{ matrix.os }}
     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
 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
 

+ 4 - 3
Pipfile

@@ -8,9 +8,9 @@ apispec = {extras = ["yaml"], version = "==6.3"}
 apispec-webframeworks = "==0.5.2"
 "backports.zoneinfo" = {version="==0.2.1", markers="python_version < '3.9'", extras=["tzdata"]}
 cookiecutter = "==2.1.1"
-deepdiff = "==6.2.2"
+deepdiff = "==6.7.1"
 flask = "==3.0.0"
-flask-cors = "==4.0.0"
+flask-cors = "==5.0.0"
 flask-socketio = "==5.3.6"
 Flask-RESTful = ">=0.3.9"
 gevent = "==23.7.0"
@@ -20,10 +20,11 @@ kthread = "==0.2.3"
 markdown = "==3.4.4"
 marshmallow = "==3.20.1"
 networkx = "==2.6"
+numpy = "==1.26.4"
 openpyxl = "==3.1.2"
 pandas = "==1.3.5"
 pyarrow = "==14.0.2"
-pymongo = {extras = ["srv"], version = "==4.2.0"}
+pymongo = {extras = ["srv"], version = "==4.6.3"}
 python-dotenv = "==1.0.0"
 python-magic = {version = "==0.4.24", markers="sys_platform != 'win32'"}
 python-magic-bin = {version = "==0.4.14", markers="sys_platform == 'win32'"}

+ 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:
 
-- Python 3.8 or higher;
+- Python 3.9 or higher;
 - Taipy GUI 2.2 or higher;
 - [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.

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

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

+ 1 - 2
setup.py

@@ -71,13 +71,12 @@ class NPMInstall(build_py):
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 3 - 3
taipy/config/common/_template_handler.py

@@ -51,11 +51,11 @@ class _TemplateHandler:
                 if required:
                     raise MissingEnvVariableError(f"Environment variable {var} is not set.")
                 return default
-            if type == bool:
+            if type is bool:
                 return cls._to_bool(val)
-            elif type == int:
+            elif type is int:
                 return cls._to_int(val)
-            elif type == float:
+            elif type is float:
                 return cls._to_float(val)
             elif type == Scope:
                 return cls._to_scope(val)

+ 1 - 2
taipy/config/setup.py

@@ -35,13 +35,12 @@ test_requirements = ["pytest>=3.8"]
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 1
taipy/config/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 1}
+{"major": 3, "minor": 1, "patch": 2}

+ 1 - 1
taipy/core/_entity/_dag.py

@@ -89,7 +89,7 @@ class _DAG:
     @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.
+        # For compatibility with Python 3. 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/setup.py

@@ -59,13 +59,12 @@ extras_require = {
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 1
taipy/core/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 1}
+{"major": 3, "minor": 1, "patch": 2}

+ 1 - 1
taipy/gui/INSTALLATION.md

@@ -14,7 +14,7 @@ you plan to use it:
 
 
 
-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
 

+ 2 - 2
taipy/gui/data/array_dict_data_accessor.py

@@ -33,14 +33,14 @@ class _ArrayDictDataAccessor(_PandasDataAccessor):
             types = {type(x) for x in value}
             if len(types) == 1:
                 type_elt = next(iter(types), None)
-                if type_elt == list:
+                if type_elt is list:
                     lengths = {len(x) for x in value}
                     return (
                         pd.DataFrame(value)
                         if len(lengths) == 1
                         else [pd.DataFrame({f"{i}/0": v}) for i, v in enumerate(value)]
                     )
-                elif type_elt == dict:
+                elif type_elt is dict:
                     return [pd.DataFrame(v) for v in value]
                 elif type_elt == _MapDict:
                     return [pd.DataFrame(v._dict) for v in value]

+ 1 - 2
taipy/gui/setup.py

@@ -73,13 +73,12 @@ class NPMInstall(build_py):
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 1
taipy/gui/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 4}
+{"major": 3, "minor": 1, "patch": 5}

+ 1 - 2
taipy/rest/setup.py

@@ -44,7 +44,7 @@ setup(
     author="Avaiga",
     name="taipy-rest",
     keywords="taipy-rest",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     version=version_string,
     author_email="dev@taipy.io",
     packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.rest"]),
@@ -59,7 +59,6 @@ setup(
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 1
taipy/rest/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 1}
+{"major": 3, "minor": 1, "patch": 2}

+ 1 - 2
taipy/templates/setup.py

@@ -31,13 +31,12 @@ test_requirements = ["pytest>=3.8"]
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 1
taipy/templates/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 1}
+{"major": 3, "minor": 1, "patch": 2}

+ 1 - 1
taipy/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 1}
+{"major": 3, "minor": 1, "patch": 2}

+ 9 - 9
tests/core/config/test_file_config.py

@@ -193,9 +193,9 @@ def test_read_configuration_file():
     Config.override(file_config.filename)
 
     assert len(Config.data_nodes) == 4
-    assert type(Config.data_nodes["my_datanode"]) == DataNodeConfig
-    assert type(Config.data_nodes["my_datanode2"]) == DataNodeConfig
-    assert type(Config.data_nodes["my_datanode3"]) == DataNodeConfig
+    assert type(Config.data_nodes["my_datanode"]) is DataNodeConfig
+    assert type(Config.data_nodes["my_datanode2"]) is DataNodeConfig
+    assert type(Config.data_nodes["my_datanode3"]) is DataNodeConfig
     assert Config.data_nodes["my_datanode"].path == "/data/csv"
     assert Config.data_nodes["my_datanode2"].path == "/data2/csv"
     assert Config.data_nodes["my_datanode3"].path == "/data3/csv"
@@ -206,27 +206,27 @@ def test_read_configuration_file():
     assert Config.data_nodes["my_datanode3"].source == "local"
 
     assert len(Config.tasks) == 2
-    assert type(Config.tasks["my_task"]) == TaskConfig
+    assert type(Config.tasks["my_task"]) is TaskConfig
     assert Config.tasks["my_task"].id == "my_task"
     assert Config.tasks["my_task"].description == "task description"
     assert Config.tasks["my_task"].function == print
     assert len(Config.tasks["my_task"].inputs) == 1
-    assert type(Config.tasks["my_task"].inputs[0]) == DataNodeConfig
+    assert type(Config.tasks["my_task"].inputs[0]) is DataNodeConfig
     assert Config.tasks["my_task"].inputs[0].path == "/data/csv"
     assert Config.tasks["my_task"].inputs[0].id == "my_datanode"
     assert len(Config.tasks["my_task"].outputs) == 1
-    assert type(Config.tasks["my_task"].outputs[0]) == DataNodeConfig
+    assert type(Config.tasks["my_task"].outputs[0]) is DataNodeConfig
     assert Config.tasks["my_task"].outputs[0].path == "/data2/csv"
     assert Config.tasks["my_task"].outputs[0].id == "my_datanode2"
 
     assert len(Config.scenarios) == 2
-    assert type(Config.scenarios["my_scenario"]) == ScenarioConfig
+    assert type(Config.scenarios["my_scenario"]) is ScenarioConfig
     assert Config.scenarios["my_scenario"].id == "my_scenario"
     assert Config.scenarios["my_scenario"].owner == "John Doe"
     assert len(Config.scenarios["my_scenario"].tasks) == 1
-    assert type(Config.scenarios["my_scenario"].tasks[0]) == TaskConfig
+    assert type(Config.scenarios["my_scenario"].tasks[0]) is TaskConfig
     assert len(Config.scenarios["my_scenario"].additional_data_nodes) == 1
-    assert type(Config.scenarios["my_scenario"].additional_data_nodes[0]) == DataNodeConfig
+    assert type(Config.scenarios["my_scenario"].additional_data_nodes[0]) is DataNodeConfig
     assert Config.scenarios["my_scenario"].tasks[0].id == "my_task"
     assert Config.scenarios["my_scenario"].tasks[0].description == "task description"
     assert Config.scenarios["my_scenario"].additional_data_nodes[0].id == "my_datanode3"

+ 9 - 4
tests/gui/gui_specific/test_gui.py

@@ -8,17 +8,20 @@
 # 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.
-
+import inspect
 import json
+from contextlib import nullcontext
 
 import pandas as pd
 import pytest
 
 from taipy.gui import Gui
-from taipy.gui.utils import _TaipyContent
+from taipy.gui.utils import _get_module_name_from_frame, _TaipyContent
 
 
 def test__get_real_var_name(gui: Gui):
+    frame = inspect.currentframe()
+    gui._set_frame(frame)
     res = gui._get_real_var_name("")
     assert isinstance(res, tuple)
     assert res[0] == ""
@@ -26,8 +29,10 @@ def test__get_real_var_name(gui: Gui):
 
     gui.run(run_server=False)
     with gui.get_flask_app().app_context():
-        with pytest.raises(NameError):
-            res = gui._get_real_var_name(f"{_TaipyContent.get_hash()}_var")
+        with gui._set_locals_context(_get_module_name_from_frame(frame)) if frame else nullcontext():
+            with pytest.raises(NameError):
+                res = gui._get_real_var_name(f"{_TaipyContent.get_hash()}_var")
+
 
 
 def test__get_user_instance(gui: Gui):

+ 1 - 1
tests/gui/utils/test_types.py

@@ -24,7 +24,7 @@ def test_taipy_base():
     assert tb.get_name() == "hash"
     tb.set("a value")
     assert tb.get() == "a value"
-    assert tb.get_hash() == NotImplementedError
+    assert tb.get_hash() is NotImplementedError
 
 
 def test_taipy_bool():

+ 1 - 2
tools/packages/taipy-config/setup.py

@@ -38,13 +38,12 @@ test_requirements = ["pytest>=3.8"]
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 2
tools/packages/taipy-core/setup.py

@@ -46,13 +46,12 @@ extras_require = {
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

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

@@ -2,6 +2,7 @@ boto3>=1.29.4,<=1.34.34
 networkx>=2.6,<=3.2.1
 openpyxl>=3.1.2,<=3.1.2
 pandas>=1.3.5,<=2.2.0
+numpy>=1.24.4,<=1.26.4
 pyarrow>=14.0.2,<=15.0.0
 pymongo[srv]>=4.2.0,<=4.6.1
 sqlalchemy>=2.0.16,<=2.0.25

+ 1 - 2
tools/packages/taipy-gui/setup.py

@@ -76,13 +76,12 @@ class NPMInstall(build_py):
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

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

@@ -8,6 +8,7 @@ gitignore-parser>=0.1,<=0.1.11
 kthread>=0.2.3,<=0.2.3
 markdown>=3.4.4,<=3.5.2
 pandas>=1.3.5,<=2.2.0
+numpy>=1.24.4,<=1.26.4
 python-dotenv>=1.0.0,<=1.0.1
 pytz>=2021.3,<=2023.3.post1
 simple-websocket>=0.10.1,<=1.0.0

+ 1 - 2
tools/packages/taipy-rest/setup.py

@@ -34,7 +34,7 @@ setup(
     author="Avaiga",
     name="taipy-rest",
     keywords="taipy-rest",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     version=version_string,
     author_email="dev@taipy.io",
     packages=find_packages(where=root_folder, include=["taipy", "taipy.rest", "taipy.rest.*"]),
@@ -48,7 +48,6 @@ setup(
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 2
tools/packages/taipy-templates/setup.py

@@ -38,13 +38,12 @@ test_requirements = ["pytest>=3.8"]
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",

+ 1 - 2
tools/packages/taipy/setup.py

@@ -60,13 +60,12 @@ class NPMInstall(build_py):
 setup(
     author="Avaiga",
     author_email="dev@taipy.io",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     classifiers=[
         "Intended Audience :: Developers",
         "License :: OSI Approved :: Apache Software License",
         "Natural Language :: English",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",