Hide keyboard shortcuts

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] 

2 

3 

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 

13 

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] 

20 

21 

22# region [Logging] 

23 

24log = logging.getLogger('gidappdata') 

25log.info(glog.imported(__name__)) 

26 

27# endregion [Logging] 

28 

29 

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 

38 

39 

40class ParaStorageKeeper(metaclass=ParaStorageKeeperMetaHelper): 

41 # region [ClassAttributes] 

42 

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] 

51 

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') 

67 

68 @classmethod 

69 def set_single_access_confighandler(cls): 

70 cls.config_handler = SingleAccessConfigHandler 

71 

72 @classmethod 

73 def set_experimental_confighandler(cls): 

74 from gidconfig.experimental import GidAttConfigIni 

75 cls.config_handler = GidAttConfigIni 

76 

77 @classmethod 

78 def set_clean(cls, setting: bool): 

79 cls.app_info['clean'] = setting 

80 

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) 

90 

91 @classmethod 

92 def set_archive_data(cls, archive_data: bytes): 

93 cls.archive_data = archive_data 

94 

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 

107 

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 

115 

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) 

122 

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) 

129 

130 @classmethod 

131 def set_unpacked(cls): 

132 cls.app_info['is_unpacked'] = True 

133 

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) 

146 

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 

156 

157 @classmethod 

158 def get_appdata(cls): 

159 if cls.is_init is False: 

160 cls.initialize() 

161 return cls.appdata 

162 

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) 

168 

169 

170if __name__ == '__main__': 

171 pass