Skip to content

Commit 4c86e89

Browse files
committed
Remove the report_format parameter and put their values in the report_type enum. Add code to define congig_path and report_type as commandline args instead of variables in the main file. Modified main, report_generator, and vuegen_demo.ipynb with these changes.
1 parent cdeb2a6 commit 4c86e89

File tree

8 files changed

+164
-217
lines changed

8 files changed

+164
-217
lines changed

docs/vuegen_demo.ipynb

Lines changed: 71 additions & 150 deletions
Large diffs are not rendered by default.

report_metadata_micw2graph.yaml renamed to report_config_micw2graph.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ report:
1111
and potential ecological functions.
1212
graphical_abstract: "example_data/MicW2Graph/Methods_MicW2Graph.png"
1313
logo: "example_data/mona_logo.png"
14-
report_type: "document"
15-
report_format: "docx"
1614
sections:
1715
- title: "Exploratory Data Analysis"
1816
subsections:

vuegen/main.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
import report_generator
2-
from utils import get_logger, load_yaml_config
2+
from utils import get_logger, load_yaml_config, get_args
33

44
if __name__ == '__main__':
5+
# Parse command-line arguments
6+
args = get_args(prog_name="Vuegen")
7+
config_path = args.config
8+
report_type = args.report_type
9+
510
# Load the YAML configuration file with the report metadata
6-
config_path = "report_metadata_micw2graph.yaml"
711
report_config = load_yaml_config(config_path)
812

9-
# Define logger suffix based on report engine, type and name
10-
report_engine = "quarto"
11-
report_type = report_config['report'].get('report_type')
12-
report_format = report_config['report'].get('report_format')
13+
# Define logger suffix based on report type and name
1314
report_name = report_config['report'].get('name')
14-
if report_engine == "streamlit":
15-
logger_suffix = f"{report_engine}_report_{report_name}"
16-
else:
17-
logger_suffix = f"{report_type}_{report_format}_report_{report_name}"
15+
logger_suffix = f"{report_type}_report_{report_name}"
1816

1917
# Initialize logger
2018
logger = get_logger(f"{logger_suffix}")
2119

2220
# Generate the report
23-
report_generator.get_report(config = report_config, report_engine = report_engine, logger = logger)
21+
report_generator.get_report(config = report_config, report_type = report_type, logger = logger)
2422

vuegen/quarto_reportview.py

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
import os
22
import subprocess
33
import report as r
4-
from enum import StrEnum, auto
54
from typing import List
65
from utils import create_folder
76

8-
class ReportFormat(StrEnum):
9-
HTML = auto()
10-
PDF = auto()
11-
DOCX = auto()
12-
ODT = auto()
13-
REVEALJS = auto()
14-
PPTX = auto()
15-
JUPYTER = auto()
16-
177
class QuartoReportView(r.ReportView):
188
"""
199
A ReportView subclass for generating Quarto reports.
@@ -22,9 +12,8 @@ class QuartoReportView(r.ReportView):
2212
BASE_DIR = 'quarto_report'
2313
STATIC_FILES_DIR = os.path.join(BASE_DIR, 'static')
2414

25-
def __init__(self, report: r.Report, report_type: r.ReportType, report_format: ReportFormat):
26-
super().__init__(report=report, report_type = report_type)
27-
self.report_format = report_format
15+
def __init__(self, report: r.Report, report_type: r.ReportType):
16+
super().__init__(report = report, report_type = report_type)
2817

2918
def generate_report(self, output_dir: str = BASE_DIR, static_dir: str = STATIC_FILES_DIR) -> None:
3019
"""
@@ -37,7 +26,7 @@ def generate_report(self, output_dir: str = BASE_DIR, static_dir: str = STATIC_F
3726
static_dir : str, optional
3827
The folder where the static files will be saved (default is STATIC_FILES_DIR).
3928
"""
40-
self.report.logger.debug(f"Generating '{self.report_type}' report with '{self.report_format}' format in directory: '{output_dir}'")
29+
self.report.logger.debug(f"Generating '{self.report_type}' report in directory: '{output_dir}'")
4130

4231
# Create the output folder
4332
if create_folder(output_dir):
@@ -53,8 +42,8 @@ def generate_report(self, output_dir: str = BASE_DIR, static_dir: str = STATIC_F
5342

5443
try:
5544
# Create variable to check if the report is static or revealjs
56-
is_report_static = self.report_format in {ReportFormat.PDF, ReportFormat.DOCX, ReportFormat.ODT, ReportFormat.PPTX}
57-
is_report_revealjs = self.report_format == ReportFormat.REVEALJS
45+
is_report_static = self.report_type in {r.ReportType.PDF, r.ReportType.DOCX, r.ReportType.ODT, r.ReportType.PPTX}
46+
is_report_revealjs = self.report_type == r.ReportType.REVEALJS
5847

5948
# Define the YAML header for the quarto report
6049
yaml_header = self._create_yaml_header()
@@ -122,7 +111,7 @@ def run_report(self, output_dir: str = BASE_DIR) -> None:
122111
"""
123112
try:
124113
subprocess.run(["quarto", "render", os.path.join(output_dir, f"{self.BASE_DIR}.qmd")], check=True)
125-
self.report.logger.info(f"'{self.report.title}' '{self.report_type}' report rendered with the '{self.report_format}' format")
114+
self.report.logger.info(f"'{self.report.title}' '{self.report_type}' report rendered")
126115
except subprocess.CalledProcessError as e:
127116
self.report.logger.error(f"Error running '{self.report.title}' {self.report_type} report: {str(e)}")
128117
raise
@@ -147,47 +136,47 @@ def _create_yaml_header(self) -> str:
147136

148137
# Define format-specific YAML configurations
149138
format_configs = {
150-
(r.ReportType.DOCUMENT, ReportFormat.HTML): """
139+
r.ReportType.HTML: """
151140
html:
152141
toc: true
153142
toc-location: left
154143
toc-depth: 3
155144
page-layout: full
156145
self-contained: true""",
157-
(r.ReportType.DOCUMENT, ReportFormat.PDF): """
146+
r.ReportType.PDF: """
158147
pdf:
159148
toc: false""",
160-
(r.ReportType.DOCUMENT, ReportFormat.DOCX): """
149+
r.ReportType.DOCX: """
161150
docx:
162151
toc: false""",
163-
(r.ReportType.DOCUMENT, ReportFormat.ODT): """
152+
r.ReportType.ODT: """
164153
odt:
165154
toc: false""",
166-
(r.ReportType.PRESENTATION, ReportFormat.REVEALJS): """
155+
r.ReportType.REVEALJS: """
167156
revealjs:
168157
toc: false
169158
smaller: true
170159
controls: true
171160
navigation-mode: vertical
172161
controls-layout: bottom-right
173162
output-file: quarto_report_revealjs.html""",
174-
(r.ReportType.PRESENTATION, ReportFormat.PPTX): """
163+
r.ReportType.PPTX: """
175164
pptx:
176165
toc: false
177166
output: true""",
178-
(r.ReportType.NOTEBOOK, ReportFormat.JUPYTER): """
167+
r.ReportType.JUPYTER: """
179168
jupyter:
180169
kernel: python3"""
181170
}
182171

183172
# Create a key based on the report type and format
184-
key = (self.report_type, self.report_format)
173+
key = self.report_type
185174

186175
# Retrieve the configuration if it exists, or raise an error
187176
if key in format_configs:
188177
config = format_configs[key]
189178
else:
190-
raise ValueError(f"Unsupported report type or format: {self.report_type}, {self.report_format}")
179+
raise ValueError(f"Unsupported report type: {self.report_type}")
191180

192181
# Add the specific configuration to the YAML header
193182
yaml_header += config

vuegen/report.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414

1515
class ReportType(StrEnum):
1616
STREAMLIT = auto()
17-
DOCUMENT = auto()
18-
PRESENTATION = auto()
19-
NOTEBOOK = auto()
17+
HTML = auto()
18+
PDF = auto()
19+
DOCX = auto()
20+
ODT = auto()
21+
REVEALJS = auto()
22+
PPTX = auto()
23+
JUPYTER = auto()
2024

2125
class ComponentType(StrEnum):
2226
PLOT = auto()

vuegen/report_generator.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
11
from streamlit_reportview import StreamlitReportView
2-
from quarto_reportview import QuartoReportView, ReportFormat
2+
from quarto_reportview import QuartoReportView
33
from metadata_manager import MetadataManager
44
from report import ReportType
55
from utils import assert_enum_value
6-
from enum import StrEnum, auto
76
import logging
87

9-
class ReportEngine(StrEnum):
10-
STREAMLIT = auto()
11-
QUARTO = auto()
12-
13-
def get_report(config: dict, report_engine: str, logger: logging.Logger) -> None:
8+
def get_report(config: dict, report_type: str, logger: logging.Logger) -> None:
149
"""
1510
Generate and run a report based on the specified engine.
1611
1712
Parameters
1813
----------
1914
config : dict
2015
The report metadata obtained from a YAML config file.
21-
report_engine : str
22-
The engine to use for generating and displaying the report.
23-
It should be one of the values of the ReportEngine Enum.
16+
report_type : str
17+
The report type. It should be one of the values of the ReportType Enum.
2418
logger : logging.Logger
2519
A logger object to track warnings, errors, and info messages.
2620
@@ -29,31 +23,26 @@ def get_report(config: dict, report_engine: str, logger: logging.Logger) -> None
2923
ValueError
3024
If an unsupported report engine, report type, or report format are provided.
3125
"""
32-
# Validate and convert the report engine to its enum value
33-
validated_engine = assert_enum_value(ReportEngine, report_engine, logger)
34-
3526
# Load report object and metadata from the YAML file
3627
yaml_manager = MetadataManager(logger)
3728
report, report_metadata = yaml_manager.initialize_report(config)
3829

39-
# Collect report type from YAML file
40-
report_type = assert_enum_value(ReportType, report_metadata['report']['report_type'], logger)
30+
# Validate and convert the report type to its enum value
31+
report_type = assert_enum_value(ReportType, report_type, logger)
4132

42-
# Create and run ReportView object based on its engine
43-
if validated_engine == ReportEngine.STREAMLIT:
33+
# Create and run ReportView object based on its type
34+
if report_type == ReportType.STREAMLIT:
4435
st_report = StreamlitReportView(
4536
report=report,
4637
report_type=report_type
4738
)
4839
st_report.generate_report()
4940
st_report.run_report()
5041

51-
elif validated_engine == ReportEngine.QUARTO:
52-
report_format = assert_enum_value(ReportFormat, report_metadata['report']['report_format'], logger)
42+
else:
5343
quarto_report = QuartoReportView(
5444
report=report,
55-
report_type=report_type,
56-
report_format=report_format
45+
report_type=report_type
5746
)
5847
quarto_report.generate_report()
5948
quarto_report.run_report()

vuegen/streamlit_reportview.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ def _generate_plot_content(self, plot, static_dir: str = STATIC_FILES_DIR) -> Li
300300
The folder where the static files will be saved (default is STATIC_FILES_DIR).
301301
"""
302302
plot_content = []
303-
304303
# Add title
305304
plot_content.append(self._format_text(text=plot.title, type='header', level=4, color='#2b8cbe'))
306305

@@ -313,7 +312,6 @@ def _generate_plot_content(self, plot, static_dir: str = STATIC_FILES_DIR) -> Li
313312
elif plot.plot_type == r.PlotType.ALTAIR:
314313
plot_content.append(self._generate_plot_code(plot))
315314
elif plot.plot_type == r.PlotType.INTERACTIVE_NETWORK:
316-
# Handle the network visualization
317315
G = plot.read_network()
318316
html_plot_file = os.path.join(static_dir, f"{plot.title.replace(' ', '_')}.html")
319317
net = plot.create_and_save_pyvis_network(G, html_plot_file)

vuegen/utils.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import yaml
44
from datetime import datetime
55
import logging
6+
import argparse
67
from enum import StrEnum
78
from typing import Type
89

@@ -16,12 +17,12 @@ def check_path(filepath: str) -> bool:
1617
filepath : str
1718
The file or folder path to check.
1819
19-
RETURNS
20+
Returns
2021
-------
2122
bool
2223
True if the path exists, False otherwise.
2324
24-
RAISES
25+
Raises
2526
------
2627
AssertionError
2728
If the filepath is not a valid string.
@@ -100,6 +101,55 @@ def create_folder(directory_path: str, is_nested: bool = False) -> bool:
100101
except OSError as e:
101102
raise OSError(f"Error creating directory '{directory_path}': {e}")
102103

104+
def get_args(prog_name: str, others: dict = {}) -> argparse.Namespace:
105+
"""
106+
Initiates argparse.ArgumentParser() and adds common arguments.
107+
108+
Parameters
109+
----------
110+
prog_name : str
111+
The name of the program.
112+
113+
others : dict, optional
114+
Additional keyword arguments for ArgumentParser initialization.
115+
116+
Returns
117+
-------
118+
argparse.Namespace
119+
Parsed command-line arguments.
120+
121+
Raises
122+
------
123+
AssertionError
124+
If prog_name is not a string or others is not a dictionary.
125+
"""
126+
# Preconditions
127+
assert isinstance(prog_name, str), f"prog_name should be a string: {prog_name}"
128+
assert isinstance(others, dict), f"others must be a dict: {others}"
129+
130+
# Initialize argument parser
131+
parser = argparse.ArgumentParser(prog=prog_name, **others)
132+
133+
# Add arguments
134+
parser.add_argument(
135+
"-c",
136+
"--config",
137+
type=str,
138+
default="report_config_micw2graph.yaml",
139+
help="Path to the YAML configuration file."
140+
)
141+
parser.add_argument(
142+
"-rt",
143+
"--report_type",
144+
type=str,
145+
default=None,
146+
help="Type of the report to generate (streamlit, html, pdf, docx, odt, revealjs, pptx, or jupyter)."
147+
)
148+
149+
# Parse arguments
150+
return parser.parse_args()
151+
152+
103153
## CONFIG
104154
def load_yaml_config(file_path: str) -> dict:
105155
"""

0 commit comments

Comments
 (0)