Skip to content

Commit 36f789d

Browse files
committed
add per-problem webwork representation file checking
1 parent 6a8e124 commit 36f789d

2 files changed

Lines changed: 42 additions & 21 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ Instructions: Add a subsection under `[Unreleased]` for additions, fixes, change
99

1010
## [Unreleased]
1111

12+
### Changed
13+
14+
- WeBWorK representations now use individual files for each problem. Added checking for these files as they are needed in the build process.
15+
1216
## [2.39.0] - 2026-05-10
1317

1418
Includes updates to core through commit: [b169423](https://github.com/PreTeXtBook/pretext/commit/b16942370f7710784c73c28349c62d4f368b3825)

pretext/project/__init__.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,10 @@ class Target(pxml.BaseXmlModel, tag="target", search_mode=SearchMode.UNORDERED):
138138
#
139139
# A path to the root source for this target, relative to the project's `source` path.
140140
source: Path = pxml.attr(default=Path("main.ptx"))
141-
# Cache of assembled source element.
141+
# Cache of assembled "version only" source element.
142142
_source_element: t.Optional[ET._Element] = None
143+
# Cache of assembled with assembly-ids.
144+
_source_element_with_ids: t.Optional[ET._Element] = None
143145
# A path to the publication file for this target, relative to the project's `publication` path. This is mostly validated by `post_validate`.
144146
publication: Path = pxml.attr(default=None)
145147
latex_engine: LatexEngine = pxml.attr(
@@ -403,6 +405,7 @@ def source_element(self) -> ET._Element:
403405
Caches the result for future calls.
404406
"""
405407
if self._source_element is None:
408+
406409
log.debug(
407410
f"Parsing source element for target {self.name}",
408411
)
@@ -414,10 +417,25 @@ def source_element(self) -> ET._Element:
414417
).getroot()
415418
else:
416419
log.debug(f"Using cached source_element for target {self.name}")
417-
#print out entire tree for debugging:
418-
log.debug("Assembled source element: ")
419-
log.debug(ET.tostring(self._source_element, pretty_print=True).decode("utf-8"))
420420
return self._source_element
421+
422+
def source_element_with_ids(self) -> ET._Element:
423+
"""
424+
Returns the root element for the assembled source, after processing with assembly-id method. Caches the result for future calls.
425+
"""
426+
if self._source_element_with_ids is None:
427+
log.debug(
428+
f"Parsing source element with assembly ids for target {self.name}",
429+
)
430+
self._source_element_with_ids = core.assembly_internal(
431+
xml=self.source_abspath(),
432+
pub_file=self.publication_abspath().as_posix(),
433+
stringparams=self.stringparams.copy(),
434+
method="assembly-id",
435+
).getroot()
436+
else:
437+
log.debug(f"Using cached source_element_with_ids for target {self.name}")
438+
return self._source_element_with_ids
421439

422440
def publication_abspath(self) -> Path:
423441
return self._project.publication_abspath() / self.publication
@@ -599,26 +617,25 @@ def ensure_webwork_reps(self) -> None:
599617
"""
600618
Ensures that the webwork representation file is present if the source contains webwork problems. This is needed to build or generate other assets.
601619
"""
602-
# NB: need to include `text()` as well as `@*|*` in the xpath, since some webwork problems are only included as text/pg source.
620+
# NB: need to include `text()` as well as `@copy|@source|*` in the xpath, since some webwork problems are only included as text/pg source.
603621
if self.source_element().xpath(".//webwork[@copy|@source|*|text()]"):
604622
log.debug("Source contains webwork problems")
605-
#spit out all the attributes of each parent of a webwork elements for debugging:
606-
#webwork_elements = self.source_element().xpath(
607-
# ".//webwork[@copy|@source|*|text()]/parent::*"
608-
#)
609-
#assert isinstance(webwork_elements, t.List)
610-
#for elem in webwork_elements:
611-
# assert isinstance(elem, ET._Element)
612-
# log.debug(f"Webwork element attributes: {elem.attrib}")
613-
if not (
614-
self.generated_dir_abspath() / "webwork" / "webwork-representations.xml"
615-
).exists():
616-
log.debug("Webwork representations file does not exist, generating")
617-
self.generate_assets(
618-
requested_asset_types=["webwork"], only_changed=False
619-
)
623+
#Get list of all assembly-ids for webwork (this will be the assembly-id of the parent of the webwork element).
624+
webwork_assembly_ids = self.source_element_with_ids().xpath(
625+
".//webwork[@copy|@source|*|text()]/parent::*/@assembly-id"
626+
)
627+
assert isinstance(webwork_assembly_ids, t.List)
628+
for id in webwork_assembly_ids:
629+
if not (
630+
self.generated_dir_abspath() / "webwork" / f"{id}.xml"
631+
).exists():
632+
log.debug(f"At least one WeBWorK representation file (for webwork problem with id \"{id}\") does not exist, generating")
633+
self.generate_assets(
634+
requested_asset_types=["webwork"], only_changed=False
635+
)
636+
break
620637
else:
621-
log.debug("Webwork representations file exists, not generating")
638+
log.debug("All WeBWorK representation files already exist, not generating")
622639
else:
623640
log.debug("Source does not contain webwork problems")
624641

0 commit comments

Comments
 (0)