Coverage for gws-app/gws/config/loader.py: 16%

122 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-17 01:37 +0200

1import sys 

2 

3import gws 

4import gws.spec.runtime 

5import gws.lib.jsonx 

6import gws.lib.osx 

7 

8from . import parser 

9 

10STORE_PATH = gws.c.CONFIG_DIR + '/config.pickle' 

11ROOT_NAME = 'gws_root_object' 

12 

13 

14def configure( 

15 manifest_path=None, 

16 config_path=None, 

17 config=None, 

18 before_init=None, 

19 fallback_config=None, 

20 with_spec_cache=True, 

21) -> gws.Root: 

22 """Configure the server""" 

23 

24 def _print(a): 

25 if isinstance(a, (list, tuple)): 

26 for item in a: 

27 _print(item) 

28 elif a is not None: 

29 for s in str(a).split('\n'): 

30 gws.log.error(errpfx + s) 

31 

32 def _report(_exc): 

33 _print(getattr(_exc, 'args', repr(_exc))) 

34 

35 errors = [] 

36 errpfx = 'CONFIGURATION ERROR: ' 

37 root_obj = None 

38 

39 ts = gws.u.stime() 

40 ms = gws.lib.osx.process_rss_size() 

41 

42 manifest_path = real_manifest_path(manifest_path) 

43 if manifest_path: 

44 gws.log.info(f'using manifest {manifest_path!r}...') 

45 

46 try: 

47 specs = gws.spec.runtime.create( 

48 manifest_path=manifest_path, 

49 read_cache=with_spec_cache, 

50 write_cache=with_spec_cache 

51 ) 

52 except Exception as exc: 

53 _report(exc) 

54 raise gws.ConfigurationError('spec failed') from exc 

55 

56 if not config: 

57 config_path = real_config_path(config_path) 

58 if config_path: 

59 gws.log.info(f'using config {config_path!r}...') 

60 p = parser.ConfigParser(specs) 

61 config = p.parse_main(config_path) 

62 errors.extend(p.errors) 

63 else: 

64 errors.append(gws.ConfigurationError('no configuration file found')) 

65 

66 if config: 

67 if before_init: 

68 before_init(config) 

69 root_obj = initialize(specs, config) 

70 if root_obj: 

71 errors.extend(root_obj.configErrors) 

72 

73 err_cnt = 0 

74 

75 if errors: 

76 err_cnt = len(errors) 

77 for n, err in enumerate(errors, 1): 

78 gws.log.error(errpfx + f'{n} of {err_cnt}') 

79 _report(err) 

80 gws.log.error(errpfx + ('-' * 60)) 

81 

82 if root_obj: 

83 info = '{:d} objects, time: {:d} s., memory: {:.2f} MB'.format( 

84 root_obj.object_count(), 

85 gws.u.stime() - ts, 

86 gws.lib.osx.process_rss_size() - ms, 

87 ) 

88 if not errors: 

89 gws.log.info(f'configuration ok, {info}') 

90 return root_obj 

91 if not specs.manifest.withStrictConfig: 

92 gws.log.warning(f'configuration complete with {err_cnt} error(s), {info}') 

93 return root_obj 

94 

95 if specs.manifest.withFallbackConfig and fallback_config: 

96 gws.log.warning(f'using fallback config') 

97 return configure(config=fallback_config) 

98 

99 raise gws.ConfigurationError('configuration failed') 

100 

101 

102def initialize(specs, parsed_config) -> gws.Root: 

103 root_obj = gws.create_root(specs) 

104 root_obj.create_application(parsed_config) 

105 root_obj.post_initialize() 

106 return root_obj 

107 

108 

109def activate(root_obj: gws.Root): 

110 root_obj.activate() 

111 return gws.u.set_app_global(ROOT_NAME, root_obj) 

112 

113 

114def deactivate(): 

115 return gws.u.delete_app_global(ROOT_NAME) 

116 

117 

118def store(root_obj: gws.Root, path=None) -> str: 

119 path = path or STORE_PATH 

120 gws.log.debug(f'writing config to {path!r}') 

121 try: 

122 gws.lib.jsonx.to_path(f'{path}.syspath.json', sys.path) 

123 gws.u.serialize_to_path(root_obj, path) 

124 return path 

125 except Exception as exc: 

126 raise gws.ConfigurationError('unable to store configuration') from exc 

127 

128 

129def load(path=None) -> gws.Root: 

130 path = path or STORE_PATH 

131 gws.log.debug(f'loading config from {path!r}') 

132 try: 

133 return _load(path) 

134 except Exception as exc: 

135 raise gws.ConfigurationError('unable to load configuration') from exc 

136 

137 

138def _load(path) -> gws.Root: 

139 sys_path = gws.lib.jsonx.from_path(f'{path}.syspath.json') 

140 for p in sys_path: 

141 if p not in sys.path: 

142 sys.path.insert(0, p) 

143 gws.log.debug(f'path {p!r} added to sys.path') 

144 

145 ts = gws.u.stime() 

146 ms = gws.lib.osx.process_rss_size() 

147 

148 root_obj = gws.u.unserialize_from_path(path) 

149 

150 activate(root_obj) 

151 

152 gws.log.info('configuration ok, {:d} objects, time: {:d} s., memory: {:.2f} MB'.format( 

153 root_obj.object_count(), 

154 gws.u.stime() - ts, 

155 gws.lib.osx.process_rss_size() - ms, 

156 )) 

157 

158 return root_obj 

159 

160 

161def root() -> gws.Root: 

162 def _err(): 

163 raise gws.Error('no configuration root found') 

164 

165 return gws.u.get_app_global(ROOT_NAME, _err) 

166 

167 

168_DEFAULT_CONFIG_PATHS = [ 

169 '/data/config.cx', 

170 '/data/config.json', 

171 '/data/config.yaml', 

172 '/data/config.py', 

173] 

174 

175 

176def real_config_path(config_path): 

177 p = config_path or gws.env.GWS_CONFIG 

178 if p: 

179 return p 

180 for p in _DEFAULT_CONFIG_PATHS: 

181 if gws.u.is_file(p): 

182 return p 

183 

184 

185_DEFAULT_MANIFEST_PATHS = [ 

186 '/data/MANIFEST.json', 

187] 

188 

189 

190def real_manifest_path(manifest_path): 

191 p = manifest_path or gws.env.GWS_MANIFEST 

192 if p: 

193 return p 

194 for p in _DEFAULT_MANIFEST_PATHS: 

195 if gws.u.is_file(p): 

196 return p