diff --git a/acacore/__version__.py b/acacore/__version__.py index 159d48b..0309ae2 100644 --- a/acacore/__version__.py +++ b/acacore/__version__.py @@ -1 +1 @@ -__version__ = "2.0.1" +__version__ = "2.0.2" diff --git a/acacore/database/column.py b/acacore/database/column.py index 142396d..41d4eb0 100644 --- a/acacore/database/column.py +++ b/acacore/database/column.py @@ -248,14 +248,21 @@ def _schema_to_column(name: str, schema: dict, defs: dict[str, dict] | None = No to_entry, from_entry = schema["enum"][0].__class__ if schema["enum"] else str, str elif schema_type in ("object", "array"): sql_type = "text" - to_entry, from_entry = lambda o: dumps(dump_object(o), default=str), lambda o: loads(o) + to_entry, from_entry = ( + lambda o: None if o is None else dumps(dump_object(o), default=str), + lambda o: None if o is None else loads(o), + ) elif type_name in _sql_schema_type_converters: to_entry, from_entry = _sql_schema_type_converters[type_name] else: raise TypeError(f"Cannot recognize type from schema {schema!r}") elif schema_any_of: if not schema_any_of[0] or len(schema_any_of) > 2: - sql_type, to_entry, from_entry = "text", lambda o: dumps(dump_object(o), default=str), lambda x: loads(x) + sql_type, to_entry, from_entry = ( + "text", + lambda x: None if x is None else dumps(dump_object(x), default=str), + lambda x: None if x is None else loads(x), + ) else: return _schema_to_column(name, {**schema_any_of[0], **schema}, defs) else: diff --git a/acacore/database/files_db.py b/acacore/database/files_db.py index 4fb0d6a..f327e3b 100644 --- a/acacore/database/files_db.py +++ b/acacore/database/files_db.py @@ -102,7 +102,8 @@ def __init__( "_IdentificationWarnings", self.files, self.files.model, - f'"{self.files.name}".warning is not null or "{self.files.name}".puid is NULL', + f'("{self.files.name}".warning is not null or "{self.files.name}".puid is null)' + f' and "{self.files.name}".size != 0', ) self.checksum_count = self.create_view( "_ChecksumCount", diff --git a/acacore/database/upgrade.py b/acacore/database/upgrade.py index 475ab0e..0b43184 100644 --- a/acacore/database/upgrade.py +++ b/acacore/database/upgrade.py @@ -28,6 +28,8 @@ def set_db_version(db: FileDB, version: Version) -> Version: def get_upgrade_function(current_version: Version, latest_version: Version) -> Callable[[FileDB], Version]: if current_version < Version("2.0.0"): return upgrade_1to2 + elif current_version < Version("2.0.2"): + return upgrade_2to2_0_2 elif current_version < latest_version: return upgrade_last else: @@ -40,11 +42,23 @@ def upgrade_1to2(db: FileDB) -> Version: db.execute("alter table Files add column lock boolean default false") db.execute("update Files set lock = false where lock is null") db.execute("update Files set action = 'template' where action = 'replace'") + db.execute("update Files set action_data = '{}' where action_data is null") + + db.execute("drop view if exists _IdentificationWarnings") + db.identification_warnings.create() + for file in db.files.select(): db.files.update(file) + return set_db_version(db, Version("2.0.0")) +def upgrade_2to2_0_2(db: FileDB) -> Version: + db.execute("drop view if exists _IdentificationWarnings") + db.identification_warnings.create() + return set_db_version(db, Version("2.0.2")) + + def upgrade_last(db: FileDB) -> Version: db.init() return set_db_version(db, Version(__version__)) diff --git a/acacore/models/file.py b/acacore/models/file.py index bd8d6e8..7009f36 100644 --- a/acacore/models/file.py +++ b/acacore/models/file.py @@ -276,6 +276,13 @@ def get_action( action: Action | None = reduce(lambda acc, cur: acc or actions.get(cur), identifiers, None) + if action and action.alternatives and (new_puid := action.alternatives.get(self.suffix.lower(), None)): + puid: str = self.puid + self.puid = new_puid + if new_action := self.get_action(actions, file_classes, set_match=set_match): + return new_action + self.puid = puid + if set_match: self.action, self.action_data = ( action.action if action else None, diff --git a/acacore/models/reference_files.py b/acacore/models/reference_files.py index 314ef38..2021cd2 100644 --- a/acacore/models/reference_files.py +++ b/acacore/models/reference_files.py @@ -6,6 +6,7 @@ from pydantic import AliasChoices from pydantic import BaseModel from pydantic import Field +from pydantic import field_validator from .base import NoDefaultsModel @@ -208,8 +209,20 @@ class Action(ActionData): name: str description: str | None = None + alternatives: dict[str, str] = Field(default_factory=dict) action: TActionType - ignore_warnings: list[str] = Field(default_factory=list, alias="ignore-warnings") + ignore_warnings: list[str] = Field( + default_factory=list, + validation_alias=AliasChoices("ignore_warnings", "ignore-warnings"), + ) + + # noinspection PyNestedDecorators + @field_validator("alternatives", mode="before") + @classmethod + def _validate_alternatives(cls, value: dict[str, str]) -> dict[str, str]: + if not isinstance(value, dict): + raise ValueError("Is not a dictionary.") + return {k.lower(): v for k, v in value.items()} @property def action_data(self) -> ActionData: diff --git a/pyproject.toml b/pyproject.toml index c6c1496..9898795 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "acacore" -version = "2.0.1" +version = "2.0.2" description = "" authors = ["Matteo Campinoti "] license = "GPL-3.0" @@ -101,6 +101,7 @@ ignore = [ "PT012", # ptest.raises should contain a simple statement "RET505", # unnecessary {branch} after return statement "S101", # use of assert, + "SIM118", # Use `key in dict` instead of `key in dict.keys()` "TRY003", # avoid using long messages outside exception class "UP007", # not using | in type anotations "INP001", # implicit namespace without __init__ (throws errors in tests)