|
1 | 1 | import os |
| 2 | +import re |
2 | 3 | import subprocess |
3 | 4 | import sys |
4 | 5 | from pathlib import Path |
|
11 | 12 | from .utils import create_folder, generate_footer, is_url |
12 | 13 |
|
13 | 14 |
|
| 15 | +def make_valid_identifier(name: str) -> str: |
| 16 | + """Create a valid Python identifier from a given name. |
| 17 | +
|
| 18 | + Used in streamlit report sections to build structure (pages). |
| 19 | + """ |
| 20 | + ret = re.sub(r"[^a-zA-Z0-9]", "_", name) |
| 21 | + if not ret[0].isalpha(): |
| 22 | + ret = "_" + ret |
| 23 | + return ret |
| 24 | + |
| 25 | + |
14 | 26 | class StreamlitReportView(r.WebAppReportView): |
15 | 27 | """ |
16 | 28 | A Streamlit-based implementation of the WebAppReportView abstract base class. |
@@ -114,7 +126,15 @@ def generate_report( |
114 | 126 | ) |
115 | 127 |
|
116 | 128 | for subsection in section.subsections: |
117 | | - subsection_name_var = subsection.title.replace(" ", "_") |
| 129 | + # ! could add a non-integer to ensure it's a valid identifier |
| 130 | + subsection_name_var = make_valid_identifier(subsection.title) |
| 131 | + if not subsection_name_var.isidentifier(): |
| 132 | + self.report.logger.warning( |
| 133 | + f"Subsection name '{subsection_name_var}' is not a valid identifier." |
| 134 | + ) |
| 135 | + raise ValueError( |
| 136 | + f"Subsection name is not a valid Python identifier: {subsection_name_var}" |
| 137 | + ) |
118 | 138 | subsection_file_path = ( |
119 | 139 | Path(section_name_var) / f"{subsection_name_var}.py" |
120 | 140 | ).as_posix() # Make sure it's Posix Paths |
@@ -336,10 +356,11 @@ def _generate_sections(self, output_dir: str, static_dir: str) -> None: |
336 | 356 | ) |
337 | 357 | try: |
338 | 358 | # Create subsection file |
| 359 | + _subsection_name = make_valid_identifier(subsection.title) |
339 | 360 | subsection_file_path = ( |
340 | 361 | Path(output_dir) |
341 | 362 | / section_name_var |
342 | | - / f"{subsection.title.replace(' ', '_')}.py" |
| 363 | + / f"{_subsection_name}.py" |
343 | 364 | ) |
344 | 365 |
|
345 | 366 | # Generate content and imports for the subsection |
|
0 commit comments