Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ Instructions: Add a subsection under `[Unreleased]` for additions, fixes, change

## [Unreleased]

### Added

- Improvements to Fill-In-The-Blank questions.
- Headnote element.
- Support for gdscript activecode.

### Changed

- WeBWorK javascript is no longer versioned.


## [2.47.1] - 2026-08-04

Includes updates to core through commit: [35f8d01](https://github.com/PreTeXtBook/pretext/commit/35f8d01149b0f657cd6fbd8d67865e0f6d487560)
Expand Down
2 changes: 1 addition & 1 deletion pretext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

VERSION = get_version("pretext", Path(__file__).parent.parent)

CORE_COMMIT = "35f8d01149b0f657cd6fbd8d67865e0f6d487560"
CORE_COMMIT = "6f1b557cb7aed2b86eb40187c21b56009f97ea1b"


def activate() -> None:
Expand Down
18 changes: 8 additions & 10 deletions pretext/cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import importlib
import importlib.util
import logging
import logging.handlers
import sys
import click
import click_log
Expand Down Expand Up @@ -32,7 +30,7 @@

from .project import Project

log = logging.getLogger("ptxlogger")
log = logger.log
logger.add_log_stream_handler()
error_flush_handler = logger.get_log_error_flush_handler()

Expand Down Expand Up @@ -636,7 +634,7 @@ def build(
except AssertionError as e:
log.warning("Assertion error in getting target.")
utils.show_target_hints(target_name, project, task="build")
log.critical("Exiting without completing build.")
log.exit("Exiting without completing build.")
log.debug(e, exc_info=True)
return

Expand Down Expand Up @@ -716,7 +714,7 @@ def build(
"It appears there is an error with your project.ptx or publication file. See the details below."
)
log.critical(e)
log.critical("Failed to build without errors. Exiting...")
log.exit("Failed to build without errors. Exiting...")
log.debug(
"\n------------------------\nException info:\n------------------------\n",
exc_info=True,
Expand All @@ -726,7 +724,7 @@ def build(
log.critical(e)
log.debug("Exception info:\n------------------------\n", exc_info=True)
log.info("------------------------")
log.critical("Failed to build without errors. Exiting...")
log.exit("Failed to build without errors. Exiting...")
return


Expand Down Expand Up @@ -911,7 +909,7 @@ def generate(
target = project.get_target(name=target_name)
except AssertionError as e:
utils.show_target_hints(target_name, project, task="generating assets for")
log.critical("Exiting without completing build.")
log.exit("Exiting without completing build.")
log.debug(e, exc_info=True)
return

Expand Down Expand Up @@ -940,7 +938,7 @@ def generate(
"It appears there is an error with your project.ptx or publication file. See the details below."
)
log.critical(e)
log.critical("Failed to build. Exiting...")
log.exit("Failed to build. Exiting...")
log.debug(
"\n------------------------\nException info:\n------------------------\n",
exc_info=True,
Expand All @@ -950,7 +948,7 @@ def generate(
log.critical(e)
log.debug("Exception info:\n------------------------\n", exc_info=True)
log.info("------------------------")
log.critical("Generating assets as failed. Exiting...")
log.exit("Generating assets as failed. Exiting...")
return


Expand Down Expand Up @@ -1075,7 +1073,7 @@ def view(
target = project.get_target(name=target_name, log_info_for_none=not stage)
except AssertionError as e:
utils.show_target_hints(target_name, project, task="view")
log.critical("Exiting.")
log.exit("Exiting.")
log.debug(e, exc_info=True)
return

Expand Down
29 changes: 27 additions & 2 deletions pretext/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,48 @@
import sys
import logging
import logging.handlers
from typing import Any, cast
import click_log

log = logging.getLogger("ptxlogger")
# EXIT is CLI-only: the wrap-up line a command logs right before handing off
# to `exit_command` (e.g. "Failed to build without errors. Exiting..."). It
# announces that the run is stopping; it isn't itself an error, so CRITICAL
# was too strong, and keeping it below ERROR keeps it out of
# error_flush_handler's buffer, so it isn't repeated in the flushed report.
EXIT_LEVEL = 35
logging.addLevelName(EXIT_LEVEL, "exit")


class PretextLogger(logging.Logger):
"""A `Logger` that also knows how to log at EXIT_LEVEL."""

def exit(self, message: object, *args: Any, **kwargs: Any) -> None:
self.log(EXIT_LEVEL, message, *args, **kwargs)


logging.setLoggerClass(PretextLogger)
log = cast(PretextLogger, logging.getLogger("ptxlogger"))
# Modules elsewhere (including core) fetch "ptxlogger" by name; whichever of
# them runs first decides the class. Retag the singleton so `log.exit` exists
# no matter the import order, then restore the default for everyone else.
log.__class__ = PretextLogger
logging.setLoggerClass(logging.Logger)


class ColorFormatter(click_log.ColorFormatter):
"""click_log prefixes a message with its level name, but only for the levels
in its own `colors` table; an unrecognized level gets no label at all. Core
PreTeXt renames level 50 to FATAL and adds BUG (45) and FALLBACK (25), so
those messages arrived unlabeled. Extend the table to cover them.
those messages arrived unlabeled. Extend the table to cover them, along
with the CLI's own EXIT level above.
"""

colors = {
**click_log.ColorFormatter.colors,
"fatal": dict(fg="red", bold=True),
"bug": dict(fg="magenta"),
"fallback": dict(fg="cyan"),
"exit": dict(fg="red"),
}


Expand Down