diff --git a/bioimageio_collection_backoffice/_backoffice.py b/bioimageio_collection_backoffice/_backoffice.py index bea001a0..ed4dfee3 100644 --- a/bioimageio_collection_backoffice/_backoffice.py +++ b/bioimageio_collection_backoffice/_backoffice.py @@ -11,7 +11,7 @@ from ._settings import settings from .backup import backup from .db_structure.chat import Chat, Message -from .db_structure.log import Log, LogContent, LogEntry +from .db_structure.log import Log, LogEntry from .gh_utils import set_gh_actions_outputs from .mailroom.send_email import notify_uploader from .remote_collection import ( @@ -46,14 +46,7 @@ def log(self, message: str, concept_id: str, version: str): raise ValueError("'RUN_URL' not set") rv = get_remote_resource_version(self.client, concept_id, version) - - rv.extend_log( - Log( - collection=[ - LogEntry(log=LogContent(message=message, run_url=settings.run_url)) - ] - ) - ) + rv.extend_log(Log(entries=[LogEntry(message=message)])) def wipe(self, subfolder: str = ""): """DANGER ZONE: wipes `subfolder` completely, only use for test folders!""" diff --git a/bioimageio_collection_backoffice/db_structure/log.py b/bioimageio_collection_backoffice/db_structure/log.py index d67a53e6..32fe088a 100644 --- a/bioimageio_collection_backoffice/db_structure/log.py +++ b/bioimageio_collection_backoffice/db_structure/log.py @@ -1,8 +1,7 @@ from __future__ import annotations -import collections.abc from datetime import datetime -from typing import Any, ClassVar, Dict, Optional, Sequence, Union +from typing import Any, ClassVar, Optional, Sequence from pydantic import Field @@ -10,36 +9,33 @@ from ..common import Node -class LogContent(Node, frozen=True, extra="ignore"): +class LogEntry(Node, frozen=True, extra="ignore"): message: str = "" - details: Any = None - run_url: Optional[str] = settings.run_url + """log message""" + details: Any = None + """log details""" -class LogEntry(Node, frozen=True, extra="ignore"): timestamp: datetime = Field(default_factory=datetime.now) """creation of log entry""" - log: LogContent - """log content""" + run_url: Optional[str] = settings.run_url + """gh action run url""" -class Log(Node, frozen=True, extra="allow"): +class Log(Node, frozen=True, extra="ignore"): """`//log.json` contains a version specific log""" file_name: ClassVar[str] = "log.json" - bioimageio_spec: Sequence[LogEntry] = Field(default_factory=list) - bioimageio_core: Sequence[LogEntry] = Field(default_factory=list) - collection: Sequence[LogEntry] = Field(default_factory=list) + log_version: str = "0.1.0" + entries: Sequence[LogEntry] = Field(default_factory=list) def get_updated(self, update: Log) -> Log: - v: Union[Any, Sequence[Any]] - data: Dict[str, Sequence[Any]] = {} - for k, v in update: - assert isinstance(v, collections.abc.Sequence) - old = getattr(self, k, ()) - assert isinstance(old, collections.abc.Sequence) - data[k] = list(old) + list(v) - - return Log.model_validate(data) + if update.log_version != self.log_version: + return update + + return Log( + log_version=update.log_version, + entries=list(self.entries) + list(update.entries), + ) diff --git a/bioimageio_collection_backoffice/remote_base.py b/bioimageio_collection_backoffice/remote_base.py index c7c24ac7..3263e722 100644 --- a/bioimageio_collection_backoffice/remote_base.py +++ b/bioimageio_collection_backoffice/remote_base.py @@ -6,7 +6,7 @@ from loguru import logger from .db_structure.chat import Chat -from .db_structure.log import CollectionLog, Log, LogContent +from .db_structure.log import Log, LogEntry from .db_structure.reserved import Reserved from .db_structure.version_info import DraftInfo, RecordInfo from .s3_client import Client @@ -48,13 +48,7 @@ def log(self) -> Log: return self._get_json(Log) def log_message(self, message: str, details: Optional[Any] = None): - self._update_json( - Log( - collection=[ - CollectionLog(log=LogContent(message=message, details=details)) - ] - ) - ) + self._update_json(Log(entries=[LogEntry(message=message, details=details)])) def log_error(self, error: Union[Exception, str], details: Optional[Any] = None): if isinstance(error, Exception): @@ -66,10 +60,4 @@ def log_error(self, error: Union[Exception, str], details: Optional[Any] = None) if isinstance(details, dict) and "traceback" not in details: details["traceback"] = traceback.format_stack() - self._update_json( - Log( - collection=[ - CollectionLog(log=LogContent(message=error, details=details)) - ] - ) - ) + self._update_json(Log(entries=[LogEntry(message=error, details=details)])) diff --git a/bioimageio_collection_backoffice/remote_collection.py b/bioimageio_collection_backoffice/remote_collection.py index 41a91169..4fcab1d7 100644 --- a/bioimageio_collection_backoffice/remote_collection.py +++ b/bioimageio_collection_backoffice/remote_collection.py @@ -53,7 +53,7 @@ TestSummary, TestSummaryEntry, ) -from .db_structure.log import Log, LogContent, LogEntry +from .db_structure.log import Log, LogEntry from .db_structure.reserved import Reserved from .db_structure.version_info import ( AcceptedStatus, @@ -560,6 +560,10 @@ def rdf_url(self) -> str: def chat(self) -> Chat: return self._get_json(Chat) + def add_log_entry(self, log_entry: LogEntry): + """add a log entry""" + self.extend_log(Log(entries=[log_entry])) + def extend_log( self, extension: Log, @@ -641,16 +645,10 @@ def unpack(self, package_url: str): # ensure we have a chat.json self.extend_chat(Chat()) - self.extend_log( - Log( - collection=[ - LogEntry( - log=LogContent( - message="new status: unpacking", - details={"package_url": package_url}, - ) - ) - ] + self.add_log_entry( + LogEntry( + message="new status: unpacking", + details={"package_url": package_url}, ) ) @@ -697,15 +695,9 @@ def unpack(self, package_url: str): for e in collection["collection"]: if e["name"] == rdf["name"]: if e["id"] != rdf["id"]: - self.extend_log( - Log( - collection=[ - LogEntry( - log=LogContent( - message=f"error: Another resource with name='{rdf['name']}' already exists ({e['id']})" - ) - ) - ] + self.add_log_entry( + LogEntry( + message=f"error: Another resource with name='{rdf['name']}' already exists ({e['id']})" ) ) break @@ -713,16 +705,8 @@ def unpack(self, package_url: str): # set matching id_emoji rdf["id_emoji"] = self.collection.config.id_parts.get_icon(self.id) if rdf["id_emoji"] is None: - self.extend_log( - Log( - collection=[ - LogEntry( - log=LogContent( - message=f"error: Failed to get icon for {self.id}" - ) - ) - ] - ) + self.add_log_entry( + LogEntry(message=f"error: Failed to get icon for {self.id}") ) if "id" not in rdf: @@ -880,16 +864,8 @@ def publish(self, reviewer: str) -> Record: def _set_status(self, value: DraftStatus): current_status = self.info.status - self.extend_log( - Log( - collection=[ - LogEntry( - log=LogContent( - message=f"set new status: {value.name}", details=value - ) - ) - ] - ) + self.add_log_entry( + LogEntry(message=f"new status: {value.description}", details=value) ) if value.name == "testing" or current_status is None: pass diff --git a/bioimageio_collection_backoffice/run_dynamic_tests.py b/bioimageio_collection_backoffice/run_dynamic_tests.py index 4b132059..a1bb2bc4 100644 --- a/bioimageio_collection_backoffice/run_dynamic_tests.py +++ b/bioimageio_collection_backoffice/run_dynamic_tests.py @@ -14,7 +14,7 @@ CompatiblityReport, ) -from .db_structure.log import Log, LogContent, LogEntry +from .db_structure.log import LogEntry from .remote_collection import Record, RecordDraft try: @@ -53,13 +53,7 @@ def run_dynamic_tests( ) summary = _run_dynamic_tests_impl(staged.rdf_url, weight_format, create_env_outcome) if summary is not None: - staged.extend_log( - Log( - bioimageio_core=[ - LogEntry(log=LogContent(message=summary.name, details=summary)) - ] - ) - ) + staged.add_log_entry(LogEntry(message=summary.name, details=summary)) def rerun_dynamic_tests( @@ -71,13 +65,7 @@ def rerun_dynamic_tests( published.rdf_url, weight_format, create_env_outcome ) if summary is not None: - published.extend_log( - Log( - bioimageio_core=[ - LogEntry(log=LogContent(message=summary.name, details=summary)) - ] - ) - ) + published.add_log_entry(LogEntry(message=summary.name, details=summary)) report = CompatiblityReport( tool="bioimageio.core", status=summary.status, diff --git a/bioimageio_collection_backoffice/validate_format.py b/bioimageio_collection_backoffice/validate_format.py index fef55605..d452a04d 100644 --- a/bioimageio_collection_backoffice/validate_format.py +++ b/bioimageio_collection_backoffice/validate_format.py @@ -10,7 +10,7 @@ from ruyaml import YAML from typing_extensions import assert_never -from .db_structure.log import Log, LogContent, LogEntry +from .db_structure.log import LogEntry from .remote_collection import Record, RecordDraft yaml = YAML(typ="safe") @@ -319,16 +319,10 @@ def validate_format(rv: Union[RecordDraft, Record]): ) ) - rv.extend_log( - Log( - bioimageio_spec=[ - LogEntry( - log=LogContent( - message=rd.validation_summary.name, - details=rd.validation_summary, - ) - ) - ] + rv.add_log_entry( + LogEntry( + message=rd.validation_summary.name, + details=rd.validation_summary, ) ) return dynamic_test_cases, conda_envs