1
0
Эх сурвалжийг харах

Merge branch 'develop' into test/StatusList

Nam Nguyen 9 сар өмнө
parent
commit
f73eb9b781

+ 6 - 1
.github/workflows/build-and-release-single-package.yml

@@ -153,10 +153,15 @@ jobs:
         run: |
           cp -r taipy/_cli/. ${{ steps.set-variables.outputs.package_dir }}/taipy/_cli
 
+      - name: Update pyproject.toml
+        working-directory: ${{ steps.set-variables.outputs.package_dir }}
+        run: |
+          python tools/release/setup_project.py . prod
+
       - name: Build package
         working-directory: ${{ steps.set-variables.outputs.package_dir }}
         run: |
-          python setup.py build_py && python -m build
+          python -m build
 
       - name: Rename files
         run: |

+ 13 - 8
.github/workflows/build-and-release.yml

@@ -151,10 +151,15 @@ jobs:
         run: |
           cp -r taipy/_cli/. ${{ steps.set-variables.outputs.package_dir }}/taipy/_cli
 
+      - name: Update pyproject.toml
+        working-directory: ${{ steps.set-variables.outputs.package_dir }}
+        run: |
+          python tools/release/setup_project.py . prod
+
       - name: Build package
         working-directory: ${{ steps.set-variables.outputs.package_dir }}
         run: |
-          python setup.py build_py && python -m build
+          python -m build
           for file in ./dist/*; do mv "$file" "${file//_/-}"; done
 
       - name: Create tag and release
@@ -204,18 +209,18 @@ jobs:
           python -m pip install --upgrade pip
           pip install build wheel
 
-
-      - name: Backup setup.py
-        run: |
-          mv setup.py setup.old.py
-
       - name: Copy files from tools
         run: |
           cp -r tools/packages/taipy/. .
 
+      - name: Update pyproject.toml
+        working-directory: ${{ steps.set-variables.outputs.package_dir }}
+        run: |
+          python tools/release/setup_project.py . prod
+
       - name: Build Taipy package
         run: |
-          python setup.py build_py && python -m build
+          python -m build
 
       - name: Create tag and release Taipy
         run: |
@@ -244,7 +249,7 @@ jobs:
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
-      - uses: stefanzweifel/git-auto-commit-action@v4
+      - uses: stefanzweifel/git-auto-commit-action@v5
         with:
           file_pattern: '*/version.json'
           commit_message: Update version to ${{ needs.fetch-versions.outputs.NEW_VERSION }}

+ 1 - 1
.github/workflows/check-config-pyi.yml

@@ -18,6 +18,6 @@ jobs:
           python-version: '3.11'
       - name: Update config.pyi
         run: python taipy/config/stubs/generate_pyi.py
-      - uses: stefanzweifel/git-auto-commit-action@v4
+      - uses: stefanzweifel/git-auto-commit-action@v5
         with:
           commit_message: "Update config.pyi"

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

@@ -31,11 +31,28 @@ jobs:
         with:
           python-version: ${{ matrix.python-versions }}
 
+      - name: Install Dependencies
+        run: |
+          pip install toml
+
       - name: Build frontends
         run: |
           python tools/frontend/bundle_build.py
 
-      - name: Install Taipy without dependencies
+      - name: Update pyproject.toml
+        run: |
+          python tools/release/setup_project.py taipy/config
+          python tools/release/setup_project.py taipy/core
+          python tools/release/setup_project.py taipy/gui
+          python tools/release/setup_project.py taipy/rest
+          python tools/release/setup_project.py taipy/templates
+          python tools/release/setup_project.py .
+
+      - name: Install Taipy Subpackages
+        run: |
+          pip install taipy/config taipy/core taipy/gui taipy/rest taipy/templates
+
+      - name: Install Taipy
         run: |
           pip install .
 

+ 64 - 0
pyproject.toml

@@ -1,3 +1,67 @@
+[build-system]
+requires = ["setuptools>=42", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "taipy"
+version = "0.0.0"  # will be dynamically set
+description = "A 360° open-source platform from Python pilots to production-ready web apps."
+readme = "package_desc.md"
+requires-python = ">=3.8"
+license = {text = "Apache License 2.0"}
+keywords = ["taipy"]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "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",
+    "Programming Language :: Python :: 3.12",
+    "Topic :: Software Development",
+    "Topic :: Scientific/Engineering",
+    "Operating System :: Microsoft :: Windows",
+    "Operating System :: POSIX",
+    "Operating System :: Unix",
+    "Operating System :: MacOS",
+]
+dependencies = []  # will be dynamically set
+
+[project.optional-dependencies]
+test = ["pytest>=3.8"]
+ngrok = ["pyngrok>=5.1,<6.0"]
+image = [
+    "python-magic>=0.4.24,<0.5; platform_system!='Windows'",
+    "python-magic-bin>=0.4.14,<0.5; platform_system=='Windows'"
+]
+rdp = ["rdp>=0.8"]
+arrow = ["pyarrow>=14.0.2,<15.0"]
+mssql = ["pyodbc>=4"]
+
+[project.urls]
+Homepage = "https://www.taipy.io"
+Documentation = "https://docs.taipy.io"
+Source = "https://github.com/Avaiga/taipy"
+Download = "https://pypi.org/project/taipy/#files"
+Tracker = "https://github.com/Avaiga/taipy/issues"
+Security = "https://github.com/Avaiga/taipy?tab=security-ov-file#readme"
+"Release notes" = "https://docs.taipy.io/en/release-0.0.0/relnotes/"  # version will be dynamically set
+
+[tool.setuptools.packages.find]
+include = ["taipy", "taipy.*"]
+
+[tool.setuptools.package-data]
+"taipy" = ["version.json"]
+
+[tool.setuptools]
+zip-safe = false
+
+[project.scripts]
+taipy = "taipy._entrypoint:_entrypoint"
+
 [tool.ruff]
 exclude = [
     ".git",

+ 0 - 121
setup.py

@@ -1,121 +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.
-
-"""The setup script for taipy package"""
-
-import os
-import json
-import platform
-import subprocess
-from pathlib import Path
-
-from setuptools import find_packages, setup
-from setuptools.command.build_py import build_py
-
-root_folder = Path(__file__).parent
-
-package_desc = Path("package_desc.md").read_text("UTF-8")
-
-# get current version
-with open(os.path.join("taipy", "version.json")) as version_file:
-    version = json.load(version_file)
-    version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
-    if vext := version.get("ext"):
-        version_string = f"{version_string}.{vext}"
-
-
-def get_requirements():
-    # get requirements from the different setups in tools/packages (removing taipy packages)
-    reqs = set()
-    for pkg in (root_folder / "tools" / "packages").iterdir():
-        requirements_file = pkg / "setup.requirements.txt"
-        if requirements_file.exists():
-            reqs.update(requirements_file.read_text("UTF-8").splitlines())
-
-    return [r for r in reqs if r and not r.startswith("taipy")]
-
-
-test_requirements = ["pytest>=3.8"]
-
-extras_require = {
-    "ngrok": ["pyngrok>=5.1,<6.0"],
-    "image": [
-        "python-magic>=0.4.24,<0.5;platform_system!='Windows'",
-        "python-magic-bin>=0.4.14,<0.5;platform_system=='Windows'",
-    ],
-    "rdp": ["rdp>=0.8"],
-    "arrow": ["pyarrow>=14.0.2,<15.0"],
-    "mssql": ["pyodbc>=4"],
-}
-
-
-class NPMInstall(build_py):
-    def run(self):
-        subprocess.run(
-            ["python", "bundle_build.py"],
-            cwd=root_folder / "tools" / "frontend",
-            check=True,
-            shell=platform.system() == "Windows",
-        )
-        build_py.run(self)
-
-
-setup(
-    author="Avaiga",
-    author_email="dev@taipy.io",
-    python_requires=">=3.8",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "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",
-        "Programming Language :: Python :: 3.12",
-        "Topic :: Software Development",
-        "Topic :: Scientific/Engineering",
-        "Operating System :: Microsoft :: Windows",
-        "Operating System :: POSIX",
-        "Operating System :: Unix",
-        "Operating System :: MacOS",
-    ],
-    description="A 360° open-source platform from Python pilots to production-ready web apps.",
-    install_requires=get_requirements(),
-    entry_points={
-        "console_scripts": [
-            "taipy = taipy._entrypoint:_entrypoint",
-        ]
-    },
-    license="Apache License 2.0",
-    long_description=package_desc,
-    long_description_content_type="text/markdown",
-    keywords="taipy",
-    name="taipy",
-    packages=find_packages(include=["taipy", "taipy.*"]),
-    include_package_data=True,
-    test_suite="tests",
-    version=version_string,
-    zip_safe=False,
-    extras_require=extras_require,
-    cmdclass={"build_py": NPMInstall},
-    project_urls={
-        "Homepage": "https://www.taipy.io",
-        "Documentation": "https://docs.taipy.io",
-        "Source": "https://github.com/Avaiga/taipy",
-        "Download": "https://pypi.org/project/taipy/#files",
-        "Tracker": "https://github.com/Avaiga/taipy/issues",
-        "Security": "https://github.com/Avaiga/taipy?tab=security-ov-file#readme",
-        f"Release notes": "https://docs.taipy.io/en/release-{version_string}/relnotes/",
-    },
-)

+ 58 - 0
taipy/config/pyproject.toml

@@ -0,0 +1,58 @@
+[build-system]
+requires = ["setuptools>=42", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "taipy-config"
+version = "0.0.0"  # will be dynamically set
+description = "A Taipy package dedicated to easily configure a Taipy application."
+readme = "package_desc.md"
+requires-python = ">=3.8"
+license = {text = "Apache License 2.0"}
+keywords = ["taipy-config"]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "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",
+    "Programming Language :: Python :: 3.12",
+    "Topic :: Software Development",
+    "Topic :: Scientific/Engineering",
+    "Operating System :: Microsoft :: Windows",
+    "Operating System :: POSIX",
+    "Operating System :: Unix",
+    "Operating System :: MacOS",
+]
+
+dependencies = [
+    "toml>=0.10,<0.11",
+    "deepdiff>=6.7,<6.8"
+]
+
+[project.optional-dependencies]
+test = [
+    "pytest>=3.8"
+]
+
+[project.urls]
+Homepage = "https://www.taipy.io"
+Documentation = "https://docs.taipy.io"
+Source = "https://github.com/Avaiga/taipy"
+Download = "https://pypi.org/project/taipy/#files"
+Tracker = "https://github.com/Avaiga/taipy/issues"
+Security = "https://github.com/Avaiga/taipy?tab=security-ov-file#readme"
+"Release notes" = "https://docs.taipy.io/en/release-0.0.0/relnotes/"  # version will be dynamically set
+
+[tool.setuptools.packages]
+find = {where = ["."], include = ["taipy", "taipy.config", "taipy.config.*", "taipy.logger", "taipy.logger.*"]}
+
+[tool.setuptools.package-data]
+"version" = ["version.json"]
+
+[tool.setuptools]
+zip-safe = false

+ 0 - 80
taipy/config/setup.py

@@ -1,80 +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.
-
-"""The setup script for taipy-config package"""
-
-import json
-import os
-from pathlib import Path
-
-from setuptools import find_namespace_packages, find_packages, setup
-
-package_desc = Path("package_desc.md").read_text("UTF-8")
-
-version_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "version.json")
-
-with open(version_path) as version_file:
-    version = json.load(version_file)
-    version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
-    if vext := version.get("ext"):
-        version_string = f"{version_string}.{vext}"
-
-requirements = ["toml>=0.10,<0.11", "deepdiff>=6.7,<6.8"]
-
-test_requirements = ["pytest>=3.8"]
-
-setup(
-    author="Avaiga",
-    author_email="dev@taipy.io",
-    python_requires=">=3.8",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "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",
-        "Programming Language :: Python :: 3.12",
-        "Topic :: Software Development",
-        "Topic :: Scientific/Engineering",
-        "Operating System :: Microsoft :: Windows",
-        "Operating System :: POSIX",
-        "Operating System :: Unix",
-        "Operating System :: MacOS",
-    ],
-    description="A Taipy package dedicated to easily configure a Taipy application.",
-    install_requires=requirements,
-    long_description=package_desc,
-    long_description_content_type="text/markdown",
-    license="Apache License 2.0",
-    keywords="taipy-config",
-    name="taipy-config",
-    packages=find_namespace_packages(where=".")
-    + find_packages(include=["taipy", "taipy.config", "taipy.config.*", "taipy.logger", "taipy.logger.*"]),
-    include_package_data=True,
-    data_files=[('version', ['version.json'])],
-    test_suite="tests",
-    tests_require=test_requirements,
-    version=version_string,
-    zip_safe=False,
-    project_urls={
-        "Homepage": "https://www.taipy.io",
-        "Documentation": "https://docs.taipy.io",
-        "Source": "https://github.com/Avaiga/taipy",
-        "Download": "https://pypi.org/project/taipy/#files",
-        "Tracker": "https://github.com/Avaiga/taipy/issues",
-        "Security": "https://github.com/Avaiga/taipy?tab=security-ov-file#readme",
-        f"Release notes": "https://docs.taipy.io/en/release-{version_string}/relnotes/",
-    },
-)

+ 3 - 0
taipy/core/_version/_version_manager_factory.py

@@ -9,6 +9,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +22,7 @@ class _VersionManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _VersionFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_VersionManager]:
         if cls._using_enterprise():
             version_manager = _utils._load_fct(
@@ -36,5 +38,6 @@ class _VersionManagerFactory(_ManagerFactory):
         return version_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 3 - 0
taipy/core/cycle/_cycle_manager_factory.py

@@ -9,6 +9,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +22,7 @@ class _CycleManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _CycleFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_CycleManager]:
         if cls._using_enterprise():
             cycle_manager = _load_fct(cls._TAIPY_ENTERPRISE_CORE_MODULE + ".cycle._cycle_manager", "_CycleManager")  # type: ignore
@@ -34,5 +36,6 @@ class _CycleManagerFactory(_ManagerFactory):
         return cycle_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 3 - 1
taipy/core/data/_data_manager_factory.py

@@ -8,7 +8,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +21,7 @@ class _DataManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _DataFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_DataManager]:
         if cls._using_enterprise():
             data_manager = _load_fct(cls._TAIPY_ENTERPRISE_CORE_MODULE + ".data._data_manager", "_DataManager")  # type: ignore
@@ -34,5 +35,6 @@ class _DataManagerFactory(_ManagerFactory):
         return data_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 3 - 1
taipy/core/job/_job_manager_factory.py

@@ -8,7 +8,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +21,7 @@ class _JobManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _JobFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_JobManager]:
         if cls._using_enterprise():
             job_manager = _load_fct(cls._TAIPY_ENTERPRISE_CORE_MODULE + ".job._job_manager", "_JobManager")  # type: ignore
@@ -34,5 +35,6 @@ class _JobManagerFactory(_ManagerFactory):
         return job_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 62 - 0
taipy/core/pyproject.toml

@@ -0,0 +1,62 @@
+[build-system]
+requires = ["setuptools>=42", "wheel", ]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "taipy-core"
+version = "0.0.0"   # will be dynamically set
+description = "A Python library to build powerful and customized data-driven back-end applications."
+readme = "package_desc.md"
+requires-python = ">=3.8"
+keywords = ["taipy-core", ]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "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",
+    "Programming Language :: Python :: 3.12",
+    "Topic :: Software Development",
+    "Topic :: Scientific/Engineering",
+    "Operating System :: Microsoft :: Windows",
+    "Operating System :: POSIX",
+    "Operating System :: Unix",
+    "Operating System :: MacOS",
+]
+
+dependencies = []   # will be dynamically set
+
+[project.license]
+text = "Apache License 2.0"
+
+[project.optional-dependencies]
+test = ["pytest>=3.8", ]
+mssql = ["pyodbc>=4,<4.1", ]
+mysql = ["pymysql>1,<1.1", ]
+postgresql = ["psycopg2>2.9,<2.10", ]
+parquet = ["fastparquet==2022.11.0", "pyarrow>=14.0.2,<15.0", ]
+s3 = ["boto3==1.29.1", ]
+mongo = ["pymongo[srv]>=4.2.0,<5.0", ]
+
+[project.urls]
+Homepage = "https://www.taipy.io"
+Documentation = "https://docs.taipy.io"
+Source = "https://github.com/Avaiga/taipy"
+Download = "https://pypi.org/project/taipy/#files"
+Tracker = "https://github.com/Avaiga/taipy/issues"
+Security = "https://github.com/Avaiga/taipy?tab=security-ov-file#readme"
+"Release notes" = "https://docs.taipy.io/en/release-4.0.0.dev0/relnotes/"
+
+[tool.setuptools]
+zip-safe = false
+
+[tool.setuptools.package-data]
+taipy = ["version.json", ]
+
+[tool.setuptools.packages.find]
+where = [".", ]
+include = ["taipy", "taipy.core", "taipy.core.*", ]

+ 3 - 1
taipy/core/scenario/_scenario_manager_factory.py

@@ -8,7 +8,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +21,7 @@ class _ScenarioManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _ScenarioFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_ScenarioManager]:
         if cls._using_enterprise():
             scenario_manager = _load_fct(
@@ -36,5 +37,6 @@ class _ScenarioManagerFactory(_ManagerFactory):
         return scenario_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 2 - 1
taipy/core/sequence/_sequence_manager_factory.py

@@ -8,7 +8,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -18,6 +18,7 @@ from ._sequence_manager import _SequenceManager
 
 class _SequenceManagerFactory(_ManagerFactory):
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_SequenceManager]:  # type: ignore
         if cls._using_enterprise():
             sequence_manager = _load_fct(

+ 0 - 102
taipy/core/setup.py

@@ -1,102 +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.
-
-"""The setup script for taipy-core package"""
-
-import json
-import os
-from pathlib import Path
-
-from setuptools import find_namespace_packages, find_packages, setup
-
-root_folder = Path(__file__).parent
-
-package_desc = Path("package_desc.md").read_text("UTF-8")
-
-version_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "version.json")
-with open(version_path) as version_file:
-    version = json.load(version_file)
-    version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
-    if vext := version.get("ext"):
-        version_string = f"{version_string}.{vext}"
-
-
-def get_requirements():
-    # get requirements from the different setups in tools/packages (removing taipy packages)
-    reqs = set()
-    for pkg in (root_folder / "tools" / "packages").iterdir():
-        if "taipy-core" not in str(pkg):
-            continue
-        requirements_file = pkg / "setup.requirements.txt"
-        if requirements_file.exists():
-            reqs.update(requirements_file.read_text("UTF-8").splitlines())
-
-    return [r for r in reqs if r and not r.startswith("taipy")]
-
-
-test_requirements = ["pytest>=3.8"]
-
-extras_require = {
-    "mssql": ["pyodbc>=4,<4.1"],
-    "mysql": ["pymysql>1,<1.1"],
-    "postgresql": ["psycopg2>2.9,<2.10"],
-    "parquet": ["fastparquet==2022.11.0", "pyarrow>=14.0.2,<15.0"],
-    "s3": ["boto3==1.29.1"],
-    "mongo": ["pymongo[srv]>=4.2.0,<5.0"],
-}
-
-setup(
-    author="Avaiga",
-    author_email="dev@taipy.io",
-    python_requires=">=3.8",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "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",
-        "Programming Language :: Python :: 3.12",
-        "Topic :: Software Development",
-        "Topic :: Scientific/Engineering",
-        "Operating System :: Microsoft :: Windows",
-        "Operating System :: POSIX",
-        "Operating System :: Unix",
-        "Operating System :: MacOS",
-    ],
-    description="A Python library to build powerful and customized data-driven back-end applications.",
-    install_requires=get_requirements(),
-    long_description=package_desc,
-    long_description_content_type="text/markdown",
-    license="Apache License 2.0",
-    keywords="taipy-core",
-    name="taipy-core",
-    packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.core", "taipy.core.*"]),
-    include_package_data=True,
-    data_files=[('version', ['version.json'])],
-    test_suite="tests",
-    tests_require=test_requirements,
-    version=version_string,
-    zip_safe=False,
-    extras_require=extras_require,
-    project_urls={
-        "Homepage": "https://www.taipy.io",
-        "Documentation": "https://docs.taipy.io",
-        "Source": "https://github.com/Avaiga/taipy",
-        "Download": "https://pypi.org/project/taipy/#files",
-        "Tracker": "https://github.com/Avaiga/taipy/issues",
-        "Security": "https://github.com/Avaiga/taipy?tab=security-ov-file#readme",
-        f"Release notes": "https://docs.taipy.io/en/release-{version_string}/relnotes/",
-    },
-)

+ 3 - 1
taipy/core/submission/_submission_manager_factory.py

@@ -8,7 +8,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +21,7 @@ class _SubmissionManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _SubmissionFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_SubmissionManager]:
         if cls._using_enterprise():
             submission_manager = _load_fct(
@@ -37,5 +38,6 @@ class _SubmissionManagerFactory(_ManagerFactory):
         return submission_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 3 - 1
taipy/core/task/_task_manager_factory.py

@@ -8,7 +8,7 @@
 # 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 functools import lru_cache
 from typing import Type
 
 from .._manager._manager_factory import _ManagerFactory
@@ -21,6 +21,7 @@ class _TaskManagerFactory(_ManagerFactory):
     __REPOSITORY_MAP = {"default": _TaskFSRepository}
 
     @classmethod
+    @lru_cache
     def _build_manager(cls) -> Type[_TaskManager]:
         if cls._using_enterprise():
             task_manager = _load_fct(cls._TAIPY_ENTERPRISE_CORE_MODULE + ".task._task_manager", "_TaskManager")  # type: ignore
@@ -34,5 +35,6 @@ class _TaskManagerFactory(_ManagerFactory):
         return task_manager  # type: ignore
 
     @classmethod
+    @lru_cache
     def _build_repository(cls):
         return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()

+ 2 - 1
taipy/gui/_default_config.py

@@ -58,12 +58,14 @@ default_config: Config = {
     "ngrok_token": "",
     "notebook_proxy": True,
     "notification_duration": 3000,
+    "port": 5000,
     "propagate": True,
     "run_browser": True,
     "run_in_thread": False,
     "run_server": True,
     "server_config": None,
     "single_client": False,
+    "state_retention_period": 0,
     "system_notification": False,
     "theme": None,
     "time_zone": None,
@@ -74,5 +76,4 @@ default_config: Config = {
     "use_reloader": False,
     "watermark": "Taipy inside",
     "webapp_path": None,
-    "port": 5000,
 }

+ 6 - 4
taipy/gui/config.py

@@ -46,6 +46,7 @@ ConfigParameter = t.Literal[
     "ngrok_token",
     "notebook_proxy",
     "notification_duration",
+    "port",
     "propagate",
     "run_browser",
     "run_in_thread",
@@ -56,13 +57,13 @@ ConfigParameter = t.Literal[
     "theme",
     "time_zone",
     "title",
+    "state_retention_period",
     "stylekit",
     "upload_folder",
     "use_arrow",
     "use_reloader",
     "watermark",
     "webapp_path",
-    "port",
 ]
 
 Stylekit = t.TypedDict(
@@ -117,23 +118,24 @@ Config = t.TypedDict(
         "ngrok_token": str,
         "notebook_proxy": bool,
         "notification_duration": int,
+        "port": t.Union[t.Literal["auto"], int],
         "propagate": bool,
         "run_browser": bool,
         "run_in_thread": bool,
         "run_server": bool,
         "server_config": t.Optional[ServerConfig],
         "single_client": bool,
+        "state_retention_period": int,
+        "stylekit": t.Union[bool, Stylekit],
         "system_notification": bool,
         "theme": t.Optional[t.Dict[str, t.Any]],
         "time_zone": t.Optional[str],
         "title": t.Optional[str],
-        "stylekit": t.Union[bool, Stylekit],
         "upload_folder": t.Optional[str],
         "use_arrow": bool,
         "use_reloader": bool,
         "watermark": t.Optional[str],
         "webapp_path": t.Optional[str],
-        "port": t.Union[t.Literal["auto"], int],
     },
     total=False,
 )
@@ -235,7 +237,7 @@ class _Config(object):
                     elif key == "port" and str(value).strip() == "auto":
                         config["port"] = "auto"
                     else:
-                        config[key] = value if config[key] is None else type(config[key])(value)  # type: ignore
+                        config[key] = value if config[key] is None else type(config[key])(value)
                 except Exception as e:
                     _warn(
                         f"Invalid keyword arguments value in Gui.run {key} - {value}. Unable to parse value to the correct type",  # noqa: E501

+ 17 - 0
taipy/gui/gui.py

@@ -26,6 +26,7 @@ import warnings
 from importlib import metadata, util
 from importlib.util import find_spec
 from pathlib import Path
+from threading import Timer
 from types import FrameType, FunctionType, LambdaType, ModuleType, SimpleNamespace
 from urllib.parse import unquote, urlencode, urlparse
 
@@ -611,6 +612,22 @@ class Gui:
 
     def _handle_disconnect(self):
         Hooks()._handle_disconnect(self)
+        if (sid := getattr(request, "sid", None)) and (st_to := self._get_config("state_retention_period", 0)) > 0:
+            for cl_id, sids in self.__client_id_2_sid.items():
+                if sid in sids:
+                    if len(sids) == 1:
+                        Timer(st_to, self._remove_state, [cl_id]).start()
+                    else:
+                        sids.remove(sid)
+                    return
+
+    def _remove_state(self, client_id: str):
+        if (sids := self.__client_id_2_sid.get(client_id, None)) and len(sids) == 1:
+            try:
+                del self.__client_id_2_sid[client_id]
+                self._bindings()._delete_scope(client_id)
+            except Exception as e:
+                _warn(f"Unexpected error removing state {client_id}", e)
 
     def _manage_message(self, msg_type: _WsType, message: dict) -> None:
         try:

+ 1 - 1
taipy/gui/hook.py

@@ -11,7 +11,7 @@ class Hook:
 
 class Hooks(object, metaclass=_Singleton):
     def __init__(self):
-        self.__hooks: t.List[Hook] = []
+        self.__hooks: t.List[Hook] = []  # type: ignore[annotation-unchecked]
 
     def _register_hook(self, hook: Hook):
         # Prevent duplicated hooks

+ 58 - 0
taipy/gui/pyproject.toml

@@ -0,0 +1,58 @@
+[build-system]
+requires = [ "setuptools>=42", "wheel", "setuptools_scm",]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "taipy-gui"
+version = "0.0.0"  # will be set dynamically
+description = "Low-code library to create graphical user interfaces on the Web for your Python applications."
+readme = "package_desc.md"
+requires-python = ">=3.8"
+keywords = [ "taipy-gui",]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "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",
+    "Programming Language :: Python :: 3.12",
+    "Topic :: Software Development",
+    "Topic :: Scientific/Engineering",
+    "Operating System :: Microsoft :: Windows",
+    "Operating System :: POSIX",
+    "Operating System :: Unix",
+    "Operating System :: MacOS",
+]
+dependencies = []  # will be set dynamically
+
+[project.license]
+text = "Apache License 2.0"
+
+[project.optional-dependencies]
+test = [ "pytest>=3.8",]
+ngrok = [ "pyngrok>=5.1,<6.0",]
+image = [ "python-magic>=0.4.24,<0.5; platform_system!='Windows'", "python-magic-bin>=0.4.14,<0.5; platform_system=='Windows'",]
+arrow = [ "pyarrow>=14.0.2,<15.0",]
+
+[project.urls]
+Homepage = "https://www.taipy.io"
+Documentation = "https://docs.taipy.io"
+Source = "https://github.com/Avaiga/taipy"
+Download = "https://pypi.org/project/taipy/#files"
+Tracker = "https://github.com/Avaiga/taipy/issues"
+Security = "https://github.com/Avaiga/taipy?tab=security-ov-file#readme"
+"Release notes" = "https://docs.taipy.io/en/release-0.0.0/relnotes/"  # will be set dynamically
+
+[tool.setuptools]
+zip-safe = false
+
+[tool.setuptools.package-data]
+taipy = [ "version.json",]
+
+[tool.setuptools.packages.find]
+where = [ ".",]
+include = [ "taipy", "taipy.gui", "taipy.gui.*",]

+ 0 - 118
taipy/gui/setup.py

@@ -1,118 +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.
-
-"""The setup script for taipy-gui package"""
-
-import json
-import os
-from pathlib import Path
-
-from setuptools import find_namespace_packages, find_packages, setup
-from setuptools.command.build_py import build_py
-
-root_folder = Path(__file__).parent
-
-package_desc = Path("package_desc.md").read_text("UTF-8")
-
-version_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "version.json")
-with open(version_path) as version_file:
-    version = json.load(version_file)
-    version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
-    if vext := version.get("ext"):
-        version_string = f"{version_string}.{vext}"
-
-
-def get_requirements():
-    # get requirements from the different setups in tools/packages (removing taipy packages)
-    reqs = set()
-    for pkg in (root_folder / "tools" / "packages").iterdir():
-        if "taipy-gui" not in str(pkg):
-            continue
-        requirements_file = pkg / "setup.requirements.txt"
-        if requirements_file.exists():
-            reqs.update(requirements_file.read_text("UTF-8").splitlines())
-
-    return [r for r in reqs if r and not r.startswith("taipy")]
-
-
-test_requirements = ["pytest>=3.8"]
-
-extras_require = {
-    "ngrok": ["pyngrok>=5.1,<6.0"],
-    "image": [
-        "python-magic>=0.4.24,<0.5;platform_system!='Windows'",
-        "python-magic-bin>=0.4.14,<0.5;platform_system=='Windows'",
-    ],
-    "arrow": ["pyarrow>=14.0.2,<15.0"],
-}
-
-
-def _build_webapp():
-    already_exists = Path("./taipy/gui/webapp/index.html").exists()
-    if not already_exists:
-        os.system("cd ../../frontend/taipy-gui/dom && npm ci")
-        os.system("cd ../../frontend/taipy-gui && npm ci --omit=optional && npm run build")
-
-
-class NPMInstall(build_py):
-    def run(self):
-        _build_webapp()
-        build_py.run(self)
-
-
-setup(
-    author="Avaiga",
-    author_email="dev@taipy.io",
-    python_requires=">=3.8",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "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",
-        "Programming Language :: Python :: 3.12",
-        "Topic :: Software Development",
-        "Topic :: Scientific/Engineering",
-        "Operating System :: Microsoft :: Windows",
-        "Operating System :: POSIX",
-        "Operating System :: Unix",
-        "Operating System :: MacOS",
-    ],
-    description="Low-code library to create graphical user interfaces on the Web for your Python applications.",
-    long_description=package_desc,
-    long_description_content_type="text/markdown",
-    install_requires=get_requirements(),
-    license="Apache License 2.0",
-    include_package_data=True,
-    data_files=[("version", ["version.json"])],
-    keywords="taipy-gui",
-    name="taipy-gui",
-    packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.gui", "taipy.gui.*"]),
-    test_suite="tests",
-    tests_require=test_requirements,
-    version=version_string,
-    zip_safe=False,
-    extras_require=extras_require,
-    cmdclass={"build_py": NPMInstall},
-    project_urls={
-        "Homepage": "https://www.taipy.io",
-        "Documentation": "https://docs.taipy.io",
-        "Source": "https://github.com/Avaiga/taipy",
-        "Download": "https://pypi.org/project/taipy/#files",
-        "Tracker": "https://github.com/Avaiga/taipy/issues",
-        "Security": "https://github.com/Avaiga/taipy?tab=security-ov-file#readme",
-        f"Release notes": "https://docs.taipy.io/en/release-{version_string}/relnotes/",
-    },
-)

+ 3 - 0
taipy/gui/utils/_bindings.py

@@ -68,6 +68,9 @@ class _Bindings:
         self.__scopes.create_scope(id)
         return id, create
 
+    def _delete_scope(self, id: str):
+        self.__scopes.delete_scope(id)
+
     def _new_scopes(self):
         self.__scopes = _DataScopes(self.__gui)
 

+ 50 - 0
taipy/rest/pyproject.toml

@@ -0,0 +1,50 @@
+[build-system]
+requires = ["setuptools>=42", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "taipy-rest"
+version = "0.0.0"  # will be dynamically set
+description = "Library to expose taipy-core REST APIs."
+readme = "package_desc.md"
+requires-python = ">=3.8"
+license = {text = "Apache License 2.0"}
+keywords = ["taipy-rest"]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "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",
+    "Programming Language :: Python :: 3.12",
+    "Topic :: Software Development",
+    "Topic :: Scientific/Engineering",
+    "Operating System :: Microsoft :: Windows",
+    "Operating System :: POSIX",
+    "Operating System :: Unix",
+    "Operating System :: MacOS",
+]
+dependencies = []  # will be dynamically set
+
+[project.urls]
+Homepage = "https://www.taipy.io"
+Documentation = "https://docs.taipy.io"
+Source = "https://github.com/Avaiga/taipy"
+Download = "https://pypi.org/project/taipy/#files"
+Tracker = "https://github.com/Avaiga/taipy/issues"
+Security = "https://github.com/Avaiga/taipy?tab=security-ov-file#readme"
+"Release notes" = "https://docs.taipy.io/en/release-0.0.0/relnotes/"  # version will be dynamically set
+
+[tool.setuptools.packages.find]
+where = ["."]
+include = ["taipy", "taipy.rest"]
+
+[tool.setuptools.package-data]
+"taipy" = ["version.json"]
+
+[tool.setuptools]
+zip-safe = false

+ 0 - 87
taipy/rest/setup.py

@@ -1,87 +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.
-
-"""The setup script for taipy-rest package"""
-
-import json
-import os
-from pathlib import Path
-
-from setuptools import find_namespace_packages, find_packages, setup
-
-root_folder = Path(__file__).parent
-
-package_desc = Path("package_desc.md").read_text("UTF-8")
-
-version_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "version.json")
-with open(version_path) as version_file:
-    version = json.load(version_file)
-    version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
-    if vext := version.get("ext"):
-        version_string = f"{version_string}.{vext}"
-
-
-def get_requirements():
-    # get requirements from the different setups in tools/packages (removing taipy packages)
-    reqs = set()
-    for pkg in (root_folder / "tools" / "packages").iterdir():
-        if "taipy-rest" not in str(pkg):
-            continue
-        requirements_file = pkg / "setup.requirements.txt"
-        if requirements_file.exists():
-            reqs.update(requirements_file.read_text("UTF-8").splitlines())
-
-    return [r for r in reqs if r and not r.startswith("taipy")]
-
-
-setup(
-    author="Avaiga",
-    name="taipy-rest",
-    keywords="taipy-rest",
-    python_requires=">=3.8",
-    version=version_string,
-    author_email="dev@taipy.io",
-    packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.rest"]),
-    include_package_data=True,
-    data_files=[('version', ['version.json'])],
-    long_description=package_desc,
-    long_description_content_type="text/markdown",
-    description="Library to expose taipy-core REST APIs.",
-    license="Apache License 2.0",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "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",
-        "Programming Language :: Python :: 3.12",
-        "Topic :: Software Development",
-        "Topic :: Scientific/Engineering",
-        "Operating System :: Microsoft :: Windows",
-        "Operating System :: POSIX",
-        "Operating System :: Unix",
-        "Operating System :: MacOS",
-    ],
-    install_requires=get_requirements(),
-    project_urls={
-        "Homepage": "https://www.taipy.io",
-        "Documentation": "https://docs.taipy.io",
-        "Source": "https://github.com/Avaiga/taipy",
-        "Download": "https://pypi.org/project/taipy/#files",
-        "Tracker": "https://github.com/Avaiga/taipy/issues",
-        "Security": "https://github.com/Avaiga/taipy?tab=security-ov-file#readme",
-        f"Release notes": "https://docs.taipy.io/en/release-{version_string}/relnotes/",
-    },
-)

+ 53 - 0
taipy/templates/pyproject.toml

@@ -0,0 +1,53 @@
+[build-system]
+requires = ["setuptools>=42", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "taipy-templates"
+version = "0.0.0"  # will be dynamically set
+description = "An open-source package holding Taipy application templates."
+readme = "package_desc.md"
+requires-python = ">=3.8"
+license = {text = "Apache License 2.0"}
+keywords = ["taipy-templates"]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "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",
+    "Programming Language :: Python :: 3.12",
+    "Topic :: Software Development",
+    "Topic :: Scientific/Engineering",
+    "Operating System :: Microsoft :: Windows",
+    "Operating System :: POSIX",
+    "Operating System :: Unix",
+    "Operating System :: MacOS",
+]
+dependencies = []  # version will be dynamically set
+
+[project.optional-dependencies]
+test = ["pytest>=3.8"]
+
+[project.urls]
+Homepage = "https://www.taipy.io"
+Documentation = "https://docs.taipy.io"
+Source = "https://github.com/Avaiga/taipy"
+Download = "https://pypi.org/project/taipy/#files"
+Tracker = "https://github.com/Avaiga/taipy/issues"
+Security = "https://github.com/Avaiga/taipy?tab=security-ov-file#readme"
+"Release notes" = "https://docs.taipy.io/en/release-0.0.0/relnotes/"  # version will be dynamically set
+
+[tool.setuptools.packages.find]
+where = ["."]
+include = ["taipy"]
+
+[tool.setuptools.package-data]
+"taipy" = ["version.json"]
+
+[tool.setuptools]
+zip-safe = false

+ 0 - 74
taipy/templates/setup.py

@@ -1,74 +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.
-
-"""The setup script for taipy-templates package"""
-
-import json
-import os
-from pathlib import Path
-
-from setuptools import find_namespace_packages, find_packages, setup
-
-package_desc = Path("package_desc.md").read_text("UTF-8")
-
-version_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "version.json")
-with open(version_path) as version_file:
-    version = json.load(version_file)
-    version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
-    if vext := version.get("ext"):
-        version_string = f"{version_string}.{vext}"
-
-test_requirements = ["pytest>=3.8"]
-
-setup(
-    author="Avaiga",
-    author_email="dev@taipy.io",
-    python_requires=">=3.8",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "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",
-        "Programming Language :: Python :: 3.12",
-        "Topic :: Software Development",
-        "Topic :: Scientific/Engineering",
-        "Operating System :: Microsoft :: Windows",
-        "Operating System :: POSIX",
-        "Operating System :: Unix",
-        "Operating System :: MacOS",
-    ],
-    description="An open-source package holding Taipy application templates.",
-    license="Apache License 2.0",
-    long_description=package_desc,
-    long_description_content_type="text/markdown",
-    keywords="taipy-templates",
-    name="taipy-templates",
-    packages=find_namespace_packages(where=".") + find_packages(include=["taipy"]),
-    include_package_data=True,
-    data_files=[('version', ['version.json'])],
-    test_suite="tests",
-    version=version_string,
-    zip_safe=False,
-    project_urls={
-        "Homepage": "https://www.taipy.io",
-        "Documentation": "https://docs.taipy.io",
-        "Source": "https://github.com/Avaiga/taipy",
-        "Download": "https://pypi.org/project/taipy/#files",
-        "Tracker": "https://github.com/Avaiga/taipy/issues",
-        "Security": "https://github.com/Avaiga/taipy?tab=security-ov-file#readme",
-        f"Release notes": "https://docs.taipy.io/en/release-{version_string}/relnotes/",
-    },
-)

+ 2 - 1
tests/gui/config/test_cli.py

@@ -82,11 +82,13 @@ def test_gui_service_arguments_hierarchy():
     assert service_config["margin"] is None
     assert service_config["ngrok_token"] == ""
     assert service_config["notification_duration"] == 3000
+    assert service_config["port"] == 5000
     assert service_config["propagate"]
     assert service_config["run_browser"]
     assert not service_config["run_in_thread"]
     assert not service_config["run_server"]
     assert not service_config["single_client"]
+    assert service_config["state_retention_period"] == 0
     assert not service_config["system_notification"]
     assert service_config["theme"] is None
     assert service_config["time_zone"] is None
@@ -96,7 +98,6 @@ def test_gui_service_arguments_hierarchy():
     assert not service_config["use_reloader"]
     assert service_config["watermark"] == "Taipy inside"
     assert service_config["webapp_path"] is None
-    assert service_config["port"] == 5000
     gui.stop()
 
     # Override default configuration by explicit defined arguments in Gui.run()

+ 5 - 5
tools/gui/generate_pyi.py

@@ -13,7 +13,7 @@ import json
 import os
 import re
 import sys
-from typing import List
+from typing import Any, Dict, List
 
 from markdownify import markdownify
 
@@ -79,7 +79,7 @@ with open(builder_pyi_file, "a") as file:
     file.write("from ._element import _Block, _Control, _Element\n")
 
 
-def resolve_inherit(name: str, properties, inherits, viselements) -> List[dict[str, any]]:
+def resolve_inherit(name: str, properties, inherits, viselements) -> List[Dict[str, Any]]:
     if not inherits:
         return properties
     for inherit_name in inherits:
@@ -137,10 +137,10 @@ def format_as_parameter(property):
     return f"{property['name']}{type}{default_value}"
 
 
-def build_doc(name: str, desc: dict[str, any]):
+def build_doc(name: str, desc: Dict[str, Any]):
     if "doc" not in desc:
         return ""
-    doc = desc["doc"]
+    doc = str(desc["doc"])
     if desc["name"] == "class_name":
         doc = doc.replace("<element_type>", name)
     # This won't work for Scenartio Management and Block elements
@@ -166,7 +166,7 @@ def generate_elements(category: str, base_class: str):
         name = element[0]
         desc = element[1]
         properties_doc = ""
-        property_list: List[dict[str, any]] = []
+        property_list: List[Dict[str, Any]] = []
         property_names: List[str] = []
         properties = resolve_inherit(name, desc["properties"], desc.get("inherits", None), viselements)
         # Remove hidden properties and indexed properties (TODO?)

+ 97 - 0
tools/release/setup_project.py

@@ -0,0 +1,97 @@
+# 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.
+
+import json
+import os
+import platform
+import re
+import subprocess
+import sys
+from pathlib import Path
+
+import toml  # type: ignore
+
+
+def get_requirements(pkg: str, env: str = "dev") -> list:
+    # get requirements from the different setups in tools/packages (removing taipy packages)
+    reqs = set()
+    pkg_name = pkg if pkg == "taipy" else f"taipy-{pkg}"
+    root_folder = Path(__file__).parent
+    package_path = os.path.join(root_folder.parent, "packages", pkg_name)
+    requirements_file = os.path.join(package_path, "setup.requirements.txt")
+    if os.path.exists(requirements_file):
+        reqs.update(Path(requirements_file).read_text("UTF-8").splitlines())
+    if env == "dev":
+        return [r for r in reqs if r and not r.startswith("taipy")]
+    return list(reqs)
+
+
+def update_pyproject(version_path: str, pyproject_path: str, env: str = "dev"):
+    with open(version_path) as version_file:
+        version = json.load(version_file)
+        version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'
+        if vext := version.get("ext"):
+            version_string = f"{version_string}.{vext}"
+
+    pyproject_data = toml.load(pyproject_path)
+    pyproject_data["project"]["version"] = version_string
+    pyproject_data["project"]["urls"]["Release notes"] = f"https://docs.taipy.io/en/release-{version_string}/relnotes/"
+    pyproject_data["project"]["dependencies"] = get_requirements(get_pkg_name(pyproject_path), env)
+
+    with open(pyproject_path, "w", encoding="utf-8") as pyproject_file:
+        toml.dump(pyproject_data, pyproject_file)
+
+
+def _build_webapp(webapp_path: str):
+    already_exists = Path(webapp_path).exists()
+    if not already_exists:
+        os.system("cd ../../frontend/taipy-gui/dom && npm ci")
+        os.system("cd ../../frontend/taipy-gui && npm ci --omit=optional && npm run build")
+
+
+def get_pkg_name(path: str) -> str:
+    # The regex pattern
+    pattern = r"([^/\\]+)[/\\]pyproject\.toml$"
+
+    # Search for the pattern
+    match = re.search(pattern, os.path.abspath(path))
+    if not match:
+        raise ValueError(f"Could not find package name in path: {path}")
+    return match.group(1)
+
+
+if __name__ == "__main__":
+    _pyproject_path = os.path.join(sys.argv[1], "pyproject.toml")
+    try:
+        env = sys.argv[2]
+    except IndexError:
+        env = "dev"
+
+    pkg = get_pkg_name(_pyproject_path)
+    if pkg == "taipy":
+        _version_path = os.path.join(sys.argv[1], "taipy", "version.json")
+        _webapp_path = os.path.join(sys.argv[1], "taipy", "gui", "webapp", "index.html")
+    else:
+        _version_path = os.path.join(sys.argv[1], "version.json")
+        _webapp_path = os.path.join(sys.argv[1], "webapp", "index.html")
+
+    update_pyproject(_version_path, _pyproject_path, env)
+
+    if pkg == "gui":
+        _build_webapp(_webapp_path)
+
+    if pkg == "taipy":
+        subprocess.run(
+            ["python", "bundle_build.py"],
+            cwd=os.path.join("tools", "frontend"),
+            check=True,
+            shell=platform.system() == "Windows",
+        )