Skip to content

Commit 768a159

Browse files
committed
Allow specifying document names to bake only those
1 parent cad2c06 commit 768a159

3 files changed

Lines changed: 67 additions & 13 deletions

File tree

src/pdfbaker/__main__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from pdfbaker import __version__
1010
from pdfbaker.baker import PDFBaker, PDFBakerOptions
11-
from pdfbaker.errors import PDFBakerError
11+
from pdfbaker.errors import DocumentNotFoundError, PDFBakerError
1212

1313
logger = logging.getLogger(__name__)
1414

@@ -24,6 +24,7 @@ def cli() -> None:
2424
"config_file",
2525
type=click.Path(exists=True, dir_okay=False, path_type=Path),
2626
)
27+
@click.argument("documents", nargs=-1)
2728
@click.option("-q", "--quiet", is_flag=True, help="Show errors only")
2829
@click.option("-v", "--verbose", is_flag=True, help="Show debug information")
2930
@click.option(
@@ -37,13 +38,17 @@ def cli() -> None:
3738
# pylint: disable=too-many-arguments,too-many-positional-arguments
3839
def bake(
3940
config_file: Path,
41+
documents: tuple[str, ...],
4042
quiet: bool,
4143
verbose: bool,
4244
trace: bool,
4345
keep_build: bool,
4446
debug: bool,
4547
) -> int:
46-
"""Parse config file and bake PDFs."""
48+
"""Parse config file and bake PDFs.
49+
50+
Optionally specify one or more document names to only process those documents.
51+
"""
4752
if debug:
4853
verbose = True
4954
keep_build = True
@@ -56,8 +61,11 @@ def bake(
5661
keep_build=keep_build,
5762
)
5863
baker = PDFBaker(config_file, options=options)
59-
success = baker.bake()
64+
success = baker.bake(document_names=documents if documents else None)
6065
sys.exit(0 if success else 1)
66+
except DocumentNotFoundError as exc:
67+
logger.error(str(exc))
68+
sys.exit(2)
6169
except PDFBakerError as exc:
6270
logger.error(str(exc))
6371
sys.exit(1)

src/pdfbaker/baker.py

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from .config import PDFBakerConfiguration, deep_merge
1414
from .document import PDFBakerDocument
15-
from .errors import ConfigurationError
15+
from .errors import ConfigurationError, DocumentNotFoundError
1616
from .logging import LoggingMixin, setup_logging
1717

1818
__all__ = ["PDFBaker", "PDFBakerOptions"]
@@ -59,6 +59,7 @@ def __init__(
5959
) -> None:
6060
"""Initialize baker configuration (needs documents)."""
6161
self.baker = baker
62+
self.name = config_file.name
6263
self.baker.log_debug_section("Loading main configuration: %s", config_file)
6364
super().__init__(base_config, config_file)
6465
self.baker.log_trace(self.pretty())
@@ -67,10 +68,12 @@ def __init__(
6768
'Key "documents" missing - is this the main configuration file?'
6869
)
6970
self.build_dir = self["directories"]["build"]
70-
self.documents = [
71-
self.resolve_path(doc_spec, directory=self["directories"]["documents"])
72-
for doc_spec in self["documents"]
73-
]
71+
self.documents = []
72+
for doc_spec in self["documents"]:
73+
doc_path = self.resolve_path(
74+
doc_spec, directory=self["directories"]["documents"]
75+
)
76+
self.documents.append({"name": doc_path.name, "path": doc_path})
7477

7578
def __init__(
7679
self,
@@ -99,22 +102,61 @@ def __init__(
99102
config_file=config_file,
100103
)
101104

102-
def bake(self) -> None:
103-
"""Create PDFs for all documents.
105+
def _get_documents_to_process(
106+
self, selected_document_names: tuple[str, ...] | None = None
107+
) -> list[Path]:
108+
"""Get the document paths to process based on optional filtering.
109+
110+
Args:
111+
document_names: Optional tuple of document names to process
112+
113+
Returns:
114+
List of document paths to process
115+
"""
116+
if not selected_document_names:
117+
return self.config.documents
118+
119+
available_doc_names = [doc["name"] for doc in self.config.documents]
120+
missing_docs = [
121+
name for name in selected_document_names if name not in available_doc_names
122+
]
123+
if missing_docs:
124+
self.log_info(
125+
f"Documents in {self.config.name}: %s",
126+
", ".join(f'"{name}"' for name in available_doc_names),
127+
)
128+
raise DocumentNotFoundError(
129+
f"{'Document' if len(missing_docs) == 1 else 'Documents'} not found in "
130+
f"configuration: {', '.join(f'"{name}"' for name in missing_docs)}."
131+
)
132+
133+
return [
134+
doc
135+
for doc in self.config.documents
136+
if doc["name"] in selected_document_names
137+
]
138+
139+
def bake(self, document_names: tuple[str, ...] | None = None) -> bool:
140+
"""Create PDFs for all documents or only the specified ones.
141+
142+
Args:
143+
document_names: Optional tuple of document names to process
104144
105145
Returns:
106146
bool: True if all documents were processed successfully, False if any failed
107147
"""
108148
pdfs_created: list[Path] = []
109149
failed_docs: list[tuple[str, str]] = []
110150

151+
documents = self._get_documents_to_process(document_names)
152+
111153
self.log_debug_subsection("Documents to process:")
112-
self.log_debug(self.config.documents)
113-
for doc_config in self.config.documents:
154+
self.log_debug(documents)
155+
for doc_config in documents:
114156
doc = PDFBakerDocument(
115157
baker=self,
116158
base_config=self.config,
117-
config_path=doc_config,
159+
config_path=doc_config["path"],
118160
)
119161
pdf_files, error_message = doc.process_document()
120162
if error_message:

src/pdfbaker/errors.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ class PDFBakerError(Exception):
1616
"""Base exception for PDF baking errors."""
1717

1818

19+
class DocumentNotFoundError(PDFBakerError):
20+
"""Document not found in main configuration."""
21+
22+
1923
class ConfigurationError(PDFBakerError):
2024
"""Failed to load or parse configuration."""
2125

0 commit comments

Comments
 (0)