" and "" respectively.
+
+ md_template = ""
+ with open(md_template_path) as template_file:
+ md_template = template_file.read()
+ if not md_template:
+ raise FileNotFoundError(f"FATAL - Could not read {md_template_path} markdown template")
+ toc = '\n'
+ for element_type in self.categories[category]:
+ toc += generate_element_doc(element_type, self.elements[element_type])
+ toc += "
\n"
+ with open(md_path, "w") as md_file:
+ md_file.write(md_template.replace("[TOC]", toc))
diff --git a/tools/_setup_generation/setup.py b/tools/_setup_generation/setup.py
index 8d1adaaac..61c994215 100644
--- a/tools/_setup_generation/setup.py
+++ b/tools/_setup_generation/setup.py
@@ -104,6 +104,7 @@ def setup(self, setup: Setup):
from .step_viselements import VisElementsStep
+from .step_corelements import CoreElementsStep
from .step_refman import RefManStep
from .step_rest_refman import RestRefManStep
from .step_gui_ext_refman import GuiExtRefManStep
@@ -115,6 +116,7 @@ def run_setup(root_dir: str, steps: List[SetupStep] = None):
if steps is None:
steps = [
VisElementsStep(),
+ CoreElementsStep(),
RefManStep(),
RestRefManStep(),
GuiExtRefManStep(),
diff --git a/tools/_setup_generation/step_corelements.py b/tools/_setup_generation/step_corelements.py
new file mode 100644
index 000000000..ebc857bb6
--- /dev/null
+++ b/tools/_setup_generation/step_corelements.py
@@ -0,0 +1,47 @@
+# ################################################################################
+# Taipy GUI Core Elements documentation.
+#
+# This includes the update of the Table of Contents of the controls
+# document pages.
+#
+# For each element, this script combines its property list and
+# documentation (located in [CORELEMENTS_SRC_PATH]), and generates full
+# Markdown files in [CORELEMENTS_DIR_PATH]. All these files ultimately get
+# integrated in the global dos set.
+#
+# The template documentation files [CORELEMENTS_SRC_PATH]/[controls|blocks].md_template
+# are also completed with generated table of contents.
+# ################################################################################
+from .setup import Setup
+from .elmnts_generator import ElementsGenerator
+import os
+
+class CoreElementsStep(ElementsGenerator):
+
+ def get_id(self) -> str:
+ return "corelements"
+
+ def get_description(self) -> str:
+ return "Extraction of the Core elements documentation"
+
+ def get_doc_dir(self) -> str:
+ return "corelements"
+
+ def enter(self, setup: Setup):
+ self.CORELEMENTS_DIR_PATH = setup.manuals_dir + "/gui/corelements"
+ self.template_path = self.CORELEMENTS_DIR_PATH + "/index.md_template"
+ if not os.access(self.template_path, os.R_OK):
+ raise FileNotFoundError(
+ f"FATAL - Could not read {self.template_path} markdown template"
+ )
+ self.load_elements(setup.root_dir + "/taipy/gui_core/viselements.json",
+ ["controls"])
+
+ def get_element_template_path(self, element_type: str) -> str:
+ return f"{self.CORELEMENTS_DIR_PATH}/{element_type}.md_template"
+
+ def get_element_md_path(self, element_type: str) -> str:
+ return f"{self.CORELEMENTS_DIR_PATH}/{element_type}.md"
+
+ def setup(self, setup: Setup) -> None:
+ self.generate_pages("controls", os.path.join(self.CORELEMENTS_DIR_PATH, "index.md"), self.template_path)
diff --git a/tools/_setup_generation/step_refman.py b/tools/_setup_generation/step_refman.py
index 4032a36a5..53691e740 100644
--- a/tools/_setup_generation/step_refman.py
+++ b/tools/_setup_generation/step_refman.py
@@ -21,6 +21,7 @@ class RefManStep(SetupStep):
"taipy.config",
"taipy.core",
"taipy.gui",
+ "taipy.gui_core",
"taipy.rest",
"taipy.auth",
"taipy.enterprise",
@@ -95,7 +96,7 @@ class RefManStep(SetupStep):
("taipy.config.common.scope.Scope", "taipy.core.config"),
("taipy.config.common.frequency.Frequency", "taipy.core.config"),
("taipy.config.unique_section.*", "taipy.config"),
- ("taipy.config.exceptions.exceptions.ConfigurationIssueError", "taipy.config.exceptions"),
+ #("taipy.config.exceptions.exceptions.ConfigurationIssueError", "taipy.config.exceptions"),
# Rest
("taipy.rest.rest.Rest", "taipy.rest"),
# Auth
@@ -145,6 +146,7 @@ def generate_refman_pages(self, setup: Setup) -> None:
REMOVE_LINE_SKIPS_RE = re.compile(r"\s*\n\s*", re.MULTILINE)
os.mkdir(self.REFERENCE_DIR_PATH)
+ loaded_modules = set()
# Entries:
# full_entry_name ->
@@ -157,6 +159,9 @@ def generate_refman_pages(self, setup: Setup) -> None:
module_doc = {}
def read_module(module):
+ if module in loaded_modules:
+ return
+ loaded_modules.add(module)
if not module.__name__.startswith(Setup.ROOT_PACKAGE):
return
for entry in dir(module):
diff --git a/tools/_setup_generation/step_viselements.py b/tools/_setup_generation/step_viselements.py
index 459dd35fa..e2458d0a0 100644
--- a/tools/_setup_generation/step_viselements.py
+++ b/tools/_setup_generation/step_viselements.py
@@ -12,274 +12,85 @@
# The skeleton documentation files [GUI_DOC_PATH]/[controls|blocks].md_template
# are also completed with generated table of contents.
# ################################################################################
-import json
-from typing import Dict, List, Optional
-from .setup import Setup, SetupStep
+from .setup import Setup
+from .elmnts_generator import ElementsGenerator
import os
import re
-class VisElementsStep(SetupStep):
- DEFAULT_PROPERTY = "default_property"
- PROPERTIES = "properties"
- NAME = "name"
- INHERITS = "inherits"
-
+class VisElementsStep(ElementsGenerator):
def get_id(self) -> str:
return "viselements"
def get_description(self) -> str:
return "Extraction of the visual elements documentation"
+ def get_doc_dir(self) -> str:
+ return "viselements"
+
def enter(self, setup: Setup):
- self.VISELEMENTS_SRC_PATH = setup.root_dir + "/gui/doc"
- self.GUI_DOC_PATH = setup.manuals_dir + "/gui/"
- self.VISELEMENTS_DIR_PATH = self.GUI_DOC_PATH + "/viselements"
- self.controls_md_template_path = self.GUI_DOC_PATH + "/controls.md_template"
- if not os.access(self.controls_md_template_path, os.R_OK):
+ self.GUI_DIR_PATH = setup.manuals_dir + "/gui"
+ self.VISELEMENTS_DIR_PATH = self.GUI_DIR_PATH + "/viselements"
+ self.controls_template_path = self.GUI_DIR_PATH + "/controls.md_template"
+ if not os.access(self.controls_template_path, os.R_OK):
raise FileNotFoundError(
- f"FATAL - Could not read {self.controls_md_template_path} markdown template"
+ f"FATAL - Could not read {self.controls_template_path} Markdown template"
)
- self.blocks_md_template_path = self.GUI_DOC_PATH + "/blocks.md_template"
- if not os.access(self.blocks_md_template_path, os.R_OK):
+ self.blocks_template_path = self.GUI_DIR_PATH + "/blocks.md_template"
+ if not os.access(self.blocks_template_path, os.R_OK):
raise FileNotFoundError(
- f"FATAL - Could not read {self.blocks_md_template_path} markdown template"
+ f"FATAL - Could not read {self.blocks_template_path} Markdown template"
)
self.charts_home_html_path = self.VISELEMENTS_DIR_PATH + "/charts/home.html_fragment"
if not os.access(self.charts_home_html_path, os.R_OK):
raise FileNotFoundError(
f"FATAL - Could not read {self.charts_home_html_path} html fragment"
)
- viselements_json_path = self.VISELEMENTS_SRC_PATH + "/viselements.json"
- with open(viselements_json_path) as viselements_json_file:
- self.viselements = json.load(viselements_json_file)
- # Test validity of visual elements doc and resolve inheritance
- self.controls = self.viselements["controls"]
- self.blocks = self.viselements["blocks"]
- undocumented = self.viselements["undocumented"]
- self.all_elements = {}
- for element in self.controls+self.blocks+undocumented:
- element_type = element[0]
- if element_type in self.all_elements:
- raise ValueError(
- f"FATAL - Duplicate element type '{element_type}' in {viselements_json_path}"
- )
- element_desc = element[1]
- if not __class__.PROPERTIES in element_desc and not __class__.INHERITS in element_desc:
- raise ValueError(
- f"FATAL - No properties in element type '{element_type}' in {viselements_json_path}"
- )
- self.all_elements[element_type] = element_desc
- # Find default property for all element types
- for element_type, element_desc in self.all_elements.items():
- default_property = None
- if properties := element_desc.get(__class__.PROPERTIES, None):
- for property in properties:
- if __class__.DEFAULT_PROPERTY in property:
- if property[__class__.DEFAULT_PROPERTY]:
- default_property = property[__class__.NAME]
- del property[__class__.DEFAULT_PROPERTY]
- element_desc[__class__.DEFAULT_PROPERTY] = default_property
- # Resolve inheritance
- def merge(element_desc, parent_element_desc, default_property) -> Optional[str]:
- element_properties = element_desc.get(__class__.PROPERTIES, [])
- element_property_names = [p[__class__.NAME] for p in element_properties]
- for property in parent_element_desc.get(__class__.PROPERTIES, []):
- property_name = property[__class__.NAME]
- if property_name in element_property_names:
- element_property = element_properties[element_property_names.index(property_name)]
- for n in ["type", "default_value", "doc"]:
- if not n in element_property and n in property:
- element_property[n] = property[n]
- else:
- element_property_names.append(property_name)
- element_properties.append(property)
- element_desc[__class__.PROPERTIES] = element_properties
- if not default_property and parent_element_desc.get(__class__.DEFAULT_PROPERTY, False):
- default_property = parent_element_desc[__class__.DEFAULT_PROPERTY]
- return default_property
+ self.load_elements(setup.root_dir + "/taipy/gui/viselements.json",
+ ["controls", "blocks"])
- for element_type, element_desc in self.all_elements.items():
- if parent_types := element_desc.get(__class__.INHERITS, None):
- del element_desc[__class__.INHERITS]
- default_property = element_desc[__class__.DEFAULT_PROPERTY]
- for parent_type in parent_types:
- parent_desc = self.all_elements[parent_type]
- default_property = merge(element_desc, parent_desc, default_property)
- element_desc[__class__.DEFAULT_PROPERTY] = default_property
- # Check that documented elements have a default property and a doc file,
- # and that their properties have the mandatory settings.
- for element in self.controls+self.blocks:
- element_type = element[0]
- element_desc = element[1]
- if not __class__.DEFAULT_PROPERTY in element_desc:
- raise ValueError(
- f"FATAL - No default property for element type '{element_type}' in {viselements_json_path}"
- )
- if not __class__.PROPERTIES in element_desc:
- raise ValueError(
- f"FATAL - No properties for element type '{element_type}' in {viselements_json_path}"
- )
- doc_path = self.VISELEMENTS_SRC_PATH + "/" + element_type + ".md"
- if not os.access(doc_path, os.R_OK):
- raise FileNotFoundError(
- f"FATAL - Could not find doc for element type '{element_type}' in {self.VISELEMENTS_SRC_PATH}"
- )
- # Check completeness
- for property in element_desc[__class__.PROPERTIES]:
- for n in ["type", "doc"]:
- if not n in property:
- raise ValueError(
- f"FATAL - No value for '{n}' in the '{property[__class__.NAME]}' properties of element type '{element_type}' in {viselements_json_path}"
- )
+
+ def get_element_template_path(self, element_type: str) -> str:
+ return f"{self.VISELEMENTS_DIR_PATH}/{element_type}.md_template"
+
+ def get_element_md_path(self, element_type: str) -> str:
+ return f"{self.VISELEMENTS_DIR_PATH}/{element_type}.md"
def setup(self, setup: Setup) -> None:
# Create VISELEMS_DIR_PATH directory if necessary
if not os.path.exists(self.VISELEMENTS_DIR_PATH):
os.mkdir(self.VISELEMENTS_DIR_PATH)
-
- FIRST_PARA_RE = re.compile(r"(^.*?)(:?\n\n)", re.MULTILINE | re.DOTALL)
- FIRST_HEADER1_RE = re.compile(r"(^.*?)(\n#\s+)", re.MULTILINE | re.DOTALL)
- # Find first level 2 or 3 header
- FIRST_HEADER2_RE = re.compile(r"(^.*?)(\n###?\s+)", re.MULTILINE | re.DOTALL)
-
- def generate_element_doc(element_type: str, element_desc: Dict):
- """
- Returns the entry for the Table of Contents that is inserted
- in the global Visual Elements doc page.
- """
- doc_path = self.VISELEMENTS_SRC_PATH + "/" + element_type + ".md"
- with open(doc_path, "r") as doc_file:
- element_documentation = doc_file.read()
- # Retrieve first paragraph from element documentation
- match = FIRST_PARA_RE.match(element_documentation)
+ self.generate_pages("controls", self.get_element_md_path("controls"), self.controls_template_path)
+ self.generate_pages("blocks", self.get_element_md_path("blocks"), self.blocks_template_path)
+
+ def element_page_hook(self, element_type:str, element_documentation: str, before: str, after: str) -> tuple[str, str]:
+ # Special case for charts: we want to insert the chart gallery that is stored in the
+ # file whose path is in self.charts_home_html_path
+ # This should be inserted before the first level 1 header
+ if element_type == "chart":
+ with open(self.charts_home_html_path, "r") as html_fragment_file:
+ chart_gallery = html_fragment_file.read()
+ # The chart_gallery begins with a comment where all sub-sections
+ # are listed.
+ SECTIONS_RE = re.compile(r"^(?:\s*)", re.MULTILINE | re.DOTALL)
+ match = SECTIONS_RE.match(chart_gallery)
if not match:
raise ValueError(
- f"Couldn't locate first paragraph in documentation for element '{element_type}'"
+ f"{self.charts_home_html_path} should begin with an HTML comment that lists the chart types"
)
- first_documentation_paragraph = match.group(1)
-
- # Build properties table
- properties_table = """
-## Properties\n\n
-
-
-
- Name |
- Type |
- Default |
- Description |
-
-
-
-"""
- STAR = "(★)"
- default_property_name = element_desc[__class__.DEFAULT_PROPERTY]
- for property in element_desc[__class__.PROPERTIES]:
- name = property[__class__.NAME]
- type = property["type"]
- default_value = property.get("default_value", None)
- doc = property.get("doc", None)
- if not default_value:
- default_value = "Required" if property.get("required", False) else ""
- full_name = f"]+>', '', name)}\">"
- if name == default_property_name:
- full_name += f"{name}
{STAR}"
- else:
- full_name += f"{name}"
- properties_table += (
- "\n"
- + f"{full_name} | \n"
- + f"{type} | \n"
- + f"{default_value} | \n"
- + f"{doc} | \n"
- + "
\n"
- )
- properties_table += " \n
\n\n"
- if default_property_name:
- properties_table += (
- f'{STAR}'
- + f''
- + f"{default_property_name}
"
- + " is the default property for this visual element.
\n"
- )
-
- # Insert title and properties in element documentation
- match = FIRST_HEADER2_RE.match(element_documentation)
+ chart_gallery = "\n" + chart_gallery[match.end() :]
+ SECTION_RE = re.compile(r"^([\w-]+):(.*)$")
+ chart_sections = ""
+ for line in match.group(1).splitlines():
+ match = SECTION_RE.match(line)
+ if match:
+ chart_sections += f"- [{match.group(2)}](charts/{match.group(1)}.md)\n"
+
+ match = ElementsGenerator.FIRST_HEADER1_RE.match(element_documentation)
if not match:
raise ValueError(
- f"Couldn't locate first header2 in documentation for element '{element_type}'"
+ f"Couldn't locate first header1 in documentation for element 'chart'"
)
- before_properties = match.group(1)
- after_properties = match.group(2) + element_documentation[match.end() :]
- output_path = os.path.join(self.VISELEMENTS_DIR_PATH, element_type + ".md")
-
- # Special case for charts: we want to insert the chart gallery that is stored in the
- # file whose path is in self.charts_home_html_path
- # This should be inserted before the first level 1 header
- if element_type == "chart":
- with open(self.charts_home_html_path, "r") as html_fragment_file:
- chart_gallery = html_fragment_file.read()
- # The chart_gallery begins with a comment where all sub-sections
- # are listed.
- SECTIONS_RE = re.compile(r"^(?:\s*)", re.MULTILINE | re.DOTALL)
- match = SECTIONS_RE.match(chart_gallery)
- if not match:
- raise ValueError(
- f"{self.charts_home_html_path} should begin with an HTML comment that lists the chart types"
- )
- chart_gallery = "\n" + chart_gallery[match.end() :]
- SECTION_RE = re.compile(r"^([\w-]+):(.*)$")
- chart_sections = ""
- for line in match.group(1).splitlines():
- match = SECTION_RE.match(line)
- if match:
- chart_sections += f"- [{match.group(2)}](charts/{match.group(1)}.md)\n"
-
- match = FIRST_HEADER1_RE.match(element_documentation)
- if not match:
- raise ValueError(
- f"Couldn't locate first header1 in documentation for element 'chart'"
- )
- before_properties = match.group(1) + chart_gallery + match.group(2) + before_properties[match.end() :]
- after_properties += chart_sections
-
- with open(output_path, "w") as output_file:
- output_file.write(
- "---\nhide:\n - navigation\n---\n\n"
- + f"# {element_type}\n\n"
- + before_properties
- + properties_table
- + after_properties
- )
- e = element_type # Shortcut
- return (
- f'\n'
- + f"{e}
\n"
- + f'\n'
- + f'\n'
- + f'\n'
- + f'\n'
- + f"{first_documentation_paragraph}
\n"
- + "\n"
- )
- # If you want a simple list, use
- # f"{e}
: {first_documentation_paragraph}\n"
- # The toc header and footer must then be "" and "" respectively.
-
- # Generate element doc pages
- def generate_doc_page(category: str, elements: List, md_template_path: str):
- md_template = ""
- with open(md_template_path) as template_file:
- md_template = template_file.read()
- if not md_template:
- raise FileNotFoundError(f"FATAL - Could not read {md_template_path} markdown template")
- toc = '\n'
- for element_type, element_desc in elements:
- toc += generate_element_doc(element_type, element_desc)
- toc += "
\n"
- with open(os.path.join(self.GUI_DOC_PATH, f"{category}.md"), "w") as file:
- file.write(md_template.replace("[TOC]", toc))
+ return (match.group(1) + chart_gallery + match.group(2) + before[match.end() :], after + chart_sections)
- generate_doc_page("controls", self.controls, self.controls_md_template_path)
- generate_doc_page("blocks", self.blocks, self.blocks_md_template_path)
+ return super().element_page_hook(element_type, element_documentation, before, after)
diff --git a/tools/fetch_source_files.py b/tools/fetch_source_files.py
index 35322a853..0e6f1e6f5 100644
--- a/tools/fetch_source_files.py
+++ b/tools/fetch_source_files.py
@@ -13,7 +13,7 @@
# Where all the code from all directories/repositories is copied
DEST_DIR_NAME = "taipy"
-REPOS = ["config", "core", "gui", "getting-started", "getting-started-core", "getting-started-gui", "rest"]
+REPOS = ["config", "core", "gui", "rest", "taipy", "getting-started", "getting-started-core", "getting-started-gui"]
PRIVATE_REPOS = ["auth", "enterprise"]
OPTIONAL_PACKAGES = {
@@ -26,7 +26,7 @@
mkdocs_yml_version = read_doc_version_from_mkdocs_yml_template_file(ROOT_DIR)
# Gather version information for each repository
-repo_defs = {repo: {"version": "local", "tag": None} for repo in REPOS + PRIVATE_REPOS}
+repo_defs = {repo if repo == "taipy" else f"taipy-{repo}": {"version": "local", "tag": None} for repo in REPOS + PRIVATE_REPOS}
CATCH_VERSION_RE = re.compile(r"(^\d+\.\d+?)(?:(\.\d+)(\..*)?)?|develop|local$")
for version in args.version:
repo = None
@@ -37,8 +37,8 @@
try:
colon = version.index(":")
repo = version[:colon]
- if repo.startswith("taipy-"):
- repo = repo[6:]
+ if not repo.startswith("taipy"):
+ repo = f"taipy-{repo}"
version = version[colon + 1:]
except ValueError as e:
pass
@@ -76,17 +76,17 @@
github_token = os.environ.get("GITHUB_TOKEN", "")
if github_token:
github_token += "@"
-github_root = f"https://{github_token}github.com/Avaiga/taipy-"
+github_root = f"https://{github_token}github.com/Avaiga/"
for repo in repo_defs.keys():
version = repo_defs[repo]["version"]
if version == "local":
- repo_path = os.path.join(TOP_DIR, "taipy-" + repo)
+ repo_path = os.path.join(TOP_DIR, repo)
repo_defs[repo]["path"] = repo_path
if not os.path.isdir(repo_path):
if repo in PRIVATE_REPOS:
repo_defs[repo]["skip"] = True
else:
- raise IOError(f"Repository 'taipy-{repo}' must be cloned in \"{TOP_DIR}\".")
+ raise IOError(f"Repository '{repo}' must be cloned in \"{TOP_DIR}\".")
elif version == "develop":
with GitContext(repo, PRIVATE_REPOS):
cmd = subprocess.run(f"{git_path} ls-remote -q -h {github_root}{repo}.git", shell=True, capture_output=True,
@@ -108,13 +108,13 @@
else:
raise SystemError(f"Couldn't query branches from {github_root}{repo}.")
if not f"release/{version}\n" in cmd.stdout:
- raise ValueError(f"No branch 'release/{version}' in repository 'taipy-{repo}'.")
+ raise ValueError(f"No branch 'release/{version}' in repository '{repo}'.")
tag = repo_defs[repo]["tag"]
if tag:
cmd = subprocess.run(f"{git_path} ls-remote -t --refs {github_root}{repo}.git", shell=True,
capture_output=True, text=True)
if not f"refs/tags/{tag}\n" in cmd.stdout:
- raise ValueError(f"No tag '{tag}' in repository 'taipy-{repo}'.")
+ raise ValueError(f"No tag '{tag}' in repository '{repo}'.")
if args.check:
print(f"Fetch should perform properly with the following settings:")
@@ -125,7 +125,7 @@
tag = repo_defs[repo]["tag"]
if tag:
version += f" tag:{tag}"
- print(f"- taipy-{repo} {version}")
+ print(f"- {repo} {version}")
exit(0)
DEST_DIR = os.path.join(ROOT_DIR, DEST_DIR_NAME)
@@ -176,8 +176,8 @@ def move_files(repo: str, src_path: str):
else:
pipfile_packages[package] = {version: [repo]}
# Copy relevant files for doc generation
- if repo.startswith("getting-started"):
- gs_dir = os.path.join(ROOT_DIR, "docs", "getting_started", repo)
+ if repo.startswith("taipy-getting-started"):
+ gs_dir = os.path.join(ROOT_DIR, "docs", "getting_started", repo[6:])
# safe_rmtree(os.path.join(gs_dir, "src"))
for step_dir in [step_dir for step_dir in os.listdir(gs_dir) if
step_dir.startswith("step_") and os.path.isdir(os.path.join(gs_dir, step_dir))]:
@@ -189,7 +189,7 @@ def move_files(repo: str, src_path: str):
shutil.copytree(os.path.join(src_path, "src"), os.path.join(gs_dir, "src"))
shutil.copy(os.path.join(src_path, "index.md"), os.path.join(gs_dir, "index.md"))
saved_dir = os.getcwd()
- os.chdir(os.path.join(ROOT_DIR, "docs", "getting_started", repo))
+ os.chdir(os.path.join(ROOT_DIR, "docs", "getting_started", repo[6:]))
subprocess.run(f"python {os.path.join(src_path, 'generate_notebook.py')}",
shell=True,
capture_output=True,
@@ -198,36 +198,56 @@ def move_files(repo: str, src_path: str):
else:
tmp_dir = os.path.join(ROOT_DIR, f"{repo}.tmp")
safe_rmtree(tmp_dir)
- gui_dir = os.path.join(ROOT_DIR, f"gui") if repo == "gui" else None
- if gui_dir and os.path.isdir(gui_dir):
+ gui_dir = os.path.join(ROOT_DIR, f"gui") if repo == "taipy-gui" else None
+ if repo == "taipy-gui" and os.path.isdir(gui_dir):
if os.path.isdir(os.path.join(gui_dir, "node_modules")):
shutil.move(os.path.join(gui_dir, "node_modules"), os.path.join(ROOT_DIR, f"gui_node_modules"))
shutil.rmtree(gui_dir)
try:
- def keep_py_files(dir, filenames):
- return [name for name in filenames if not os.path.isdir(os.path.join(dir, name)) and not (
- name.endswith('.py') or name.endswith('.pyi') or name.endswith('.json') or name.endswith('.ipynb'))]
+ def copy_source(src_path: str, repo: str):
+ def copy(item: str, src: str, dst: str, rel_path: str):
+ full_src = os.path.join(src, item)
+ full_dst = os.path.join(dst, item)
+ if os.path.isdir(full_src):
+ if item in ["__pycache__", "node_modules"]:
+ return
+ if not os.path.isdir(full_dst):
+ os.makedirs(full_dst)
+ rel_path = f"{rel_path}/{item}"
+ for sub_item in os.listdir(full_src):
+ copy(sub_item, full_src, full_dst, rel_path)
+ elif any(item.endswith(ext) for ext in [".py", ".pyi", ".json", ".ipynb"]):
+ if os.path.isfile(full_dst): # File exists - compare
+ with open(full_src, "r") as f:
+ src = f.read()
+ with open(full_dst, "r") as f:
+ dst = f.read()
+ if src != dst:
+ raise FileExistsError(f"File {rel_path}/{item} already exists and is different (copying repository {repo})")
+ else:
+ shutil.copy(full_src, full_dst)
+ dest_path = os.path.join(ROOT_DIR, "taipy")
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+ src_path = os.path.join(src_path, "src", "taipy")
+ for item in os.listdir(src_path):
+ copy(item, src_path, dest_path, "")
+ copy_source(src_path, repo)
- shutil.copytree(os.path.join(src_path, "src", "taipy"), tmp_dir, ignore=keep_py_files)
- entries = os.listdir(tmp_dir)
- for entry in entries:
- try:
- if entry != "__pycache__":
- shutil.move(os.path.join(tmp_dir, entry), DEST_DIR)
- except shutil.Error as e:
- if entry != "__init__.py": # Top-most __entry__.py gets overwritten over and over
- raise e
if gui_dir:
- os.mkdir(gui_dir)
+ if not os.path.isdir(gui_dir):
+ os.mkdir(gui_dir)
src_gui_dir = os.path.join(src_path, "gui")
- shutil.copytree(os.path.join(src_gui_dir, "doc"), os.path.join(gui_dir, "doc"))
shutil.copytree(os.path.join(src_gui_dir, "src"), os.path.join(gui_dir, "src"))
for f in [f for f in os.listdir(src_gui_dir) if f.endswith(".md") or f.endswith(".json")]:
shutil.copy(os.path.join(src_gui_dir, f), os.path.join(gui_dir, f))
if os.path.isdir(os.path.join(ROOT_DIR, "gui_node_modules")):
shutil.move(os.path.join(ROOT_DIR, "gui_node_modules"), os.path.join(gui_dir, "node_modules"))
finally:
+ pass
+ """
shutil.rmtree(tmp_dir)
+ """
for repo in repo_defs.keys():
diff --git a/tools/postprocess.py b/tools/postprocess.py
index ceec608ca..4bb0e1bdc 100644
--- a/tools/postprocess.py
+++ b/tools/postprocess.py
@@ -85,8 +85,8 @@ def remove_dummy_h3(content: str, ids: Dict[str, str]) -> str:
def on_post_build(env):
"Post-build actions for Taipy documentation"
- site_dir = env.conf["site_dir"]
log = logging.getLogger("mkdocs")
+ site_dir = env.conf["site_dir"]
xrefs = {}
if os.path.exists(site_dir + "/manuals/xrefs"):
with open(site_dir + "/manuals/xrefs") as xrefs_file:
@@ -103,8 +103,11 @@ def on_post_build(env):
fixed_cross_refs = {}
for root, _, file_list in os.walk(site_dir):
for f in file_list:
+ # Remove the *_template files
+ if f.endswith("_template"):
+ os.remove(os.path.join(root, f))
# Post-process generated '.html' files
- if f.endswith(".html"):
+ elif f.endswith(".html"):
filename = os.path.join(root, f)
file_was_changed = False
with open(filename) as html_file: