From cfc0a14828fd7ad374932dd5fa2a40cfe9d50953 Mon Sep 17 00:00:00 2001 From: Henry Webel Date: Tue, 8 Apr 2025 17:13:17 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=A7=20ensure=20a=20valid=20python?= =?UTF-8?q?=20identifier=20for=20report=5Fmanger.py=20streamlit=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit save subsection are also referenced as Page instances, therefore they need a valid Python variable name. This would not be catched at build time, but only when report is being run. --- src/vuegen/streamlit_reportview.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index 74d5d24..eda7f9d 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 @@ -11,6 +12,17 @@ from .utils import create_folder, generate_footer, is_url +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 + + class StreamlitReportView(r.WebAppReportView): """ A Streamlit-based implementation of the WebAppReportView abstract base class. @@ -114,7 +126,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 +356,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 From b7bde51c8fde835357ff99c357736921c2094075 Mon Sep 17 00:00:00 2001 From: Henry Webel Date: Fri, 11 Apr 2025 09:18:45 +0200 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=9A=9A=20move=20utils=20to=20subpacka?= =?UTF-8?q?ge=20-=20helps=20to=20split=20up=20utils=20into=20submodules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vuegen/{utils.py => utils/__init__.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/vuegen/{utils.py => utils/__init__.py} (100%) 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 From d27d81019b2c14735b1b84092d3d230b0db25e0a Mon Sep 17 00:00:00 2001 From: Henry Webel Date: Fri, 11 Apr 2025 09:29:21 +0200 Subject: [PATCH 3/4] :sparkles: add test for valid identifier fct. move to utils --- src/vuegen/streamlit_reportview.py | 10 ---------- src/vuegen/utils/variables.py | 12 ++++++++++++ tests/utils/test_variables.py | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/vuegen/utils/variables.py create mode 100644 tests/utils/test_variables.py diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index eda7f9d..abb5be6 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -12,16 +12,6 @@ from .utils import create_folder, generate_footer, is_url -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 - class StreamlitReportView(r.WebAppReportView): """ 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 From 7a1489718d9ed5bd869c9c882f70bb37a39fd74d Mon Sep 17 00:00:00 2001 From: Henry Webel Date: Fri, 11 Apr 2025 09:31:53 +0200 Subject: [PATCH 4/4] :bug: add missing import --- src/vuegen/streamlit_reportview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index abb5be6..40ce2ce 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -10,7 +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):