Skip to content

Commit 1e27019

Browse files
committed
Finish transition to pydantic
Major reshuffling. Tests are all passing again.
1 parent 2731eb5 commit 1e27019

15 files changed

Lines changed: 1100 additions & 1083 deletions

File tree

src/pdfbaker/baker.py

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010

1111
from pydantic import BaseModel, ValidationError
1212

13-
from .config import (
14-
BakerConfig,
15-
PathSpec,
16-
)
13+
from .config import PathSpec
14+
from .config.baker import BakerConfig
1715
from .document import Document
1816
from .errors import DocumentNotFoundError
1917
from .logging import LoggingMixin, setup_logging
@@ -54,63 +52,84 @@ def __init__(
5452
self.log_debug_section("Loading main configuration: %s", config_file)
5553
self.config = BakerConfig(
5654
config_file=config_file,
57-
keep_build=options and options.keep_build or False,
55+
keep_build=options.keep_build,
5856
**kwargs,
5957
)
6058
self.log_trace(self.config.readable())
6159

62-
def _get_documents_to_process(
63-
self, selected_document_names: tuple[str, ...] | None = None
64-
) -> list[PathSpec]:
65-
"""Get the document paths to process based on optional filtering.
60+
def bake(self, document_names: tuple[str, ...] | None = None) -> None:
61+
"""Bake the documents."""
62+
docs = self._get_selected_documents(document_names)
63+
self.log_debug_subsection("Documents to process:")
64+
self.log_debug(docs)
65+
66+
pdfs_created, failed_docs = self._process_documents(docs)
6667

67-
Args:
68-
document_names: Optional tuple of document names to process
68+
if pdfs_created:
69+
self.log_info("Successfully created PDFs:")
70+
for pdf in pdfs_created:
71+
self.log_info(" ✅ %s", pdf)
72+
else:
73+
self.log_warning("No PDFs were created.")
6974

70-
Returns:
71-
List of document paths to process
72-
"""
73-
if not selected_document_names:
75+
if not self.config.keep_build:
76+
self.teardown()
77+
78+
if failed_docs:
79+
self.log_warning(
80+
"Failed to process %d document%s:",
81+
len(failed_docs),
82+
"" if len(failed_docs) == 1 else "s",
83+
)
84+
for failed_doc, error_message in failed_docs:
85+
name = failed_doc.name
86+
if isinstance(failed_doc, Document) and failed_doc.is_variant:
87+
name += f' variant "{failed_doc.variant["name"]}"'
88+
self.log_error(" %s: %s", name, error_message)
89+
90+
return not failed_docs
91+
92+
def _get_selected_documents(
93+
self, selected_names: tuple[str, ...] | None = None
94+
) -> list[PathSpec]:
95+
"""Return the document paths to actually process as selected."""
96+
if not selected_names:
7497
return self.config.documents
7598

76-
available_doc_names = [doc.name for doc in self.config.documents]
77-
missing_docs = [
78-
name for name in selected_document_names if name not in available_doc_names
79-
]
80-
if missing_docs:
81-
available_str = ", ".join([f'"{name}"' for name in available_doc_names])
99+
available = [doc.name for doc in self.config.documents]
100+
missing = [name for name in selected_names if name not in available]
101+
if missing:
102+
available_str = ", ".join([f'"{name}"' for name in available])
82103
self.log_info(
83104
f"Documents in {self.config.config_file.name}: {available_str}"
84105
)
85-
missing_str = ", ".join([f'"{name}"' for name in missing_docs])
106+
missing_str = ", ".join([f'"{name}"' for name in missing])
86107
raise DocumentNotFoundError(
87-
f"Document{'s' if len(missing_docs) != 1 else ''} not found "
88-
f"in configuration: {missing_str}."
108+
f"Document{'s' if len(missing) != 1 else ''} not found "
109+
f"in configuration file: {missing_str}."
89110
)
90111

91-
return [
92-
doc for doc in self.config.documents if doc.name in selected_document_names
93-
]
112+
return [doc for doc in self.config.documents if doc.name in selected_names]
94113

95-
def bake(self, document_names: tuple[str, ...] | None = None) -> None:
96-
"""Bake the documents."""
114+
def _process_documents(
115+
self, docs: list[PathSpec]
116+
) -> tuple[list[Path], list[tuple[PathSpec, str]]]:
97117
pdfs_created: list[Path] = []
98118
failed_docs: list[tuple[PathSpec, str]] = []
99119

100-
doc_configs = self._get_documents_to_process(document_names)
101-
102-
self.log_debug_subsection("Documents to process:")
103-
self.log_debug(doc_configs)
104-
for doc_config in doc_configs:
120+
for config_path in docs:
105121
try:
106122
document = Document(
107-
config_path=doc_config, **self.config.document_settings
123+
config_path=config_path, **self.config.document_settings
108124
)
109125
except ValidationError as e:
110-
self.log_error(f'Invalid config for document "{doc_config.name}": {e}')
126+
error_message = f'Invalid config for document "{config_path.name}": {e}'
127+
self.log_error(error_message)
128+
failed_docs.append((config_path, error_message))
111129
continue
112130

113131
pdf_files, error_message = document.process_document()
132+
114133
if error_message:
115134
self.log_error(
116135
"Failed to process document '%s': %s",
@@ -125,26 +144,7 @@ def bake(self, document_names: tuple[str, ...] | None = None) -> None:
125144
if not self.config.keep_build:
126145
document.teardown()
127146

128-
if pdfs_created:
129-
self.log_info("Successfully created PDFs:")
130-
for pdf in pdfs_created:
131-
self.log_info(" %s", pdf)
132-
else:
133-
self.log_warning("No PDFs were created.")
134-
135-
if failed_docs:
136-
self.log_warning(
137-
"Failed to process %d document%s:",
138-
len(failed_docs),
139-
"" if len(failed_docs) == 1 else "s",
140-
)
141-
for doc_name, error in failed_docs:
142-
self.log_error(" %s: %s", doc_name, error)
143-
144-
if not self.config.keep_build:
145-
self.teardown()
146-
147-
return not failed_docs
147+
return pdfs_created, failed_docs
148148

149149
def teardown(self) -> None:
150150
"""Clean up (top-level) build directory after processing."""

0 commit comments

Comments
 (0)