make python app load a bit eariler, making startup a bit faster

This commit is contained in:
Alex Bezdieniezhnykh
2025-02-13 18:13:15 +02:00
parent e329e5bb67
commit cfd5483a18
31 changed files with 183 additions and 124 deletions
+5 -2
View File
@@ -1,7 +1,10 @@
from user cimport User
from credentials cimport Credentials
from file_data cimport FileData
cdef class ApiClient:
cdef str email, password, token, folder, token_file, api_url
cdef public Credentials credentials
cdef str token, folder, api_url
cdef User user
cdef get_encryption_key(self, str hardware_hash)
@@ -9,7 +12,7 @@ cdef class ApiClient:
cdef set_token(self, str token)
cdef get_user(self)
cdef load_bytes(self, str filename)
cdef load_bytes(self, FileData file_data)
cdef load_ai_model(self)
cdef load_queue_config(self)
+12 -19
View File
@@ -9,33 +9,25 @@ from hardware_service cimport HardwareService, HardwareInfo
from security cimport Security
from io import BytesIO
from user cimport User, RoleEnum
from file_data cimport FileData
cdef class ApiClient:
"""Handles API authentication and downloading of the AI model."""
def __init__(self, str email, str password, str folder):
self.email = email
self.password = password
self.folder = folder
def __init__(self):
self.credentials = None
self.user = None
if os.path.exists(<str>constants.TOKEN_FILE):
with open(<str>constants.TOKEN_FILE, "r") as file:
self.set_token(<str>file.read().strip())
else:
self.token = None
self.token = None
cdef get_encryption_key(self, str hardware_hash):
cdef str key = f'{self.email}-{self.password}-{hardware_hash}-#%@AzaionKey@%#---'
cdef str key = f'{self.credentials.email}-{self.credentials.password}-{hardware_hash}-#%@AzaionKey@%#---'
return Security.calc_hash(key)
cdef login(self):
response = requests.post(f"{constants.API_URL}/login",
json={"email": self.email, "password": self.password})
json={"email": self.credentials.email, "password": self.credentials.password})
response.raise_for_status()
token = response.json()["token"]
self.set_token(token)
with open(<str>constants.TOKEN_FILE, 'w') as file:
file.write(token)
cdef set_token(self, str token):
self.token = token
@@ -68,14 +60,15 @@ cdef class ApiClient:
self.login()
return self.user
cdef load_bytes(self, str filename):
cdef load_bytes(self, FileData file_data):
folder = file_data.folder or self.credentials.folder
hardware_service = HardwareService()
cdef HardwareInfo hardware = hardware_service.get_hardware_info()
if self.token is None:
self.login()
url = f"{constants.API_URL}/resources/get/{self.folder}"
url = f"{constants.API_URL}/resources/get/{folder}"
headers = {
"Authorization": f"Bearer {self.token}",
"Content-Type": "application/json"
@@ -83,9 +76,9 @@ cdef class ApiClient:
payload = json.dumps(
{
"password": self.password,
"password": self.credentials.password,
"hardware": hardware.to_json_object(),
"fileName": filename
"fileName": file_data.filename
}, indent=4)
response = requests.post(url, data=payload, headers=headers, stream=True)
@@ -104,7 +97,7 @@ cdef class ApiClient:
stream = BytesIO(response.raw.read())
data = Security.decrypt_to(stream, key)
print(f'loaded file: {filename}, {len(data)} bytes')
print(f'loaded file: {file_data.filename}, {len(data)} bytes')
return data
cdef load_ai_model(self):
+4 -2
View File
@@ -7,13 +7,15 @@ pyinstaller --onefile ^
--collect-all cryptography ^
--collect-all cv2 ^
--collect-all onnxruntime ^
--hidden-import constants ^
--hidden-import annotation ^
--hidden-import credentials ^
--hidden-import file_data ^
--hidden-import user ^
--hidden-import security ^
--hidden-import secure_model ^
--hidden-import api_client ^
--hidden-import hardware_service ^
--hidden-import constants ^
--hidden-import annotation ^
--hidden-import remote_command ^
--hidden-import ai_config ^
--hidden-import inference ^
-1
View File
@@ -5,7 +5,6 @@ cdef str COMMANDS_QUEUE # Name of the commands queue in rabbit
cdef str ANNOTATIONS_QUEUE # Name of the annotations queue in rabbit
cdef str API_URL # Base URL for the external API
cdef str TOKEN_FILE # Name of the token file where temporary token would be stored
cdef str QUEUE_CONFIG_FILENAME # queue config filename to load from api
cdef str AI_MODEL_FILE # AI Model file
-1
View File
@@ -5,7 +5,6 @@ cdef str COMMANDS_QUEUE = "azaion-commands"
cdef str ANNOTATIONS_QUEUE = "azaion-annotations"
cdef str API_URL = "https://api.azaion.com" # Base URL for the external API
cdef str TOKEN_FILE = "token"
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
cdef str AI_MODEL_FILE = "azaion.onnx"
+7
View File
@@ -0,0 +1,7 @@
cdef class Credentials:
cdef public str email
cdef public str password
cdef public str folder
@staticmethod
cdef from_msgpack(bytes data)
+17
View File
@@ -0,0 +1,17 @@
from msgpack import unpackb
cdef class Credentials:
def __init__(self, str email, str password, str folder):
self.email = email
self.password = password
self.folder = folder
@staticmethod
cdef from_msgpack(bytes data):
unpacked = unpackb(data, strict_map_key=False)
return Credentials(
unpacked.get("Email"),
unpacked.get("Password"),
unpacked.get("Folder"))
+6
View File
@@ -0,0 +1,6 @@
cdef class FileData:
cdef public str folder
cdef public str filename
@staticmethod
cdef from_msgpack(bytes data)
+14
View File
@@ -0,0 +1,14 @@
from msgpack import unpackb
cdef class FileData:
def __init__(self, str folder, str filename):
self.folder = folder
self.filename = filename
@staticmethod
cdef from_msgpack(bytes data):
unpacked = unpackb(data, strict_map_key=False)
return FileData(
unpacked.get("Folder"),
unpacked.get("Filename"))
+15 -15
View File
@@ -9,16 +9,10 @@ from annotation cimport Annotation
from inference cimport Inference
from remote_command cimport RemoteCommand, CommandType
from remote_command_handler cimport RemoteCommandHandler
from credentials cimport Credentials
from file_data cimport FileData
from user cimport User
cdef class ParsedArguments:
cdef str email, password, folder;
def __init__(self, str email, str password, str folder):
self.email = email
self.password = password
self.folder = folder
cdef class CommandProcessor:
cdef ApiClient api_client
cdef RemoteCommandHandler remote_handler
@@ -26,8 +20,8 @@ cdef class CommandProcessor:
cdef bint running
cdef Inference inference
def __init__(self, args: ParsedArguments):
self.api_client = ApiClient(args.email, args.password, args.folder)
def __init__(self):
self.api_client = ApiClient()
self.remote_handler = RemoteCommandHandler(self.on_command)
self.inference_queue = Queue(maxsize=constants.QUEUE_MAXSIZE)
self.remote_handler.start()
@@ -49,11 +43,10 @@ cdef class CommandProcessor:
cdef on_command(self, RemoteCommand command):
try:
if command.command_type == CommandType.GET_USER:
self.get_user(command, self.api_client.get_user())
if command.command_type == CommandType.LOGIN:
self.login(command)
elif command.command_type == CommandType.LOAD:
response = self.api_client.load_bytes(command.filename)
self.remote_handler.send(command.client_id, response)
self.load_file(command)
elif command.command_type == CommandType.INFERENCE:
self.inference_queue.put(command)
elif command.command_type == CommandType.STOP_INFERENCE:
@@ -66,9 +59,16 @@ cdef class CommandProcessor:
except Exception as e:
print(f"Error handling client: {e}")
cdef get_user(self, RemoteCommand command, User user):
cdef login(self, RemoteCommand command):
cdef User user
self.api_client.credentials = Credentials.from_msgpack(command.data)
user = self.api_client.get_user()
self.remote_handler.send(command.client_id, user.serialize())
cdef load_file(self, RemoteCommand command):
response = self.api_client.load_bytes(FileData.from_msgpack(command.data))
self.remote_handler.send(command.client_id, response)
cdef on_annotation(self, RemoteCommand cmd, Annotation annotation):
data = annotation.serialize()
self.remote_handler.send(cmd.client_id, data)
+1 -2
View File
@@ -1,5 +1,5 @@
cdef enum CommandType:
GET_USER = 10
LOGIN = 10
LOAD = 20
INFERENCE = 30
STOP_INFERENCE = 40
@@ -8,7 +8,6 @@ cdef enum CommandType:
cdef class RemoteCommand:
cdef public bytes client_id
cdef CommandType command_type
cdef str filename
cdef bytes data
@staticmethod
+4 -5
View File
@@ -1,23 +1,22 @@
import msgpack
cdef class RemoteCommand:
def __init__(self, CommandType command_type, str filename, bytes data):
def __init__(self, CommandType command_type, bytes data):
self.command_type = command_type
self.filename = filename
self.data = data
def __str__(self):
command_type_names = {
10: "GET_USER",
10: "LOGIN",
20: "LOAD",
30: "INFERENCE",
40: "STOP_INFERENCE",
100: "EXIT"
}
data_str = f'. Data: {len(self.data)} bytes' if self.data else ''
return f'{command_type_names[self.command_type]}: {self.filename}{data_str}'
return f'{command_type_names[self.command_type]}: {data_str}'
@staticmethod
cdef from_msgpack(bytes data):
unpacked = msgpack.unpackb(data, strict_map_key=False)
return RemoteCommand(unpacked.get("CommandType"), unpacked.get("Filename"), unpacked.get("Data"))
return RemoteCommand(unpacked.get("CommandType"), unpacked.get("Data"))
+2
View File
@@ -5,6 +5,8 @@ import numpy as np
extensions = [
Extension('constants', ['constants.pyx']),
Extension('annotation', ['annotation.pyx']),
Extension('credentials', ['credentials.pyx']),
Extension('file_data', ['file_data.pyx']),
Extension('security', ['security.pyx']),
Extension('hardware_service', ['hardware_service.pyx'], extra_compile_args=["-g"], extra_link_args=["-g"]),
Extension('remote_command', ['remote_command.pyx']),
+5 -14
View File
@@ -1,22 +1,13 @@
import argparse
from main import ParsedArguments, CommandProcessor
from main import CommandProcessor
def parse_arguments():
parser = argparse.ArgumentParser(description="Command Processor")
parser.add_argument("-e", "--email", type=str, default="", help="Email")
parser.add_argument("-p", "--pw", type=str, default="", help="Password")
parser.add_argument("-f", "--folder", type=str, default="", help="Folder to API inner folder to download file from")
args = parser.parse_args()
return ParsedArguments(args.email, args.pw, args.folder)
def start(args: ParsedArguments):
processor = CommandProcessor(args)
def start():
processor = CommandProcessor()
try:
processor.start()
except KeyboardInterrupt:
processor.stop()
if __name__ == '__main__':
start(parse_arguments())
start()
+1 -1
View File
@@ -3,7 +3,7 @@ from PyInstaller.utils.hooks import collect_all
datas = []
binaries = []
hiddenimports = ['user', 'security', 'secure_model', 'api_client', 'hardware_service', 'constants', 'annotation', 'remote_command', 'ai_config', 'inference', 'remote_command_handler']
hiddenimports = ['constants', 'annotation', 'credentials', 'file_data', 'user', 'security', 'secure_model', 'api_client', 'hardware_service', 'remote_command', 'ai_config', 'inference', 'remote_command_handler']
tmp_ret = collect_all('jwt')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
tmp_ret = collect_all('requests')