Coverage for gidappdata\standard_appdata\appdata_provider_new.py : 84%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# region [Imports]
4import lzma
5import os
6from dotenv import load_dotenv
7import zipfile
8import os
9import base64
10import logging
11import gidlogger as glog
12from gidconfig.standard import ConfigHandler, SingleAccessConfigHandler
14from gidappdata.standard_appdata.appdata_storager import AppDataStorager
15from gidappdata.utility.functions import pathmaker, to_attr_name, filename_to_attr_name, create_folder, create_file, readit, writeit
16from gidappdata.utility.extended_dotenv import find_dotenv_everywhere
17from gidappdata.utility.exceptions import ConstructionEnvDataMissing, DevSettingError
18from gidappdata.cli.pack_and_bin_and_py_data import generate_user_data_binfile
19# endregion [Imports]
22# region [Logging]
24log = logging.getLogger('gidappdata')
25log.info(glog.imported(__name__))
27# endregion [Logging]
30class ParaStorageKeeperMetaHelper(type):
31 def __getattr__(cls, name):
32 _out = ParaStorageKeeper.configs.get(name, None)
33 if _out is None:
34 _out = ParaStorageKeeper.app_info.get(name)
35 if _out is None:
36 raise AttributeError
37 return _out
40class ParaStorageKeeper(metaclass=ParaStorageKeeperMetaHelper):
41 # region [ClassAttributes]
43 is_init = False
44 appdata = None
45 configs = {}
46 construction_env_filename = 'construction_info.env'
47 app_info = {'app_name': None, 'author_name': None, 'uses_base64': None, 'clean': True, 'dev': False, 'redirect': '', 'log_folder': '', "is_unpacked": False}
48 config_handler = ConfigHandler
49 archive_data = None
50 # endregion[ClassAttributes]
52 @staticmethod
53 def _unzip(root_dir, zip_file, overwrite: bool = False):
54 # sourcery skip: simplify-boolean-comparison
55 with zipfile.ZipFile(zip_file, 'r') as zipf:
56 for item in zipf.namelist():
57 _info = zipf.getinfo(item)
58 if _info.is_dir() is True:
59 create_folder(pathmaker(root_dir, item))
60 else:
61 if os.path.isfile(pathmaker(root_dir, item)) is False or overwrite is True:
62 zipf.extract(item, pathmaker(root_dir))
63 log.debug("extracted file '%s' because it didn't exist", pathmaker(root_dir, item))
64 else:
65 log.debug("file '%s' is already existing and overwrite is 'False' so file was not extracted", pathmaker(root_dir, item))
66 log.info('unzipping finished')
68 @classmethod
69 def set_single_access_confighandler(cls):
70 cls.config_handler = SingleAccessConfigHandler
72 @classmethod
73 def set_experimental_confighandler(cls):
74 from gidconfig.experimental import GidAttConfigIni
75 cls.config_handler = GidAttConfigIni
77 @classmethod
78 def set_clean(cls, setting: bool):
79 cls.app_info['clean'] = setting
81 @classmethod
82 def set_dev(cls, setting: bool, redirect=None, log_folder=None):
83 # sourcery skip: simplify-boolean-comparison
84 cls.app_info['dev'] = setting
85 if setting is True:
86 if redirect is None:
87 raise DevSettingError()
88 cls.app_info['redirect'] = pathmaker(redirect)
89 cls.app_info['log_folder'] = pathmaker(log_folder)
91 @classmethod
92 def set_archive_data(cls, archive_data: bytes):
93 cls.archive_data = archive_data
95 @staticmethod
96 def checked_get_env(env_var_name):
97 _out = os.getenv(env_var_name)
98 if _out is None:
99 raise ConstructionEnvDataMissing(env_var_name)
100 if _out.casefold() in ['true', 'yes', '1']:
101 _out = True
102 elif _out.casefold() in ['false', 'no', '0']:
103 _out = False
104 else:
105 _out = _out
106 return _out
108 @classmethod
109 def _archive_from_bin(cls, bin_data, name: str = 'user_data_archive', ext: str = 'zip', uses_base64: bool = False):
110 _file = pathmaker(str(cls.appdata), name + '.' + ext)
111 with open(_file, 'wb') as archfile:
112 _bin_data = bin_data if not uses_base64 else base64.b64decode(bin_data)
113 archfile.write(_bin_data)
114 return _file
116 @classmethod
117 def unpack_archive(cls, in_archive, clean: bool, uses_base64: bool):
118 _file = cls._archive_from_bin(in_archive, uses_base64=uses_base64)
119 cls._unzip(str(cls.appdata), _file, False)
120 if clean:
121 os.remove(_file)
123 @classmethod
124 def find_construct_env(cls):
125 for dirname, folderlist, filelist in os.walk(os.getcwd()):
126 for file in filelist:
127 if file == cls.construction_env_filename:
128 return pathmaker(dirname, file)
130 @classmethod
131 def set_unpacked(cls):
132 cls.app_info['is_unpacked'] = True
134 @classmethod
135 def initialize(cls, archive_data=None):
136 if cls.is_init is True:
137 return
138 load_dotenv(find_dotenv_everywhere(cls.construction_env_filename))
139 for info in cls.app_info:
140 if cls.app_info[info] is None:
141 cls.app_info[info] = cls.checked_get_env(info.upper())
142 redirect = None if cls.app_info['redirect'] == '' else cls.app_info['redirect']
143 log_folder = None if cls.app_info['log_folder'] == '' else cls.app_info['log_folder']
144 archive_data = cls.archive_data if archive_data is None else archive_data
145 cls.appdata = AppDataStorager(cls.app_info['author_name'], cls.app_info['app_name'], cls.app_info['dev'], redirect, log_folder)
147 if cls.app_info['dev'] is False or cls.app_info.get('is_unpacked') is False:
148 cls.unpack_archive(archive_data, cls.app_info['clean'], cls.app_info['uses_base64'])
149 cls.set_unpacked()
150 if os.path.isdir(cls.appdata['config']) is True:
151 for file in os.scandir(cls.appdata['config']):
152 if file.name.endswith('.ini') and 'config' in file.name:
153 name = filename_to_attr_name(file.name)
154 cls.configs[name] = ConfigHandler(cls.appdata[file.name])
155 cls.is_init = True
157 @classmethod
158 def get_appdata(cls):
159 if cls.is_init is False:
160 cls.initialize()
161 return cls.appdata
163 @classmethod
164 def get_config(cls, config_name):
165 if cls.is_init is False:
166 cls.initialize()
167 return cls.configs.get(config_name)
170if __name__ == '__main__':
171 pass