diff --git a/src/vuegen/quarto_reportview.py b/src/vuegen/quarto_reportview.py index 8fd6f1f..21eb79d 100644 --- a/src/vuegen/quarto_reportview.py +++ b/src/vuegen/quarto_reportview.py @@ -7,7 +7,7 @@ import pandas as pd from . import report as r -from .utils import create_folder, is_url +from .utils import create_folder, is_url, sort_imports class QuartoReportView(r.ReportView): @@ -118,7 +118,16 @@ def generate_report( ] # Remove duplicated imports - report_unique_imports = list(set(flattened_report_imports)) + report_unique_imports = set(flattened_report_imports) + + # ! set leads to random import order + # ! separate and sort import statements, separate from setup code + + report_unique_imports, setup_statements = sort_imports( + report_unique_imports + ) + report_unique_imports += os.linesep + report_unique_imports.extend(setup_statements) # Format imports report_formatted_imports = "\n".join(report_unique_imports) @@ -801,8 +810,9 @@ def _generate_component_imports(self, component: r.Component) -> List[str]: r.PlotType.PLOTLY: ["import plotly.io as pio", "import requests"], }, "dataframe": [ + "init_notebook_mode(all_interactive=True)", # ! somehow order is random in qmd file "import pandas as pd", - "from itables import show", + "from itables import show, init_notebook_mode", "import dataframe_image as dfi", ], "markdown": ["import IPython.display as display", "import requests"], diff --git a/src/vuegen/utils.py b/src/vuegen/utils.py index 41fa4e7..981d0dd 100644 --- a/src/vuegen/utils.py +++ b/src/vuegen/utils.py @@ -14,7 +14,7 @@ from io import StringIO from pathlib import Path -from typing import Type +from typing import Iterable, Type from urllib.parse import urlparse import networkx as nx @@ -798,3 +798,41 @@ def generate_footer() -> str: """ return footer + + +def sort_imports(imp: Iterable[str]) -> tuple[list[str], list[str]]: + """Separte 'from' and 'import' statements from setup code. + + Parameters + ---------- + imp : Iterable[str] + A list of import statements and setup statements. + + Returns + ------- + Tuple[List[str], List[str]] + A tuple of two lists: one for import statements and one for setup statements. + + Examples + -------- + >>> imp = [ + ... 'import logging', + ... 'import shutil', + ... 'logging.basicConfig(level=logging.INFO)', + ... 'import pandas as pd', + ... 'import numpy as np', + ... ] + >>> sort_imports(imp) + (['import logging', 'import numpy as np', 'import pandas as pd', 'import shutil + ], ['logging.basicConfig(level=logging.INFO)']) + """ + imports_statements, setup_statements = [], [] + for line in imp: + line = line.strip() # just for safety + if line.startswith("from ") or line.startswith("import "): + imports_statements.append(line) + else: + setup_statements.append(line) + imports_statements.sort() + setup_statements.sort() + return imports_statements, setup_statements