from core.Constants import Constants from core.models.Model import Model from dataclasses import dataclass, field from dataclasses_json import config, Exclude from datetime import datetime from dateutil.parser import isoparse from marshmallow import fields from typing import Optional import os _table_name: str = 'application_versions' _table_definition: str = """ 'id' int UNIQUE, 'application_code' varchar, 'version_number' varchar, 'format_revision' int, 'download_path' varchar UNIQUE, 'released_at' varchar, 'file_hash' varchar, UNIQUE(application_code, version_number) """ @dataclass class ApplicationVersion(Model): application_code: str version_number: str format_revision: Optional[int] = field( default=None, metadata=config(exclude=Exclude.ALWAYS) ) id: Optional[int] = field( default=None, metadata=config(exclude=Exclude.ALWAYS) ) download_path: Optional[str] = field( default=None, metadata=config(exclude=Exclude.ALWAYS) ) released_at: Optional[datetime] = field( default=None, metadata=config( encoder=datetime.isoformat, decoder=datetime.fromisoformat, mm_field=fields.DateTime(format='iso'), exclude=Exclude.ALWAYS ) ) file_hash: Optional[str] = field( default=None, metadata=config(exclude=Exclude.ALWAYS) ) installation_path: Optional[str] = field( default=None, metadata=config(exclude=Exclude.ALWAYS) ) def __post_init__(self): self.installation_path = f'{Constants.SP_APPLICATION_DATA_HOME}/{self.application_code}/{self.version_number}' def is_installed(self): return os.path.isdir(self.installation_path) and len(os.listdir(self.installation_path)) > 0 def is_supported(self): return self.exists(self.application_code, self.version_number) and self.format_revision == 1 @staticmethod def find_by_id(id: int): Model._create_table_if_not_exists(table_name=_table_name, table_definition=_table_definition) return Model._query_one('SELECT * FROM application_versions WHERE id = ? LIMIT 1', ApplicationVersion.factory, [id]) @staticmethod def find(application_code: str, version_number: str): Model._create_table_if_not_exists(table_name=_table_name, table_definition=_table_definition) return Model._query_one('SELECT * FROM application_versions WHERE application_code = ? AND version_number = ? LIMIT 1', ApplicationVersion.factory, [application_code, version_number]) @staticmethod def exists(application_code: str, version_number: str): Model._create_table_if_not_exists(table_name=_table_name, table_definition=_table_definition) return Model._query_exists('SELECT * FROM application_versions WHERE application_code = ? AND version_number = ?', [application_code, version_number]) @staticmethod def truncate(): Model._create_table_if_not_exists(table_name=_table_name, table_definition=_table_definition, drop_existing=True) @staticmethod def save_many(application_versions): Model._create_table_if_not_exists(table_name=_table_name, table_definition=_table_definition) Model._insert_many('INSERT INTO application_versions VALUES(?, ?, ?, ?, ?, ?, ?)', ApplicationVersion.tuple_factory, application_versions) @staticmethod def factory(cursor, row): database_fields = [column[0] for column in cursor.description] application_version = ApplicationVersion(**{key: value for key, value in zip(database_fields, row)}) application_version.released_at = isoparse(str(application_version.released_at)) return application_version @staticmethod def tuple_factory(application_version): return application_version.id, application_version.application_code, application_version.version_number, application_version.format_revision, application_version.download_path, application_version.released_at, application_version.file_hash