from core.Constants import Constants from core.models.Location import Location from core.models.Subscription import Subscription from core.models.session.ApplicationVersion import ApplicationVersion from dataclasses import dataclass, field from dataclasses_json import config, Exclude, dataclass_json from json import JSONDecodeError from typing import Optional import json import os import re import shutil @dataclass_json @dataclass class BaseProfile: id: int = field( metadata=config(exclude=Exclude.ALWAYS) ) name: str subscription: Optional[Subscription] location: Optional[Location] def get_config_path(self): return BaseProfile.__get_config_path(self.id) def get_data_path(self): return BaseProfile.__get_data_path(self.id) def has_subscription(self): return self.subscription is not None def is_session_profile(self): return type(self).__name__ == 'SessionProfile' def is_system_profile(self): return type(self).__name__ == 'SystemProfile' def delete_data(self): shutil.rmtree(BaseProfile.__get_data_path(self.id), ignore_errors=True) def delete(self): self._delete() def _delete(self): shutil.rmtree(BaseProfile.__get_config_path(self.id), ignore_errors=True) self.delete_data() @staticmethod def find_by_id(id: int): try: config_file_contents = open(f'{BaseProfile.__get_config_path(id)}/config.json', 'r').read() except FileNotFoundError: return None try: profile = json.loads(config_file_contents) except JSONDecodeError: return None profile['id'] = id if profile['location'] is not None: location = Location.find(profile['location']['code'] or None) if location is not None: if profile['location']['time_zone'] is not None: location.time_zone = profile['location']['time_zone'] profile['location'] = location if 'application_version' in profile: if profile['application_version'] is not None: application_version = ApplicationVersion.find(profile['application_version']['application_code'] or None, profile['application_version']['version_number'] or None) if application_version is not None: profile['application_version'] = application_version from core.models.session.SessionProfile import SessionProfile # noinspection PyUnresolvedReferences profile = SessionProfile.from_dict(profile) else: from core.models.system.SystemProfile import SystemProfile # noinspection PyUnresolvedReferences profile = SystemProfile.from_dict(profile) return profile @staticmethod def exists(id: int): return os.path.isdir(BaseProfile.__get_config_path(id)) and re.match(r'^\d+$', str(id)) @staticmethod def all(): profiles = {} for id in map(int, sorted(os.listdir(Constants.SP_PROFILE_CONFIG_HOME))): if BaseProfile.exists(id): if os.path.exists(f'{BaseProfile.__get_config_path(id)}/config.json'): profile = BaseProfile.find_by_id(id) if profile is not None: profiles[id] = profile return profiles @staticmethod def save(profile): if profile.is_session_profile() and profile.application_version is not None: persistent_state_path = f'{BaseProfile.__get_data_path(profile.id)}/persistent-state' if os.path.isdir(persistent_state_path): shutil.rmtree(persistent_state_path, ignore_errors=True) config_file_contents = f'{profile.to_json(indent=4)}\n' os.makedirs(BaseProfile.__get_config_path(profile.id), exist_ok=True) os.makedirs(BaseProfile.__get_data_path(profile.id), exist_ok=True) config_file_path = f'{BaseProfile.__get_config_path(profile.id)}/config.json' with open(config_file_path, 'w') as config_file: config_file.write(config_file_contents) config_file.close() @staticmethod def __get_config_path(id: int): return f'{Constants.SP_PROFILE_CONFIG_HOME}/{str(id)}' @staticmethod def __get_data_path(id: int): return f'{Constants.SP_PROFILE_DATA_HOME}/{str(id)}'