Initial commit

This commit is contained in:
tanexc
2026-06-12 23:53:39 +03:00
commit 67fd2bc5ac
32 changed files with 1107 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
class DomainError(Exception):
pass
class ModelNotFoundError(DomainError):
pass
class DuplicateModelVersionError(DomainError):
pass
class InvalidModelVersionError(DomainError):
pass
class InvalidModelFileError(DomainError):
pass
class ModelFileMissingError(DomainError):
pass
class ModelConversionError(DomainError):
pass
+12
View File
@@ -0,0 +1,12 @@
from dataclasses import dataclass
from datetime import datetime
@dataclass(slots=True)
class Model:
id: int | None
version: str
filename: str
file_path: str
created_at: datetime
is_latest: bool
+8
View File
@@ -0,0 +1,8 @@
from abc import abstractmethod, ABC
from pathlib import Path
class ModelConverter(ABC):
@abstractmethod
def convert(self, model_pt_path: Path, results_dir: Path) -> Path:
raise NotImplementedError
+17
View File
@@ -0,0 +1,17 @@
from abc import ABC, abstractmethod
from app.domain.Model import Model
class ModelRepository(ABC):
@abstractmethod
def get_latest(self) -> Model | None:
raise NotImplementedError
@abstractmethod
def get_by_version(self, version: str) -> Model | None:
raise NotImplementedError
@abstractmethod
def add(self, model: Model) -> Model:
raise NotImplementedError
+41
View File
@@ -0,0 +1,41 @@
from abc import ABC, abstractmethod
from pathlib import Path
class ModelStorage(ABC):
@property
@abstractmethod
def models_dir(self) -> Path:
raise NotImplementedError
@abstractmethod
def ensure_directories(self) -> None:
raise NotImplementedError
@abstractmethod
def validate_upload_filename(self, filename: str | None) -> str:
raise NotImplementedError
@abstractmethod
def save_upload_to_tmp(self, source_file, filename: str) -> Path:
raise NotImplementedError
@abstractmethod
def build_model_filename(self, version: str) -> str:
raise NotImplementedError
@abstractmethod
def prepare_conversion_input(self, tmp_path: Path, model_filename: str) -> Path:
raise NotImplementedError
@abstractmethod
def finalize_converted_model(self, converted_path: Path, model_filename: str) -> Path:
raise NotImplementedError
@abstractmethod
def ensure_model_file_exists(self, file_path: str) -> Path:
raise NotImplementedError
@abstractmethod
def delete_file_if_exists(self, file_path: Path | None) -> None:
raise NotImplementedError
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1,21 @@
from app.domain.ModelStorage import ModelStorage
from app.domain.Model import Model
from app.domain.Exception import ModelNotFoundError
from app.domain.ModelRepository import ModelRepository
class GetLatestModelUseCase:
def __init__(self, repository: ModelRepository, storage: ModelStorage) -> None:
self._repository = repository
self._storage = storage
def execute(self, version: str | None = None, filename: str | None = None) -> Model:
model = self._repository.get_latest()
if model is None:
raise ModelNotFoundError("No models have been uploaded yet.")
if version is not None and model.version != version:
raise ModelNotFoundError("Latest model does not match requested version.")
if filename is not None and model.filename != filename:
raise ModelNotFoundError("Latest model does not match requested filename.")
self._storage.ensure_model_file_exists(model.file_path)
return model
+74
View File
@@ -0,0 +1,74 @@
from datetime import datetime, timezone
from app.domain.Model import Model
from app.domain.Exception import *
from app.domain.ModelRepository import ModelRepository
from app.domain.ModelStorage import ModelStorage
from app.domain.ModelConverter import ModelConverter
class UploadModelUseCase:
def __init__(
self,
repository: ModelRepository,
storage: ModelStorage,
converter: ModelConverter,
) -> None:
self._repository = repository
self._storage = storage
self._converter = converter
def execute(self, version: str, upload_file) -> Model:
normalized_version = version.strip()
if not normalized_version:
raise InvalidModelVersionError("Version must not be empty.")
if self._repository.get_by_version(normalized_version) is not None:
raise DuplicateModelVersionError(f"Model version '{normalized_version}' already exists.")
safe_filename = self._storage.validate_upload_filename(upload_file.filename)
tmp_path = self._storage.save_upload_to_tmp(upload_file.file, safe_filename)
conversion_input_path = None
final_model_path = None
try:
model_filename = self._storage.build_model_filename(normalized_version)
conversion_input_path = self._storage.prepare_conversion_input(
tmp_path=tmp_path,
model_filename=model_filename,
)
converted_path = self._converter.convert(
model_pt_path=conversion_input_path,
results_dir=self._storage.models_dir,
)
final_model_path = self._storage.finalize_converted_model(
converted_path=converted_path,
model_filename=model_filename,
)
model = self._repository.add(
Model(
id=None,
version=normalized_version,
filename=model_filename,
file_path=str(final_model_path),
created_at=datetime.now(timezone.utc),
is_latest=True,
)
)
return model
except Exception as exc:
self._storage.delete_file_if_exists(final_model_path)
if isinstance(
exc,
(
InvalidModelVersionError,
DuplicateModelVersionError,
ModelNotFoundError,
),
):
raise
raise ModelConversionError(f"Model conversion failed: {exc}") from exc
finally:
upload_file.file.close()
self._storage.delete_file_if_exists(tmp_path)
self._storage.delete_file_if_exists(conversion_input_path)
View File