Source code for ocrd_network.resource_manager_server

from datetime import datetime
from os import getpid
from shutil import which
from typing import Any
from uvicorn import run as uvicorn_run
from fastapi import APIRouter, FastAPI, HTTPException, status

from ocrd import OcrdResourceManager
from ocrd_utils import getLogger, get_ocrd_tool_json, initLogging
from .logging_utils import configure_file_handler_with_formatter, get_resource_manager_server_logging_file_path


[docs] class ResourceManagerServer(FastAPI): def __init__(self, host: str, port: int) -> None: self.title = f"OCR-D Resource Manager Server" super().__init__( title=self.title, on_startup=[self.on_startup], on_shutdown=[self.on_shutdown], description=self.title ) initLogging() self.log = getLogger("ocrd_network.resource_manager_server") log_file = get_resource_manager_server_logging_file_path(pid=getpid()) configure_file_handler_with_formatter(self.log, log_file=log_file, mode="a") self.resmgr_instance = OcrdResourceManager() self.hostname = host self.port = port self.add_api_routes()
[docs] def start(self): uvicorn_run(self, host=self.hostname, port=int(self.port))
[docs] async def on_startup(self): self.log.info(f"Starting {self.title}") pass
[docs] async def on_shutdown(self) -> None: pass
[docs] def add_api_routes(self): base_router = APIRouter() base_router.add_api_route( path="/", endpoint=self.home_page, methods=["GET"], status_code=status.HTTP_200_OK, summary="Get information about the OCR-D Resource Manager Server" ) base_router.add_api_route( path="/list_available", endpoint=self.list_available_resources, methods=["GET"], status_code=status.HTTP_200_OK, summary="" ) base_router.add_api_route( path="/list_installed", endpoint=self.list_installed_resources, methods=["GET"], status_code=status.HTTP_200_OK, summary="" ) base_router.add_api_route( path="/download", endpoint=self.download_resource, methods=["GET"], status_code=status.HTTP_200_OK, summary="" ) self.include_router(base_router)
[docs] async def home_page(self): message = f"The home page of the {self.title}" json_message = { "message": message, "time": datetime.now().strftime("%Y-%m-%d %H:%M") } return json_message
[docs] async def list_available_resources( self, executable: Any = "ocrd-dummy", dynamic: bool = True, name: Any = None, database: Any = None, url: Any = None ): if executable == '*': message = f"'*' is not an acceptable executable name! Try with a specific executable." self.log.error(message) raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=message) result = self.resmgr_instance.list_available(executable, dynamic, name, database, url) json_message = { "result": result } return json_message
[docs] async def list_installed_resources(self, executable: Any = None): if executable == '*': message = f"'*' is not an acceptable executable name! Try with a specific executable." self.log.error(message) raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=message) result = self.resmgr_instance.list_available(executable) json_message = { "result": result } return json_message
[docs] async def download_resource( self, executable: str = "ocrd-dummy", name: Any = None, location: Any = None, any_url: str = '', no_dynamic: bool = False, resource_type: str = 'file', path_in_archive: str = '.', allow_uninstalled: bool = True, overwrite: bool = True ): resmgr = OcrdResourceManager() response = [] if executable == '*': message = f"'*' is not an acceptable executable name! Try with a specific executable." self.log.error(message) raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=message) if name == '*': name = None if executable and not which(executable): if not allow_uninstalled: message = (f"Executable '{executable}' is not installed. To download resources anyway, " f"use the -a/--allow-uninstalled flag") self.log.error(message) raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=message) else: message = f"Executable '{executable}' is not installed, but downloading resources anyway." self.log.info(message) response.append(message) reslist = resmgr.list_available(executable=executable, dynamic=not no_dynamic, name=name) if not any(r[1] for r in reslist): message = f"No resources {name} found in registry for executable {executable}" self.log.info(message) response.append(message) if executable and name: reslist = [(executable, [{ 'url': any_url or '???', 'name': name, 'type': resource_type, 'path_in_archive': path_in_archive}] )] for this_executable, this_reslist in reslist: resource_locations = get_ocrd_tool_json(this_executable)['resource_locations'] if not location: location = resource_locations[0] elif location not in resource_locations: response.append( f"The selected --location {location} is not in the {this_executable}'s resource search path, " f"refusing to install to invalid location. Instead installing to: {resource_locations[0]}") res_dest_dir = resmgr.build_resource_dest_dir(location=location, executable=this_executable) for res_dict in this_reslist: try: fpath = resmgr.handle_resource( res_dict=res_dict, executable=this_executable, dest_dir=res_dest_dir, any_url=any_url, overwrite=overwrite, resource_type=resource_type, path_in_archive=path_in_archive ) if not fpath: continue except FileExistsError as exc: response.append(str(exc)) usage = res_dict.get('parameter_usage', 'as-is') response.append(f"Use in parameters as '{resmgr.parameter_usage(res_dict['name'], usage)}'") json_message = { "result": response } return json_message