Coverage for gws-app/gws/base/application/core.py: 93%

150 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-16 22:59 +0200

1"""Core application object""" 

2 

3from typing import Optional 

4 

5import gws 

6import gws.base.action 

7import gws.base.application.middleware 

8import gws.base.auth 

9import gws.base.client 

10import gws.base.database 

11import gws.base.job 

12import gws.base.model 

13import gws.base.printer 

14import gws.base.project 

15import gws.base.search 

16import gws.base.storage 

17import gws.base.template 

18import gws.base.web 

19import gws.config 

20import gws.gis.cache 

21import gws.gis.mpx.config 

22import gws.lib.font 

23import gws.lib.importer 

24import gws.base.metadata 

25import gws.lib.osx 

26import gws.server.manager 

27import gws.server.monitor 

28import gws.spec 

29 

30_DEFAULT_LOCALE = ['en_CA'] 

31 

32_DEFAULT_TEMPLATES = [ 

33 gws.Config( 

34 type='html', 

35 path=gws.u.dirname(__file__) + '/templates/project_description.cx.html', 

36 subject='project.description', 

37 access=gws.c.PUBLIC, 

38 uid='default_template.project_description', 

39 ), 

40 gws.Config( 

41 type='html', 

42 path=gws.u.dirname(__file__) + '/templates/layer_description.cx.html', 

43 subject='layer.description', 

44 access=gws.c.PUBLIC, 

45 uid='default_template.layer_description', 

46 ), 

47 gws.Config( 

48 type='html', 

49 path=gws.u.dirname(__file__) + '/templates/feature_description.cx.html', 

50 subject='feature.description', 

51 access=gws.c.PUBLIC, 

52 uid='default_template.feature_description', 

53 ), 

54 gws.Config( 

55 type='html', 

56 path=gws.u.dirname(__file__) + '/templates/feature_title.cx.html', 

57 subject='feature.title', 

58 access=gws.c.PUBLIC, 

59 uid='default_template.feature_title', 

60 ), 

61 gws.Config( 

62 type='html', 

63 path=gws.u.dirname(__file__) + '/templates/feature_label.cx.html', 

64 subject='feature.label', 

65 access=gws.c.PUBLIC, 

66 uid='default_template.feature_label', 

67 ), 

68] 

69 

70_DEFAULT_PRINTER = gws.Config( 

71 uid='gws.base.application.default_printer', 

72 access=gws.c.PUBLIC, 

73 template=gws.Config( 

74 type='html', 

75 path=gws.u.dirname(__file__) + '/templates/project_print.cx.html', 

76 mapSize=(200, 180, gws.Uom.mm), 

77 ), 

78 qualityLevels=[{'dpi': 72}], 

79) 

80 

81 

82class Config(gws.ConfigWithAccess): 

83 """Main application configuration""" 

84 

85 actions: Optional[list[gws.ext.config.action]] 

86 """System-wide server actions.""" 

87 auth: Optional[gws.base.auth.manager.Config] 

88 """Authorization methods and options.""" 

89 cache: Optional[gws.gis.cache.Config] 

90 """Global cache configuration.""" 

91 client: Optional[gws.base.client.Config] 

92 """Gws client configuration.""" 

93 database: Optional[gws.base.database.manager.Config] 

94 """Database configuration.""" 

95 developer: Optional[dict] 

96 """Developer options.""" 

97 finders: Optional[list[gws.ext.config.finder]] 

98 """Global search providers.""" 

99 fonts: Optional[gws.lib.font.Config] 

100 """Fonts configuration.""" 

101 helpers: Optional[list[gws.ext.config.helper]] 

102 """Helpers configurations.""" 

103 locales: Optional[list[gws.LocaleUid]] 

104 """Default locales for all projects.""" 

105 metadata: Optional[gws.base.metadata.Config] 

106 """Application metadata.""" 

107 models: Optional[list[gws.ext.config.model]] 

108 """Global data models.""" 

109 owsServices: Optional[list[gws.ext.config.owsService]] 

110 """OWS services configuration.""" 

111 projectDirs: Optional[list[gws.DirPath]] 

112 """Directories with additional projects.""" 

113 projectPaths: Optional[list[gws.FilePath]] 

114 """Additional project paths.""" 

115 printers: Optional[list[gws.ext.config.printer]] 

116 """Print configurations.""" 

117 projects: Optional[list[gws.ext.config.project]] 

118 """Project configurations.""" 

119 server: Optional[gws.server.Config] 

120 """Server engine options.""" 

121 storage: Optional[gws.base.storage.manager.Config] 

122 """Database configuration.""" 

123 templates: Optional[list[gws.ext.config.template]] 

124 """Default templates.""" 

125 vars: Optional[dict] 

126 """Custom variables.""" 

127 web: Optional[gws.base.web.manager.Config] 

128 """Web server options.""" 

129 

130 

131class Object(gws.Application): 

132 """Main Application object""" 

133 

134 _helperMap: dict[str, gws.Node] 

135 

136 _developerOptions: dict 

137 

138 mpxUrl = '' 

139 mpxConfig = '' 

140 

141 def configure(self): 

142 self.vars = self.cfg('vars') or {} 

143 

144 self.serverMgr = self.create_child(gws.server.manager.Object, self.cfg('server')) 

145 # NB need defaults from the server 

146 self.config.server = self.serverMgr.config 

147 

148 gws.log.set_level(self.cfg('server.log.level')) 

149 

150 self.version = self.root.specs.version 

151 self.versionString = f'GWS version {self.version}' 

152 

153 if gws.u.is_file('/GWS_REVISION'): 

154 self.versionString += ' (rev. ' + gws.u.read_file('/GWS_REVISION') + ')' 

155 

156 if not gws.env.GWS_IN_TEST: 

157 gws.log.info('*' * 80) 

158 gws.log.info(self.versionString) 

159 gws.log.info('*' * 80) 

160 

161 self._developerOptions = self.cfg('developer') or {} 

162 if self._developerOptions: 

163 gws.log.warning(f'developer mode enabled: {self._developerOptions}') 

164 

165 self.monitor = self.create_child(gws.server.monitor.Object, self.serverMgr.cfg('monitor')) 

166 

167 self.localeUids = self.cfg('locales') or _DEFAULT_LOCALE 

168 self.metadata = gws.base.metadata.from_config(self.cfg('metadata')) 

169 

170 self.middlewareMgr = self.create_child(gws.base.application.middleware.Object) 

171 

172 p = self.cfg('fonts') 

173 if p: 

174 gws.lib.font.configure(p) 

175 

176 # NB the order of initialization is important 

177 # - db 

178 # - helpers 

179 # - auth providers 

180 # - actions, client, web 

181 # - finally, projects 

182 

183 self.databaseMgr = self.create_child(gws.base.database.manager.Object, self.cfg('database')) 

184 

185 helpers = self.create_children(gws.ext.object.helper, self.cfg('helpers')) 

186 self._helperMap = {p.extType: p for p in helpers} 

187 

188 self.storageMgr = self.create_child(gws.base.storage.manager.Object, self.cfg('storage')) 

189 self.authMgr = self.create_child(gws.base.auth.manager.Object, self.cfg('auth')) 

190 

191 # @TODO default API 

192 self.actionMgr = self.create_child(gws.base.action.manager.Object) 

193 self.actions = self.create_children(gws.ext.object.action, self.cfg('actions')) 

194 

195 self.webMgr = self.create_child(gws.base.web.manager.Object, self.cfg('web')) 

196 

197 self.searchMgr = self.create_child(gws.base.search.manager.Object) 

198 self.finders = self.create_children(gws.ext.object.finder, self.cfg('finders')) 

199 

200 self.modelMgr = self.create_child(gws.base.model.manager.Object) 

201 self.models = self.create_children(gws.ext.object.model, self.cfg('models')) 

202 

203 self.templateMgr = self.create_child(gws.base.template.manager.Object) 

204 self.templates = self.create_children(gws.ext.object.template, self.cfg('templates')) 

205 for cfg in _DEFAULT_TEMPLATES: 

206 self.templates.append(self.root.create_shared(gws.ext.object.template, cfg)) 

207 

208 self.jobMgr = self.create_child(gws.base.job.manager.Object) 

209 

210 self.printerMgr = self.create_child(gws.base.printer.manager.Object) 

211 self.printers = self.create_children(gws.ext.object.printer, self.cfg('printers')) 

212 self.defaultPrinter = self.root.create_shared(gws.ext.object.printer, _DEFAULT_PRINTER) 

213 

214 self.owsServices = self.create_children(gws.ext.object.owsService, self.cfg('owsServices')) 

215 

216 self.client = self.create_child(gws.base.client.Object, self.cfg('client')) 

217 

218 self.projects = self.create_children(gws.ext.object.project, self.cfg('projects')) 

219 

220 def post_configure(self): 

221 if not self.cfg('server.mapproxy.disabled'): 

222 self.mpxUrl = f"http://{self.cfg('server.mapproxy.host')}:{self.cfg('server.mapproxy.port')}" 

223 self.mpxConfig = gws.gis.mpx.config.create_and_save(self.root) 

224 

225 def activate(self): 

226 gws.log.set_level(self.cfg('server.log.level')) 

227 

228 for p in self.root.configPaths: 

229 if p.startswith(gws.c.CONFIG_DIR): 

230 # do not watch derived config paths 

231 continue 

232 self.monitor.watch_file(p) 

233 for d in self.config.get('projectDirs') or []: 

234 self.monitor.watch_directory(d, gws.config.CONFIG_PATH_PATTERN) 

235 

236 def project(self, uid): 

237 for p in self.projects: 

238 if p.uid == uid: 

239 return p 

240 

241 def helper(self, ext_type): 

242 if ext_type not in self._helperMap: 

243 p = self.create_child(gws.ext.object.helper, type=ext_type) 

244 if not p: 

245 raise gws.Error(f'helper {ext_type!r} not found') 

246 gws.log.info(f'created helper {ext_type!r}') 

247 self._helperMap[ext_type] = p 

248 return self._helperMap.get(ext_type) 

249 

250 def developer_option(self, key): 

251 return self._developerOptions.get(key)