fix: lazy load exchange excel codecs

main
NoahLan 2 weeks ago
parent 6aec02acb6
commit d3a37ce145

@ -27,7 +27,6 @@ from .schemas import (
ExchangeTemplateUpdateRequest, ExchangeTemplateUpdateRequest,
) )
from .service import ExchangeService from .service import ExchangeService
from .excel import ExcelTemplateCodec
from .sources import get_exchange_source from .sources import get_exchange_source
@ -383,7 +382,7 @@ def upload_template_version(
): ):
service = ExchangeService(request.app, db) service = ExchangeService(request.app, db)
content = file.file.read() content = file.file.read()
parsed = ExcelTemplateCodec().load(content) parsed = _excel_template_codec().load(content)
snapshot = service.publish_version( snapshot = service.publish_version(
template_id=template_id, template_id=template_id,
version=version, version=version,
@ -404,6 +403,12 @@ def upload_template_version(
return ok(ExchangeTemplateVersionResponse.model_validate(_version_payload(snapshot)).model_dump(mode="json")) return ok(ExchangeTemplateVersionResponse.model_validate(_version_payload(snapshot)).model_dump(mode="json"))
def _excel_template_codec():
from .excel import ExcelTemplateCodec
return ExcelTemplateCodec()
@router.post("/tasks") @router.post("/tasks")
def create_task( def create_task(
payload: ExchangeTaskCreateRequest, payload: ExchangeTaskCreateRequest,

@ -21,7 +21,6 @@ from .base import (
ExchangeTemplateSnapshot, ExchangeTemplateSnapshot,
ExchangeTaskKind, ExchangeTaskKind,
) )
from .excel import ExcelTemplateCodec, ExcelWorkbookCodec
from .models import ( from .models import (
ExchangeTaskModel, ExchangeTaskModel,
ExchangeTaskRowModel, ExchangeTaskRowModel,
@ -136,7 +135,7 @@ class ExchangeService:
with storage.download(version.file_key) as file_stream: with storage.download(version.file_key) as file_stream:
return file_stream.read() return file_stream.read()
snapshot = self.snapshot_from_model(version) snapshot = self.snapshot_from_model(version)
return ExcelTemplateCodec().dump(snapshot) return _excel_template_codec().dump(snapshot)
def build_plan_template_file(self, plan: ExchangePlan) -> bytes: def build_plan_template_file(self, plan: ExchangePlan) -> bytes:
if plan.version_id: if plan.version_id:
@ -145,7 +144,7 @@ class ExchangeService:
storage = get_exchange_storage(self.app) storage = get_exchange_storage(self.app)
with storage.download(version.file_key) as file_stream: with storage.download(version.file_key) as file_stream:
return file_stream.read() return file_stream.read()
return ExcelTemplateCodec().dump(plan) return _excel_template_codec().dump(plan)
def export_rows( def export_rows(
self, self,
@ -155,7 +154,7 @@ class ExchangeService:
fields: list[ExchangeField] | None = None, fields: list[ExchangeField] | None = None,
sheet_name: str | None = None, sheet_name: str | None = None,
) -> bytes: ) -> bytes:
workbook_codec = ExcelWorkbookCodec() workbook_codec = _excel_workbook_codec()
if plan is not None: if plan is not None:
return workbook_codec.export_rows_with_plan( return workbook_codec.export_rows_with_plan(
plan=plan, plan=plan,
@ -180,7 +179,7 @@ class ExchangeService:
plan: ExchangePlan | None = None, plan: ExchangePlan | None = None,
fields: list[ExchangeField] | None = None, fields: list[ExchangeField] | None = None,
) -> list[dict[str, Any]]: ) -> list[dict[str, Any]]:
workbook_codec = ExcelWorkbookCodec() workbook_codec = _excel_workbook_codec()
if plan is not None and plan.fields: if plan is not None and plan.fields:
return workbook_codec.import_rows_with_fields(content, fields=list(plan.fields)) return workbook_codec.import_rows_with_fields(content, fields=list(plan.fields))
if fields is not None: if fields is not None:
@ -501,6 +500,18 @@ def _excel_mime_type() -> str:
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
def _excel_template_codec():
from .excel import ExcelTemplateCodec
return ExcelTemplateCodec()
def _excel_workbook_codec():
from .excel import ExcelWorkbookCodec
return ExcelWorkbookCodec()
def _jsonable(value: Any) -> Any: def _jsonable(value: Any) -> Any:
if isinstance(value, Enum): if isinstance(value, Enum):
return value.value return value.value

@ -14,7 +14,6 @@ from .base import (
ExchangeTemplateSource, ExchangeTemplateSource,
ExchangeTemplateSourceKind, ExchangeTemplateSourceKind,
) )
from .excel import ExcelTemplateCodec
class ExchangeSource(Protocol): class ExchangeSource(Protocol):
@ -75,7 +74,7 @@ class MappingExchangeSource:
) )
def load_template_file(self, plan: ExchangePlan) -> bytes | None: def load_template_file(self, plan: ExchangePlan) -> bytes | None:
return ExcelTemplateCodec().dump(plan) return _excel_template_codec().dump(plan)
@dataclass @dataclass
@ -131,7 +130,7 @@ class LocalExchangeSource:
from .service import ExchangeService from .service import ExchangeService
return ExchangeService(self.app, self.db).build_template_file(plan.version_id) return ExchangeService(self.app, self.db).build_template_file(plan.version_id)
return ExcelTemplateCodec().dump(plan) return _excel_template_codec().dump(plan)
@dataclass @dataclass
@ -192,7 +191,7 @@ class RemoteExchangeSource:
def load_template_file(self, plan: ExchangePlan) -> bytes | None: def load_template_file(self, plan: ExchangePlan) -> bytes | None:
if not plan.version_id: if not plan.version_id:
return ExcelTemplateCodec().dump(plan) return _excel_template_codec().dump(plan)
client = service_client(self.app, self.service_name) client = service_client(self.app, self.service_name)
response = client.get( response = client.get(
f"/exchange/template-versions/{plan.version_id}/download", f"/exchange/template-versions/{plan.version_id}/download",
@ -259,6 +258,12 @@ def _placeholder_from_mapping(item: dict[str, Any]) -> ExchangePlaceholder:
) )
def _excel_template_codec():
from .excel import ExcelTemplateCodec
return ExcelTemplateCodec()
def get_exchange_source( def get_exchange_source(
app: Any, app: Any,
*, *,

Loading…
Cancel
Save