pretext 2.33.1.dev20251210064446__tar.gz → 2.33.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/PKG-INFO +3 -3
  2. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/__init__.py +1 -1
  3. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/codechat.py +3 -1
  4. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/project/__init__.py +25 -32
  5. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/resources/core.zip +0 -0
  6. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/resources/pelican.zip +0 -0
  7. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/resources/resource_hash_table.json +19 -9
  8. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/resources/rs_cache.zip +0 -0
  9. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/resources/templates.zip +0 -0
  10. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/utils.py +30 -6
  11. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pyproject.toml +3 -3
  12. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/LICENSE +0 -0
  13. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/README.md +0 -0
  14. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/__main__.py +0 -0
  15. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/cli.py +0 -0
  16. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/constants.py +0 -0
  17. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/core/__init__.py +0 -0
  18. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/core/braille_format.py +0 -0
  19. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/core/pretext.py +0 -0
  20. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/logger.py +0 -0
  21. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Alignment.jinja2s +0 -0
  22. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Arrays.jinja2s +0 -0
  23. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Bibliography.jinja2s +0 -0
  24. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Boxes.jinja2s +0 -0
  25. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Breaking.jinja2s +0 -0
  26. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Crossref.jinja2s +0 -0
  27. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Floats.jinja2s +0 -0
  28. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/FontSelection.jinja2s +0 -0
  29. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Footnotes.jinja2s +0 -0
  30. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Index.jinja2s +0 -0
  31. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Lists.jinja2s +0 -0
  32. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Pictures.jinja2s +0 -0
  33. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Quotations.jinja2s +0 -0
  34. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Sectioning.jinja2s +0 -0
  35. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Sentences.jinja2s +0 -0
  36. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Space.jinja2s +0 -0
  37. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Tabbing.jinja2s +0 -0
  38. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Themes/__init__.py +0 -0
  39. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Themes/default/__init__.py +0 -0
  40. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Themes/default/default-layout.jinja2 +0 -0
  41. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Themes/default/document-layout.jinja2 +0 -0
  42. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Thms.jinja2s +0 -0
  43. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/Verbatim.jinja2s +0 -0
  44. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/__init__.py +0 -0
  45. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/babel.jinja2s +0 -0
  46. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/graphicx.jinja2s +0 -0
  47. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/hyperref.jinja2s +0 -0
  48. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/lipsum.jinja2s +0 -0
  49. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/longtable.jinja2s +0 -0
  50. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/math.jinja2s +0 -0
  51. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/misc.jinja2s +0 -0
  52. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/natbib.jinja2s +0 -0
  53. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/p.jinja2s +0 -0
  54. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/subfig.jinja2s +0 -0
  55. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/textcomp.jinja2s +0 -0
  56. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/tikzcd.jinja2 +0 -0
  57. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/tikzpicture.jinja2 +0 -0
  58. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/url.jinja2s +0 -0
  59. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/plastex/wrapfig.jinja2s +0 -0
  60. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/project/generate.py +0 -0
  61. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/project/xml.py +0 -0
  62. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/resources/__init__.py +0 -0
  63. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/server.py +0 -0
  64. {pretext-2.33.1.dev20251210064446 → pretext-2.33.2}/pretext/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pretext
3
- Version: 2.33.1.dev20251210064446
3
+ Version: 2.33.2
4
4
  Summary: A package to author, build, and deploy PreTeXt projects.
5
5
  Home-page: https://pretextbook.org
6
6
  License: GPL-3.0-or-later
@@ -24,12 +24,12 @@ Requires-Dist: click-log (>=0.4,<0.5)
24
24
  Requires-Dist: coloraide (>=4,<5)
25
25
  Requires-Dist: ghp-import (>=2,<3)
26
26
  Requires-Dist: jinja2 (>=3,<4)
27
- Requires-Dist: lxml (>=5.3,<6.0)
27
+ Requires-Dist: lxml (>=6,<7)
28
28
  Requires-Dist: pdfCropMargins (>=1.0.9,<1.1.0)
29
29
  Requires-Dist: pelican[markdown] (>=4.10,<5.0) ; extra == "homepage" or extra == "all"
30
30
  Requires-Dist: plastex (>=3,<4)
31
31
  Requires-Dist: playwright (>=1,<2)
32
- Requires-Dist: prefig[text] (>=0.4.2,<0.5.0) ; extra == "prefigure" or extra == "all"
32
+ Requires-Dist: prefig[text] (>=0.4.6,<0.5.0) ; extra == "prefigure" or extra == "all"
33
33
  Requires-Dist: psutil (>=7,<8)
34
34
  Requires-Dist: pyMuPDF (>=1.24,<2.0)
35
35
  Requires-Dist: pydantic-xml (==2.14.3)
@@ -19,7 +19,7 @@ from single_version import get_version
19
19
  VERSION = get_version("pretext", Path(__file__).parent.parent)
20
20
 
21
21
 
22
- CORE_COMMIT = '1c97959297d51749717f9b34ce5da131c960b92d'
22
+ CORE_COMMIT = "1c97959297d51749717f9b34ce5da131c960b92d"
23
23
 
24
24
 
25
25
  def activate() -> None:
@@ -88,7 +88,9 @@ def map_path_to_xml_id(
88
88
  # Load the XML, performing xincludes using this loader.
89
89
  huge_parser = ET.XMLParser(huge_tree=True)
90
90
  src_tree = ET.parse(_xml, parser=huge_parser)
91
- lxml.ElementInclude.include(src_tree, loader=my_loader)
91
+ # Previously, we used the following line instead of .xinclude(), but that no longer seems to work in 6.0 lxml.
92
+ # lxml.ElementInclude.include(src_tree, loader=my_loader)
93
+ src_tree.xinclude()
92
94
 
93
95
  # Walk though every element with an xml ID. Note: the type stubs don't have the ``iterfind`` method, hence the ignore in the next line.
94
96
  for elem in src_tree.iterfind(f".//*[@{xml_id_attrib}]"): # type: ignore
@@ -128,6 +128,8 @@ class Target(pxml.BaseXmlModel, tag="target", search_mode=SearchMode.UNORDERED):
128
128
  #
129
129
  # A path to the root source for this target, relative to the project's `source` path.
130
130
  source: Path = pxml.attr(default=Path("main.ptx"))
131
+ # Cache of assembled source element.
132
+ _source_element: t.Optional[ET._Element] = None
131
133
  # A path to the publication file for this target, relative to the project's `publication` path. This is mostly validated by `post_validate`.
132
134
  publication: Path = pxml.attr(default=None)
133
135
  latex_engine: LatexEngine = pxml.attr(
@@ -368,29 +370,9 @@ class Target(pxml.BaseXmlModel, tag="target", search_mode=SearchMode.UNORDERED):
368
370
  if server.name not in self_server_names:
369
371
  self.server.append(server)
370
372
 
371
- # For the Runestone format, determine the `<document-id>`, which specifies the `output_dir`.
372
- if self.format == Format.HTML and self.platform == Platform.RUNESTONE:
373
- # We expect `d_list == ["document-id contents here"]`.
374
- d_list = self.source_element().xpath("/pretext/docinfo/document-id/text()")
375
- if isinstance(d_list, list):
376
- if len(d_list) != 1:
377
- raise ValueError(
378
- "Only one `document-id` tag is allowed in a PreTeXt document."
379
- )
380
- # NB as of 2025-04-08, we are no longer setting the output directory automatically for
381
- # Runestone targets. This must be managed by the project.ptx file or by a client script.
382
- # The commented code below is how we used to do this.
383
-
384
- # d = d_list[0]
385
- # assert isinstance(d, str)
386
- # # Use the correct number of `../` to undo the project's `output-dir`, so the output from the build is located in the correct directory of `published/document-id`.
387
- # self.output_dir = Path(
388
- # f"{'../'*len(self._project.output_dir.parents)}published/{d}"
389
- # )
390
- else:
391
- raise ValueError(
392
- "The `document-id` tag must be defined for the Runestone format."
393
- )
373
+ # NB as of 2025-04-08, we are no longer setting the output directory automatically for
374
+ # Runestone targets. This must be managed by the project.ptx file or by a client script.
375
+ # Check history here for how that was done.
394
376
 
395
377
  def source_abspath(self) -> Path:
396
378
  return self._project.source_abspath() / self.source
@@ -408,14 +390,21 @@ class Target(pxml.BaseXmlModel, tag="target", search_mode=SearchMode.UNORDERED):
408
390
  def source_element(self) -> ET._Element:
409
391
  """
410
392
  Returns the root element for the assembled source, after processing with the "version-only" assembly.
393
+ Caches the result for future calls.
411
394
  """
412
- assembled = core.assembly_internal(
413
- xml=self.source_abspath(),
414
- pub_file=self.publication_abspath().as_posix(),
415
- stringparams=self.stringparams.copy(),
416
- method="version",
417
- )
418
- return assembled.getroot()
395
+ if self._source_element is None:
396
+ log.debug(
397
+ f"Parsing source element for target {self.name}",
398
+ )
399
+ self._source_element = core.assembly_internal(
400
+ xml=self.source_abspath(),
401
+ pub_file=self.publication_abspath().as_posix(),
402
+ stringparams=self.stringparams.copy(),
403
+ method="version",
404
+ ).getroot()
405
+ else:
406
+ log.debug(f"Using cached source_element for target {self.name}")
407
+ return self._source_element
419
408
 
420
409
  def publication_abspath(self) -> Path:
421
410
  return self._project.publication_abspath() / self.publication
@@ -682,12 +671,16 @@ class Target(pxml.BaseXmlModel, tag="target", search_mode=SearchMode.UNORDERED):
682
671
  self.stringparams["cli.version"] = VERSION[: VERSION.rfind(".")]
683
672
 
684
673
  # Check for xml syntax errors and quit if xml invalid:
685
- if not utils.xml_syntax_is_valid(self.source_abspath()):
674
+ try:
675
+ # Access the source_element to trigger assembly if it hasn't been done yet.
676
+ self.source_element()
677
+ except Exception as e:
678
+ log.error(f"Error assembling source file: {e}")
686
679
  raise RuntimeError("XML syntax for source file is invalid")
687
680
  if not utils.xml_syntax_is_valid(self.publication_abspath(), "publication"):
688
681
  raise RuntimeError("XML syntax for publication file is invalid")
689
682
  # Validate xml against schema; continue with warning if invalid:
690
- utils.xml_source_validates_against_schema(self.source_abspath())
683
+ utils.xml_validates_against_schema(self.source_element())
691
684
 
692
685
  # Clean output upon request
693
686
  if clean:
@@ -503,14 +503,24 @@
503
503
  "installPandoc.sh": "410a4ef5ab8e6acb2ca06d250878e61e44e85331a9871c93bca31ea052dfd5df",
504
504
  "installSage.sh": "77b4ce12661071605ff48729ef84df1333d9e09e71e7b05e2cd6ef0fe95afa2f"
505
505
  },
506
- "2.33.1.dev20251210064446": {
507
- "project.ptx": "b7e04a13a58a300bb5c05bd43a81e558a326546827a403b7aa94408b33da47d1",
508
- "codechat_config.yaml": "25a78ee644c31ebfa8a5df42ceca3b37d8baa4a97232baee0b54d6e4252cd589",
509
- ".gitignore": "80af0856f9cbe7fd22606fa7a77b845a8303022367c955a8fb7ac9c2266db2ba",
510
- "devcontainer.json": "53f05afcaae27ec4db24c829a2d98d2785bd32d022dfaaf9a13915331750a9ff",
511
- "pretext-cli.yml": "ff4362c86ea52c5745b3d104ad95de1fe398329834612e64b8d29c142e4b246d",
512
- "pretext-deploy.yml": "4a2e574935caaba462efe09ec8e2e1b6dee19a9e7da0c34910eee7b46e5abdb2",
513
- "installPandoc.sh": "c8440c5eeefa521beae96d6484cca750d5096562315ab8ef4e55144ba94c9f93",
514
- "installSage.sh": "b4cdce1dc196a83a7937154905ae8e25fafd1265241cee28839c42cbea59c16b"
506
+ "2.33.1": {
507
+ "project.ptx": "1fcb1aa1f15f78f9e58a9fbf88922a6b938ade35b70093e1a0ef78bf69f2c38f",
508
+ "codechat_config.yaml": "0963c6d7fa76fa4b5ea2f77cc858f0cacbb34651a703fc2fa760203887b62946",
509
+ ".gitignore": "abb4cc703620c8bc7cbd85469f3934a99a880b36aa0b432b72cab404f284f697",
510
+ "devcontainer.json": "a8a60dcf33d1f266a05b535b291225eb438fa532204d261568afd25b167c7851",
511
+ "pretext-cli.yml": "b2d3f4d4026d84bdabe78947690b9a0165f9bc3b79d5cec62aa3a473a904dc41",
512
+ "pretext-deploy.yml": "031198662ff32c0c368fd8bae0a99ff540fae02598c9ca0b4f8e9ea62579acc6",
513
+ "installPandoc.sh": "3d4ee0fe164575e7f17dda651c12570f12fed3e042ca4739edd5bbfcaaec5c24",
514
+ "installSage.sh": "e9682f35f46c2faf5c062b679fd2e17d9767098022b5f10164b8c4e5439544a9"
515
+ },
516
+ "2.33.2": {
517
+ "project.ptx": "08f992b2f4b2420bf9c3002deb8b4a2be8d6fc90ce770eb5bf47437859db10f7",
518
+ "codechat_config.yaml": "78634ed0c6f14bd1df9aaf7b29c73ff0f5cae126898179381549b6d7b00cb8b5",
519
+ ".gitignore": "d62ea9ea215f605c430ffcedeb33b81e808490a94c6d30cabbbefdf3a4de1ae8",
520
+ "devcontainer.json": "94ea6ba7e57b238543d39b2997142d52792fefaf543064184485f2a851f75348",
521
+ "pretext-cli.yml": "2d6fc8ad7efbf30ce061feb5c387a89d9e9cae3663e17ece9842d50a1bf14fa2",
522
+ "pretext-deploy.yml": "fe66cd20fb2bfb52b1cf01228a99a203829691dd173b7995c317180fdfcf3f09",
523
+ "installPandoc.sh": "a18b850870b5e2d744c99300c0643f12a81eba3e27dfd985927554af2062c967",
524
+ "installSage.sh": "8020b532e1101c77c5681c0dfaff308a36c60e95db6b0f652bf230f7de216cb8"
515
525
  }
516
526
  }
@@ -12,6 +12,7 @@ import shutil
12
12
  import socketserver
13
13
  import socket
14
14
  import subprocess
15
+ import time as time
15
16
  import logging
16
17
  import logging.handlers
17
18
  import psutil
@@ -203,17 +204,13 @@ def xml_syntax_is_valid(xmlfile: Path, root_tag: str = "pretext") -> bool:
203
204
  return True
204
205
 
205
206
 
206
- def xml_source_validates_against_schema(xmlfile: Path) -> bool:
207
+ def xml_validates_against_schema(etree: _Element) -> bool:
207
208
  # get path to RelaxNG schema file:
208
209
  schemarngfile = resources.resource_base_path() / "core" / "schema" / "pretext.rng"
209
210
 
210
211
  # Open schemafile for validation:
211
212
  relaxng = ET.RelaxNG(file=schemarngfile)
212
213
 
213
- # Parse xml file:
214
- source_xml = ET.parse(xmlfile)
215
- source_xml.xinclude()
216
-
217
214
  # just for testing
218
215
  # ----------------
219
216
  # relaxng.validate(source_xml)
@@ -222,7 +219,7 @@ def xml_source_validates_against_schema(xmlfile: Path) -> bool:
222
219
 
223
220
  # validate against schema
224
221
  try:
225
- relaxng.assertValid(source_xml)
222
+ relaxng.assertValid(etree)
226
223
  log.info("PreTeXt source passed schema validation.")
227
224
  except ET.DocumentInvalid as err:
228
225
  log.debug(
@@ -1104,3 +1101,30 @@ def rs_methods(
1104
1101
  f"PTX-BUG: Format {format} not recognized for running ext_rs_methods. Something is wrong with the pretext script."
1105
1102
  )
1106
1103
  return None
1104
+
1105
+
1106
+ class Stopwatch:
1107
+ """A simple stopwatch class for measuring elapsed time."""
1108
+
1109
+ """print_log set to false disables logging of elapsed time """
1110
+
1111
+ def __init__(self, name: str = "", print_log: bool = True):
1112
+ self.name = name
1113
+ self.print_log = print_log
1114
+ self.start_time = time.time()
1115
+ self.last_log_time = self.start_time
1116
+
1117
+ def reset(self) -> None:
1118
+ """Reset the log timer to the current time."""
1119
+ self.last_log_time = time.time()
1120
+
1121
+ def log(self, timepoint_description: str = "") -> None:
1122
+ """Print a log message with the elapsed time since the last log event."""
1123
+ if self.print_log:
1124
+ cur_time = time.time()
1125
+ elapsed_time = cur_time - self.start_time
1126
+ since_last_log_time = cur_time - self.last_log_time
1127
+ self.reset()
1128
+ log.debug(
1129
+ f"** Timing report from {self.name}: {timepoint_description}, {since_last_log_time:.2f}s since last watch reset. {elapsed_time:.2f}s total elapsed time."
1130
+ )
@@ -11,7 +11,7 @@
11
11
  # ----------------
12
12
  [tool.poetry]
13
13
  name = "pretext"
14
- version = "2.33.1.dev20251210064446"
14
+ version = "2.33.2"
15
15
  description = "A package to author, build, and deploy PreTeXt projects."
16
16
  readme = "README.md"
17
17
  homepage = "https://pretextbook.org"
@@ -27,7 +27,7 @@ include = ["pretext/core/pretext.py", "pretext/core/braille_format.py", "pretext
27
27
  # ------------
28
28
  [tool.poetry.dependencies]
29
29
  python = "^3.10"
30
- lxml = "^5.3"
30
+ lxml = "^6"
31
31
  requests = "^2"
32
32
  GitPython = "^3"
33
33
  click = "^8"
@@ -45,7 +45,7 @@ plastex = "^3"
45
45
  jinja2 = "^3"
46
46
  coloraide = "^4"
47
47
  pelican = { extras = ["markdown"], version = "^4.10", optional = true }
48
- prefig = { extras = ["text"], version = "^0.4.2", optional = true }
48
+ prefig = { extras = ["text"], version = "^0.4.6", optional = true }
49
49
  citeproc-py = "^0"
50
50
 
51
51