def get_backup_data(self) -> dict: """ Stores the backup at the current destination. """ data = DictHelper().from_json_file(self.source_file) if PlatformUtility.is_windows(): result = {} for directory, files in data.items(): result[os.path.normpath(directory)] = files PyFunceble.facility.Logger.debug("Backup (read) data:\n%r", result) return result PyFunceble.facility.Logger.debug("Backup (read) data:\n%r", data) return data
class InfoManager: """ Provides an interface for the management of the :code:`info.json` file. .. warning:: Keep in mind that this interface provides everything that may be needed by other interfaces. """ WORKSPACE_DIR: str = dead_hosts.launcher.defaults.envs.WORKSPACE_DIR PYFUNCEBLE_CONFIG_DIR: str = ( dead_hosts.launcher.defaults.paths.PYFUNCEBLE_CONFIG_DIRECTORY ) GHA_WORKFLOWS_DIR: str = os.path.join( WORKSPACE_DIR, dead_hosts.launcher.defaults.paths.GHA_WORKFLOW_DIR ) INFO_FILE = os.path.join( WORKSPACE_DIR, dead_hosts.launcher.defaults.paths.INFO_FILENAME ) def __init__(self) -> None: self.info_file_instance = FileHelper(self.INFO_FILE) if self.info_file_instance.exists(): self.content = DictHelper().from_json_file(self.info_file_instance.path) else: self.content = {} logging.debug("Administration file path: %r", self.INFO_FILE) logging.debug( "Administration file exists: %r", self.info_file_instance.exists() ) logging.debug("Administration file content:\n%r", self.content) self.update() self.create_missing_index() self.clean() self.store() def __getattr__(self, index: str) -> Any: if index in self.content: return self.content[index] raise AttributeError(index) def __getitem__(self, index: str) -> Any: if index in self.content: return self.content[index] raise AttributeError(index) def __setitem__(self, index: str, value: Any): self.content[index] = value def __del__(self): self.store() def store(self) -> "InfoManager": """ Stores the current state. """ local_copy = {} for index, value in self.content.items(): if index.endswith("_timestamp") and isinstance(value, datetime): local_copy[index] = value.timestamp() elif index.endswith("_datetime") and isinstance(value, datetime): local_copy[index] = value.isoformat() else: local_copy[index] = copy.deepcopy(value) DictHelper(local_copy).to_json_file(self.info_file_instance.path) return self def clean(self) -> "InfoManager": """ Cleans the unneeded indexes. """ for index in [ "arguments", "clean_list_file", "clean_original", "commit_autosave_message", "last_test", "list_name", "stable", ]: if index in self.content: del self.content[index] logging.debug( "Deleted the %r index of the administration file, " "it is not needed anymore.", index, ) return self def create_missing_index(self) -> "InfoManager": """ Creates the missing indexes. """ default_datetime = datetime.utcnow() - timedelta(days=15) indexes = { "currently_under_test": False, "custom_pyfunceble_config": {}, "days_until_next_test": 2, "finish_datetime": default_datetime, "finish_timestamp": default_datetime.timestamp(), "last_download_datetime": default_datetime, "last_download_timestamp": default_datetime.timestamp(), "latest_part_finish_timestamp": default_datetime.timestamp(), "latest_part_start_timestamp": default_datetime.timestamp(), "latest_part_finish_datetime": default_datetime, "latest_part_start_datetime": default_datetime, "name": dead_hosts.launcher.defaults.paths.GIT_BASE_NAME, "own_management": False, "ping": [], "raw_link": None, "start_datetime": default_datetime, "start_timestamp": default_datetime.timestamp(), "live_update": True, } for index, value in indexes.items(): if index not in self.content: self.content[index] = value logging.debug( "Created the %r index of the administration file, it was not found.", index, ) def update(self) -> "InfoManager": """ Updates and filters the new content. """ # pylint: disable=too-many-branches self.content["name"] = dead_hosts.launcher.defaults.paths.GIT_BASE_NAME logging.debug("Updated the `name` index of the administration file.") to_delete = [ FileHelper(os.path.join(self.WORKSPACE_DIR, ".administrators")), FileHelper(os.path.join(self.WORKSPACE_DIR, "update_me.py")), FileHelper(os.path.join(self.WORKSPACE_DIR, "admin.py")), ] if "list_name" in self.content: to_delete.append( FileHelper(os.path.join(self.WORKSPACE_DIR, self.content["list_name"])) ) if "ping" in self.content: local_ping_result = [] for username in self.content["ping"]: if username.startswith("@"): local_ping_result.append(username) else: local_ping_result.append(f"@{username}") self.content["ping"] = local_ping_result logging.debug( "Updated the `ping` index of the administration file, " "the format has to stay the same everywhere." ) if ( "raw_link" in self.content and isinstance(self.content["raw_link"], str) and not self.content["raw_link"] ): self.content["raw_link"] = None logging.debug( "Updated the `raw_link` index of the administration file, " "empty string not accepted." ) if "custom_pyfunceble_config" in self.content: if self.content["custom_pyfunceble_config"]: if not isinstance(self.content["custom_pyfunceble_config"], dict): self.content["custom_pyfunceble_config"] = {} else: self.content["custom_pyfunceble_config"] = DictHelper( self.content["custom_pyfunceble_config"] ).flatten() else: self.content["custom_pyfunceble_config"] = {} logging.debug( "Updated the `custom_pyfunceble_config` index of the " "administration file, it should be a %r.", dict, ) if ( "custom_pyfunceble_config" in self.content and self.content["custom_pyfunceble_config"] and not isinstance(self.content["custom_pyfunceble_config"], dict) ): self.content["custom_pyfunceble_config"] = {} logging.debug( "Updated the `custom_pyfunceble_config` index of the " "administration file, it should be a %r.", dict, ) for index in ["currently_under_test"]: if index in self.content and not isinstance(self.content[index], bool): self.content[index] = bool(int(self.content[index])) logging.debug( "Updated the %r index of the administration file, " "it should be a %r.", index, bool, ) for index in [ "days_until_next_test", "finish_timestamp", "last_download_datetime" "last_download_timestamp" "lastest_part_finish_timestamp", "lastest_part_start_timestamp", "start_timestamp", ]: if index in self.content and not isinstance(self.content[index], float): self.content[index] = float(self.content[index]) logging.debug( "Updated the %r index of the administration file, " "it should be a %r.", index, float, ) for index in [ "finish_timestamp", "last_download_timestamp", "lastest_part_finish_timestamp", "lastest_part_start_timestamp", "start_timestamp", ]: if index in self.content and not isinstance(self.content[index], datetime): self.content[index] = datetime.fromtimestamp(self.content[index]) logging.debug( "Updated the %r index of the administration file, " "the system understands %r only." " (JSON => %s).", index, datetime, dict, ) for index in [ "finish_datetime", "last_download_datetime", "lastest_part_finish_datetime", "lastest_part_start_datetime", "start_datetime", ]: if index in self.content: if self.content[index] and not isinstance( self.content[index], datetime ): self.content[index] = datetime.fromisoformat(self.content[index]) logging.debug( "Updated the %r index of the administration file, " "the system understands %r only." " (JSON => %r.", index, datetime, dict, ) else: self.content[index] = datetime.fromtimestamp(0) logging.debug( "Set the %r index of the administration file, " "it was not previously set.", repr(index), ) for file in to_delete: if file.exists(): file.delete() logging.debug( "Deleted the %r file, it is not needed anymore.", file.path, ) def get_ping_for_commit(self) -> str: """ Provides the string to append in order to mention the users to ping. """ if "ping" in self.content: return " ".join(self.content["ping"]) return ""