diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index 74d5d24..40ce2ce 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -1,4 +1,5 @@ import os +import re import subprocess import sys from pathlib import Path @@ -9,6 +10,7 @@ from . import report as r from .utils import create_folder, generate_footer, is_url +from .utils.variables import make_valid_identifier class StreamlitReportView(r.WebAppReportView): @@ -114,7 +116,15 @@ def generate_report( ) for subsection in section.subsections: - subsection_name_var = subsection.title.replace(" ", "_") + # ! could add a non-integer to ensure it's a valid identifier + subsection_name_var = make_valid_identifier(subsection.title) + if not subsection_name_var.isidentifier(): + self.report.logger.warning( + f"Subsection name '{subsection_name_var}' is not a valid identifier." + ) + raise ValueError( + f"Subsection name is not a valid Python identifier: {subsection_name_var}" + ) subsection_file_path = ( Path(section_name_var) / f"{subsection_name_var}.py" ).as_posix() # Make sure it's Posix Paths @@ -336,10 +346,11 @@ def _generate_sections(self, output_dir: str, static_dir: str) -> None: ) try: # Create subsection file + _subsection_name = make_valid_identifier(subsection.title) subsection_file_path = ( Path(output_dir) / section_name_var - / f"{subsection.title.replace(' ', '_')}.py" + / f"{_subsection_name}.py" ) # Generate content and imports for the subsection diff --git a/src/vuegen/utils.py b/src/vuegen/utils/__init__.py similarity index 100% rename from src/vuegen/utils.py rename to src/vuegen/utils/__init__.py diff --git a/src/vuegen/utils/variables.py b/src/vuegen/utils/variables.py new file mode 100644 index 0000000..7a532b6 --- /dev/null +++ b/src/vuegen/utils/variables.py @@ -0,0 +1,12 @@ +import re + + +def make_valid_identifier(name: str) -> str: + """Create a valid Python identifier from a given name. + + Used in streamlit report sections to build structure (pages). + """ + ret = re.sub(r"[^a-zA-Z0-9]", "_", name) + if not ret[0].isalpha(): + ret = "_" + ret + return ret diff --git a/tests/utils/test_variables.py b/tests/utils/test_variables.py new file mode 100644 index 0000000..cc4bae2 --- /dev/null +++ b/tests/utils/test_variables.py @@ -0,0 +1,16 @@ +import pytest + +from vuegen.utils.variables import make_valid_identifier + +test_cases = [ + ("a.non valid name", "a_non_valid_name"), + ("1.non valid name", "_1_non_valid_name"), + ("a_valid_name", "a_valid_name"), + ("test", "test"), +] + + +@pytest.mark.parametrize("var_name,expected", test_cases) +def test_make_valid_identifier(var_name, expected): + """Test the make_valid_identifier function.""" + assert make_valid_identifier(var_name) == expected