浏览代码

Fix Builder API Default Property (#994) (#1034)

Dinh Long Nguyen 1 年之前
父节点
当前提交
8160791a74

+ 0 - 1
doc/gui/extension/MANIFEST.in

@@ -1,3 +1,2 @@
 # Include all files relevant to the extension library
 include example_library/front-end/dist/*
-

+ 11 - 0
doc/gui/extension/example_library/__init__.py

@@ -1 +1,12 @@
+# 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 .example_library import ExampleLibrary

+ 0 - 1
frontend/taipy-gui/src/utils/downloads.ts

@@ -34,4 +34,3 @@ export const runXHR = (downloadLink: HTMLAnchorElement | undefined, url: string,
     request.send();
     return request;
 };
-

+ 0 - 1
frontend/taipy/src/utils.ts

@@ -215,4 +215,3 @@ export const MenuProps = {
 export const selectSx = { m: 1, width: 300 };
 
 export const DeleteIconSx = { height: 50, width: 50, p: 0 };
-

+ 2 - 1
taipy/gui/_page.py

@@ -39,7 +39,8 @@ class _Page(object):
             if not silent and w:
                 s = "\033[1;31m\n"
                 s += (
-                    message := f"--- {len(w)} warning(s) were found for page '{'/' if self._route == gui._get_root_page_name() else self._route}' {self._renderer._get_content_detail(gui)} ---\n"  # noqa: E501
+                    message
+                    := f"--- {len(w)} warning(s) were found for page '{'/' if self._route == gui._get_root_page_name() else self._route}' {self._renderer._get_content_detail(gui)} ---\n"  # noqa: E501
                 )
                 for i, wm in enumerate(w):
                     s += f" - Warning {i + 1}: {wm.message}\n"

+ 1 - 3
taipy/gui/_renderers/utils.py

@@ -139,6 +139,4 @@ class FileWatchdogHandler(FileSystemEventHandler):
         self._last_modified = datetime.datetime.now()
         if Path(event.src_path).resolve() == Path(self._file_path).resolve():
             self._renderer.set_content(self._file_path)
-            _TaipyLogger._get_logger().info(
-                f"File '{self._file_path}' has been modified."
-            )
+            _TaipyLogger._get_logger().info(f"File '{self._file_path}' has been modified.")

+ 3 - 1
taipy/gui/_warnings.py

@@ -35,7 +35,9 @@ def _warn(message: str, e: t.Optional[BaseException] = None):
         (
             f"{message}:\n{''.join(traceback.format_exception(type(e), e, e.__traceback__))}"
             if e and TaipyGuiWarning._tp_debug_mode
-            else f"{message}:\n{e}" if e else message
+            else f"{message}:\n{e}"
+            if e
+            else message
         ),
         TaipyGuiWarning,
         stacklevel=2,

+ 7 - 5
taipy/gui/builder/_api_generator.py

@@ -19,6 +19,7 @@ import typing as t
 from taipy.logger._taipy_logger import _TaipyLogger
 
 from ..utils.singleton import _Singleton
+from ..utils.viselements import VisElements, resolve_inherits
 from ._element import _Block, _Control
 
 if t.TYPE_CHECKING:
@@ -45,18 +46,19 @@ class _ElementApiGenerator(object, metaclass=_Singleton):
             raise RuntimeError(f"{error_message}: taipy-gui module not found.")
         module_name = current_frame.f_back.f_globals["__name__"]
         self.__module = module = sys.modules[module_name]
-        with open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "viselements.json"))) as viselements:
-            data = json.load(viselements)
-            if "blocks" not in data or "controls" not in data:
+        with open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "viselements.json"))) as f:
+            viselements_json = json.load(f)
+            if "blocks" not in viselements_json or "controls" not in viselements_json:
                 raise RuntimeError(f"{error_message}: Invalid viselements.json file.")
-            for blockElement in data["blocks"]:
+            viselements = resolve_inherits(t.cast(VisElements, viselements_json))
+            for blockElement in viselements["blocks"]:
                 default_property = _ElementApiGenerator.find_default_property(blockElement[1]["properties"])
                 setattr(
                     module,
                     blockElement[0],
                     _ElementApiGenerator.create_block_api(blockElement[0], blockElement[0], default_property),
                 )
-            for controlElement in data["controls"]:
+            for controlElement in viselements["controls"]:
                 default_property = _ElementApiGenerator.find_default_property(controlElement[1]["properties"])
                 setattr(
                     module,

+ 1 - 1
taipy/gui/custom/__init__.py

@@ -1,4 +1,4 @@
-# Copyright 2023 Avaiga Private Limited
+# 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

+ 1 - 1
taipy/gui/custom/_page.py

@@ -1,4 +1,4 @@
-# Copyright 2023 Avaiga Private Limited
+# 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

+ 1 - 1
taipy/gui/data/utils.py

@@ -145,7 +145,7 @@ def _df_relayout(
         if y1 is not None:
             df_filter_conditions.append(df[y_column] < y1)
     if df_filter_conditions:
-            df = df.loc[np.bitwise_and.reduce(df_filter_conditions)]
+        df = df.loc[np.bitwise_and.reduce(df_filter_conditions)]
     if not has_x_col:
         df.drop(x_column, axis=1, inplace=True)
     return df, is_copied

+ 6 - 4
taipy/gui/types.py

@@ -144,7 +144,8 @@ class PropertyType(Enum):
 
 
 @t.overload  # noqa: F811
-def _get_taipy_type(a_type: None) -> None: ...
+def _get_taipy_type(a_type: None) -> None:
+    ...
 
 
 @t.overload
@@ -159,12 +160,13 @@ def _get_taipy_type(a_type: PropertyType) -> t.Type[_TaipyBase]:  # noqa: F811
 
 @t.overload
 def _get_taipy_type(  # noqa: F811
-    a_type: t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]]
-) -> t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]]: ...
+    a_type: t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]],
+) -> t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]]:
+    ...
 
 
 def _get_taipy_type(  # noqa: F811
-    a_type: t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]]
+    a_type: t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]],
 ) -> t.Optional[t.Union[t.Type[_TaipyBase], t.Type[Decimator], PropertyType]]:
     if a_type is None:
         return None

+ 3 - 1
taipy/gui/utils/boolean.py

@@ -16,7 +16,9 @@ def _is_boolean_true(s: t.Union[bool, str]) -> bool:
     return (
         s
         if isinstance(s, bool)
-        else s.lower() in ["true", "1", "t", "y", "yes", "yeah", "sure"] if isinstance(s, str) else False
+        else s.lower() in ["true", "1", "t", "y", "yes", "yeah", "sure"]
+        if isinstance(s, str)
+        else False
     )
 
 

+ 3 - 1
taipy/gui/utils/chart_config_builder.py

@@ -253,7 +253,9 @@ def _build_chart_config(gui: "Gui", attributes: t.Dict[str, t.Any], col_types: t
                 (
                     tr[_Chart_iprops.line.value]
                     if isinstance(tr[_Chart_iprops.line.value], (dict, _MapDict))
-                    else {"dash": tr[_Chart_iprops.line.value]} if tr[_Chart_iprops.line.value] else None
+                    else {"dash": tr[_Chart_iprops.line.value]}
+                    if tr[_Chart_iprops.line.value]
+                    else None
                 )
                 for tr in traces
             ],

+ 59 - 0
taipy/gui/utils/viselements.py

@@ -0,0 +1,59 @@
+# 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 typing as t
+from copy import deepcopy
+
+
+class VisElementProperties(t.TypedDict, total=False):
+    name: str
+    type: str
+    doc: str
+    default_value: t.Any
+    default_property: t.Any
+
+
+class VisElementDetail(t.TypedDict, total=False):
+    inherits: t.List[str]
+    properties: t.List[VisElementProperties]
+
+
+VisElement = t.Tuple[str, VisElementDetail]
+
+
+class VisElements(t.TypedDict):
+    blocks: t.List[VisElement]
+    controls: t.List[VisElement]
+    undocumented: t.List[VisElement]
+
+
+def _resolve_inherit_property(element: VisElement, viselements: VisElements) -> t.List[VisElementProperties]:
+    element_detail = element[1]
+    properties = deepcopy(element_detail["properties"])
+    if "inherits" not in element_detail:
+        return properties
+    for inherit in element_detail["inherits"]:
+        inherit_element = None
+        for element_type in "blocks", "controls", "undocumented":
+            inherit_element = next((e for e in viselements[element_type] if e[0] == inherit), None)  # type: ignore[literal-required]
+            if inherit_element is not None:
+                break
+        if inherit_element is None:
+            raise RuntimeError(f"Error resolving inherit element with name {inherit} in viselements.json")
+        properties = properties + _resolve_inherit_property(inherit_element, viselements)
+    return properties
+
+
+def resolve_inherits(viselements: VisElements) -> VisElements:
+    for element_type in "blocks", "controls":
+        for element in viselements[element_type]:  # type: ignore[literal-required]
+            element[1]["properties"] = _resolve_inherit_property(element, viselements)
+    return viselements

+ 4 - 5
tests/gui/control/test_toggle.py

@@ -65,18 +65,17 @@ def test_toggle_html_2(gui: Gui, test_client, helpers):
     ]
     helpers.test_control_html(gui, html_string, expected_list)
 
+
 def test_toggle_switch_md(gui: Gui, test_client, helpers):
     gui._bind_var_val("x", True)
     md_string = "<|{x}|toggle|label=Label|>"
     expected_list = [
         "<Toggle",
-        'isSwitch={true}',
-        'defaultValue={true}',
+        "isSwitch={true}",
+        "defaultValue={true}",
         'libClassName="taipy-toggle"',
         'updateVarName="_TpB_tpec_TpExPr_x_TPMDL_0"',
-        'value={_TpB_tpec_TpExPr_x_TPMDL_0}',
+        "value={_TpB_tpec_TpExPr_x_TPMDL_0}",
         'label="Label"',
     ]
     helpers.test_control_md(gui, md_string, expected_list)
-
-

+ 1 - 1
tools/gui/builder/block.txt

@@ -1,7 +1,7 @@
 
 class {{name}}(_Block):
     _ELEMENT_NAME: str
-    def __init__(self, {{properties}}) -> None: 
+    def __init__(self, {{properties}}) -> None:
         """
         Arguments:
             {{doc_arguments}}

+ 7 - 3
tools/gui/generate_pyi.py

@@ -61,7 +61,7 @@ with open("./tools/gui/builder/control.txt", "r") as file:
 os.system(f"pipenv run stubgen {builder_py_file} --no-import --parse-only --export-less -o ./")
 
 with open(builder_pyi_file, "a") as file:
-    file.write("from ._element import _Element, _Block\n")
+    file.write("from ._element import _Element, _Block, _Control\n")
 
 
 def get_properties(element, viselements) -> t.List[t.Dict[str, t.Any]]:
@@ -89,10 +89,14 @@ def build_doc(element: t.Dict[str, t.Any]):
 
 for control_element in viselements["controls"]:
     name = control_element[0]
-    property_list = []
-    property_names = []
+    property_list: t.List[t.Dict[str, t.Any]] = []
+    property_names: t.List[str] = []
     for property in get_properties(control_element[1], viselements):
         if property["name"] not in property_names and "[" not in property["name"]:
+            if "default_property" in property and property["default_property"] is True:
+                property_list.insert(0, property)
+                property_names.insert(0, property["name"])
+                continue
             property_list.append(property)
             property_names.append(property["name"])
     properties = ", ".join([f"{p} = ..." for p in property_names])

+ 11 - 0
tools/modify_readme.py

@@ -1,3 +1,14 @@
+# 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 re
 import sys
 

+ 102 - 94
tools/packages/check-dependencies.py

@@ -1,10 +1,21 @@
-'''
+# 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.
+
+"""
 This script is a helper on the dependencies management of the project.
 It can be used:
 - To check that the same version of a package is set across files.
 - To generate a Pipfile and requirements files with the latest version installables.
 - To display a summary of the dependencies to update.
-'''
+"""
 import glob
 import itertools
 import sys
@@ -22,6 +33,7 @@ class Release:
     """
     Information about a release of a package.
     """
+
     version: str
     upload_date: datetime.date
 
@@ -31,6 +43,7 @@ class Package:
     """
     Information about a package.
     """
+
     # Package name
     name: str
     # Min version of the package set as requirements.
@@ -69,10 +82,7 @@ class Package:
         """
         import requests  # pylint: disable=import-outside-toplevel
 
-        releases = requests.get(
-            f"https://pypi.org/pypi/{self.name}/json",
-            timeout=5
-        ).json().get('releases', {})
+        releases = requests.get(f"https://pypi.org/pypi/{self.name}/json", timeout=5).json().get("releases", {})
 
         for version, info in releases.items():
             # Ignore old releases without upload time.
@@ -81,7 +91,7 @@ class Package:
             # Ignore pre and post releases.
             if any(str.isalpha(c) for c in version):
                 continue
-            date = datetime.strptime(info[0]['upload_time'], "%Y-%m-%dT%H:%M:%S").date()
+            date = datetime.strptime(info[0]["upload_time"], "%Y-%m-%dT%H:%M:%S").date()
             release = Release(version, date)
             self.releases.append(release)
             if self.min_version == version:
@@ -106,11 +116,11 @@ class Package:
 
         if with_version:
             if self.installation_markers:
-                return f'{name}>={self.min_version},<={self.max_version};{self.installation_markers}'
-            return f'{name}>={self.min_version},<={self.max_version}'
+                return f"{name}>={self.min_version},<={self.max_version};{self.installation_markers}"
+            return f"{name}>={self.min_version},<={self.max_version}"
 
         if self.installation_markers:
-            return f'{name};{self.installation_markers}'
+            return f"{name};{self.installation_markers}"
         return name
 
     def as_pipfile_line(self) -> str:
@@ -124,10 +134,10 @@ class Package:
             line += f', markers="{self.installation_markers}"'
 
         if self.extras_dependencies:
-            dep = ','.join(f'"{p}"' for p in self.extras_dependencies)
-            line += f', extras=[{dep}]'
+            dep = ",".join(f'"{p}"' for p in self.extras_dependencies)
+            line += f", extras=[{dep}]"
 
-        line += '}'
+        line += "}"
         return line
 
     @classmethod
@@ -135,9 +145,9 @@ class Package:
         """
         Check if a package definition is correctly formatted.
         """
-        if '>=' not in package or '<' not in package:
+        if ">=" not in package or "<" not in package:
             # Only Taipy dependencies can be without version.
-            if 'taipy' not in package:
+            if "taipy" not in package:
                 raise Exception(f"Invalid package: {package}")
 
     @classmethod
@@ -149,18 +159,18 @@ class Package:
         try:
             # Lower the name to avoid case issues.
             name = extract_name(package).lower()
-            is_taipy = 'taipy' in name
+            is_taipy = "taipy" in name
             return cls(
                 name,
-                extract_min_version(package) if not is_taipy else '',
-                extract_max_version(package) if not is_taipy else '',
-                extract_installation_markers(package) if not is_taipy else '',
+                extract_min_version(package) if not is_taipy else "",
+                extract_max_version(package) if not is_taipy else "",
+                extract_installation_markers(package) if not is_taipy else "",
                 is_taipy,
                 extract_extras_dependencies(package),
-                [filename]
+                [filename],
             )
         except Exception as e:
-            print(f"Error while parsing package {package}: {e}") # noqa: T201
+            print(f"Error while parsing package {package}: {e}")  # noqa: T201
             raise
 
 
@@ -169,9 +179,9 @@ def extract_installation_markers(package: str) -> str:
     Extract the installation markers of a package from a requirements line.
     ex: "pandas>=1.0.0,<2.0.0;python_version<'3.9'" -> "python_version<'3.9'"
     """
-    if ';' not in package:
-        return ''
-    return package.split(';')[1]
+    if ";" not in package:
+        return ""
+    return package.split(";")[1]
 
 
 def extract_min_version(package: str) -> str:
@@ -180,14 +190,14 @@ def extract_min_version(package: str) -> str:
     ex: "pandas>=1.0.0,<2.0.0;python_version<'3.9'" -> "1.0.0"
     """
     # The max version is the defined version if it is a fixed version.
-    if '==' in package:
-        version = package.split('==')[1]
-        if ';' in version:
+    if "==" in package:
+        version = package.split("==")[1]
+        if ";" in version:
             # Remove installation markers.
-            version = version.split(';')[0]
+            version = version.split(";")[0]
         return version
 
-    return package.split('>=')[1].split(',')[0]
+    return package.split(">=")[1].split(",")[0]
 
 
 def extract_max_version(package: str) -> str:
@@ -200,23 +210,23 @@ def extract_max_version(package: str) -> str:
         - pandas>=1.0.0,<2.0.0;python_version<'3.9' -> 2.0.0
     """
     # The max version is the defined version if it is a fixed version.
-    if '==' in package:
-        version = package.split('==')[1]
-        if ';' in version:
+    if "==" in package:
+        version = package.split("==")[1]
+        if ";" in version:
             # Remove installation markers.
-            version = version.split(';')[0]
+            version = version.split(";")[0]
         return version
 
     version = None
 
-    if ',<=' in package:
-        version = package.split(',<=')[1]
+    if ",<=" in package:
+        version = package.split(",<=")[1]
     else:
-        version = package.split(',<')[1]
+        version = package.split(",<")[1]
 
-    if ';' in version:
+    if ";" in version:
         # Remove installation markers.
-        version = version.split(';')[0]
+        version = version.split(";")[0]
 
     return version
 
@@ -230,15 +240,15 @@ def extract_name(package: str) -> str:
         - pandas==1.0.0;python_version<'3.9' -> pandas
         - pandas>=1.0.0,<2.0.0;python_version<'3.9' -> pandas
     """
-    if '==' in package:
-        return package.split('==')[0]
+    if "==" in package:
+        return package.split("==")[0]
 
-    name = package.split('>=')[0]
+    name = package.split(">=")[0]
 
     # Remove optional dependencies.
     # Ex: "pandas[sql]" -> "pandas"
-    if '[' in name:
-        name = name.split('[')[0]
+    if "[" in name:
+        name = name.split("[")[0]
     return name
 
 
@@ -248,10 +258,10 @@ def extract_extras_dependencies(package: str) -> List[str]:
     Ex:
         - pymongo[srv]>=4.2.0,<=4.6.1 -> ["srv"]
     """
-    if '[' not in package:
+    if "[" not in package:
         return []
 
-    return package.split('[')[1].split(']')[0].split(',')
+    return package.split("[")[1].split("]")[0].split(",")
 
 
 def load_dependencies(requirements_filenames: List[str], enforce_format: bool) -> Dict[str, Package]:
@@ -279,8 +289,10 @@ def load_dependencies(requirements_filenames: List[str], enforce_format: bool) -
             # In that case, do not load the releases again but ensure versions are the same.
             if package.name in dependencies:
                 existing_package = dependencies[package.name]
-                if not existing_package.min_version == package.min_version or \
-                    not existing_package.max_version == package.max_version:
+                if (
+                    not existing_package.min_version == package.min_version
+                    or not existing_package.max_version == package.max_version
+                ):
                     raise Exception(
                         f"Inconsistent version of '{package.name}' between '{filename}' and {','.join(package.files)}."
                     )
@@ -308,27 +320,29 @@ def display_dependencies_versions(dependencies: Dict[str, Package]):
         # Load the latest releases of the package.
         package.load_releases()
 
-        to_print.append((
-            package_name,
-            f'{package.min_version} ({package.min_release.upload_date if package.min_release else "N.A."})',
-            f'{package.max_version} ({package.max_release.upload_date if package.max_release else "N.C."})',
-            f'{package.releases[0].version} ({package.releases[0].upload_date})',
-            len(list(itertools.takewhile(lambda x: x.version != package.max_version, package.releases))),  # noqa: B023
-        ))
+        to_print.append(
+            (
+                package_name,
+                f'{package.min_version} ({package.min_release.upload_date if package.min_release else "N.A."})',
+                f'{package.max_version} ({package.max_release.upload_date if package.max_release else "N.C."})',
+                f"{package.releases[0].version} ({package.releases[0].upload_date})",
+                len(list(itertools.takewhile(lambda x: x.version != package.max_version, package.releases))),  # noqa: B023
+            )
+        )
 
     to_print.sort(key=lambda x: x[0])
-    h = ['name', 'version-min', 'version-max', 'current-version', 'nb-releases-behind']
-    print(tabulate.tabulate(to_print, headers=h, tablefmt='pretty')) # noqa: T201
+    h = ["name", "version-min", "version-max", "current-version", "nb-releases-behind"]
+    print(tabulate.tabulate(to_print, headers=h, tablefmt="pretty"))  # noqa: T201
 
 
 def update_dependencies(
-        # Dependencies installed in the environment.
-        dependencies_installed: Dict[str, Package],
-        # Dependencies set in requirements files.
-        dependencies_set: Dict[str, Package],
-        # Requirements files to update.
-        requirements_filenames: List[str]
-    ):
+    # Dependencies installed in the environment.
+    dependencies_installed: Dict[str, Package],
+    # Dependencies set in requirements files.
+    dependencies_set: Dict[str, Package],
+    # Requirements files to update.
+    requirements_filenames: List[str],
+):
     """
     Display and updates dependencies.
     """
@@ -342,32 +356,26 @@ def update_dependencies(
         di = dependencies_installed.get(name)
         # Some package as 'gitignore-parser' becomes 'gitignore_parser' during the installation.
         if not di:
-            di = dependencies_installed.get(name.replace('-', '_'))
+            di = dependencies_installed.get(name.replace("-", "_"))
 
         if di:
             if di.max_version != ds.max_version:
-                to_print.append((
-                    name,
-                    di.max_version,
-                    ','.join(f.split('/')[0] for f in ds.files)
-                ))
+                to_print.append((name, di.max_version, ",".join(f.split("/")[0] for f in ds.files)))
                 # Save the new dependency version.
                 ds.max_version = di.max_version
 
     # Print the dependencies to update.
     to_print.sort(key=lambda x: x[0])
-    print(tabulate.tabulate(to_print, headers=['name', 'version', 'files'], tablefmt='pretty')) # noqa: T201
+    print(tabulate.tabulate(to_print, headers=["name", "version", "files"], tablefmt="pretty"))  # noqa: T201
 
     # Update requirements files.
     for fd in requirements_filenames:
-        requirements = '\n'.join(
-            d.as_requirements_line()
-            for d in sorted(dependencies_set.values(), key=lambda d: d.name)
-            if fd in d.files
+        requirements = "\n".join(
+            d.as_requirements_line() for d in sorted(dependencies_set.values(), key=lambda d: d.name) if fd in d.files
         )
         # Add a new line at the end of the file.
-        requirements += '\n'
-        Path(fd).write_text(requirements, 'UTF-8')
+        requirements += "\n"
+        Path(fd).write_text(requirements, "UTF-8")
 
 
 def generate_raw_requirements_txt(dependencies: Dict[str, Package]):
@@ -376,7 +384,7 @@ def generate_raw_requirements_txt(dependencies: Dict[str, Package]):
     """
     for package in dependencies.values():
         if not package.is_taipy:
-            print(package.as_requirements_line(with_version=False)) # noqa: T201
+            print(package.as_requirements_line(with_version=False))  # noqa: T201
 
 
 def update_pipfile(pipfile: str, dependencies_version: Dict[str, Package]):
@@ -389,13 +397,13 @@ def update_pipfile(pipfile: str, dependencies_version: Dict[str, Package]):
     dependencies_str = ""
     pipfile_obj = toml.load(pipfile)
 
-    packages = pipfile_obj.pop('packages')
+    packages = pipfile_obj.pop("packages")
     for name, dep in packages.items():
         # Find the package in use.
         rp = dependencies_version.get(name)
         # Some package as 'gitignore-parser' becomes 'gitignore_parser' during the installation.
         if not rp:
-            rp = dependencies_version.get(name.replace('-', '_'))
+            rp = dependencies_version.get(name.replace("-", "_"))
             if rp:
                 # Change for the real name of the package.
                 rp.name = name
@@ -404,48 +412,48 @@ def update_pipfile(pipfile: str, dependencies_version: Dict[str, Package]):
             # Package not found. Can be due to python version.
             # Ex: backports.zoneinfo
             if isinstance(dep, dict):
-                new_dep = ''
+                new_dep = ""
                 # Format as a Pipfile line.
                 new_dep = f'version="{dep["version"]}"'
-                if dep.get('markers'):
+                if dep.get("markers"):
                     new_dep += f', markers="{dep["markers"]}"'
-                if dep.get('extras'):
+                if dep.get("extras"):
                     new_dep += f', extras={dep["extras"]}'
                 dep = f"{{{new_dep}}}"
             dependencies_str += f'"{name}" = {dep}\n'
         else:
             if isinstance(dep, dict):
                 # Requirements does not have installation markers and extras.
-                rp.installation_markers = dep.get('markers', '')
-                rp.extras_dependencies = [dep.get('extras')[0]] if dep.get('extras') else []
-            dependencies_str += f'{rp.as_pipfile_line()}\n'
+                rp.installation_markers = dep.get("markers", "")
+                rp.extras_dependencies = [dep.get("extras")[0]] if dep.get("extras") else []
+            dependencies_str += f"{rp.as_pipfile_line()}\n"
 
     toml_str = toml.dumps(pipfile_obj)
-    Path(pipfile).write_text(f'{toml_str}\n\n[packages]\n{dependencies_str}', 'UTF-8')
+    Path(pipfile).write_text(f"{toml_str}\n\n[packages]\n{dependencies_str}", "UTF-8")
 
 
-if __name__ == '__main__':
-    if sys.argv[1] == 'ensure-same-version':
+if __name__ == "__main__":
+    if sys.argv[1] == "ensure-same-version":
         # Load dependencies from requirements files.
         # Verify that the same version is set for the same package across files.
-        _requirements_filenames = glob.glob('taipy*/*requirements.txt')
+        _requirements_filenames = glob.glob("taipy*/*requirements.txt")
         _dependencies = load_dependencies(_requirements_filenames, True)
         display_dependencies_versions(_dependencies)
-    if sys.argv[1] == 'dependencies-summary':
+    if sys.argv[1] == "dependencies-summary":
         # Load and compare dependencies from requirements files.
         # The first file is the reference to the other.
         # Display the differences including new version available on Pypi.
-        _requirements_filenames = glob.glob('taipy*/*requirements.txt')
+        _requirements_filenames = glob.glob("taipy*/*requirements.txt")
         _dependencies_installed = load_dependencies([sys.argv[2]], False)
         _dependencies_set = load_dependencies(_requirements_filenames, False)
         update_dependencies(_dependencies_installed, _dependencies_set, _requirements_filenames)
-    if sys.argv[1] == 'generate-raw-requirements':
+    if sys.argv[1] == "generate-raw-requirements":
         # Load dependencies from requirements files.
         # Print the dependencies as requirements lines without born.
-        _requirements_filenames = glob.glob('taipy*/*requirements.txt')
+        _requirements_filenames = glob.glob("taipy*/*requirements.txt")
         _dependencies = load_dependencies(_requirements_filenames, False)
         generate_raw_requirements_txt(_dependencies)
-    if sys.argv[1] == 'generate-pipfile':
+    if sys.argv[1] == "generate-pipfile":
         # Generate a new Pipfile from requirements files using dependencies versions
         # set in the requirement file.
         _pipfile_path = sys.argv[2]

+ 1 - 1
tools/packages/requirements.txt

@@ -1,3 +1,3 @@
 tabulate
 toml
-requests
+requests

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

@@ -1 +0,0 @@
-

+ 11 - 0
tools/release/check_releases.py

@@ -1,3 +1,14 @@
+# 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 os
 import sys
 

+ 11 - 0
tools/release/extract_from_setup.py

@@ -1,3 +1,14 @@
+# 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 sys
 
 

+ 11 - 0
tools/release/update_setup.py

@@ -1,3 +1,14 @@
+# 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 sys
 
 

+ 12 - 1
tools/validate_taipy_install.py

@@ -1,3 +1,14 @@
+# 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 logging
 import os
 import sys
@@ -38,7 +49,7 @@ def is_taipy_gui_install_valid() -> bool:
     if not os.path.exists(taipy_gui_webapp_path):
         return False
 
-    if not any(fname.endswith('.js') for fname in os.listdir(taipy_gui_webapp_path)):
+    if not any(fname.endswith(".js") for fname in os.listdir(taipy_gui_webapp_path)):
         logging.error("Missing js files inside taipy gui webapp folder")
         return False