Coverage for gws-app/gws/base/application/core.py: 93%
166 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 12:46 +0200
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 12:46 +0200
1"""Core application object"""
3from typing import Optional
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.exporter
12import gws.base.job
13import gws.base.metadata
14import gws.base.model
15import gws.base.printer
16import gws.base.search
17import gws.base.storage
18import gws.base.template
19import gws.base.web
20import gws.config
21import gws.gis.cache
22import gws.gis.mpx.config
23import gws.lib.font
24import gws.server.manager
25import gws.server.monitor
27DEFAULT_LOCALE = ['en_CA']
29DEFAULT_TEMPLATE_SUBJECTS = [
30 'application.home',
31 'application.error',
32 'project.home',
33 'project.description',
34 'layer.description',
35 'feature.description',
36 'feature.title',
37 'feature.label',
38]
40DEFAULT_TEMPLATES = [
41 gws.Config(
42 type='html',
43 path=f'{gws.c.APP_DIR}/gws/base/application/templates/{_s.replace(".", "_")}.cx.html',
44 subject=_s,
45 access=gws.c.PUBLIC,
46 uid=f'gws.base.application.default_template.{_s}',
47 )
48 for _s in DEFAULT_TEMPLATE_SUBJECTS
49]
51DEFAULT_PRINTER = gws.Config(
52 uid='gws.base.application.default_printer',
53 access=gws.c.PUBLIC,
54 template=gws.Config(
55 type='html',
56 path=f'{gws.c.APP_DIR}/gws/base/application/templates/project_print.cx.html',
57 mapSize=(200, 180, gws.Uom.mm),
58 ),
59 qualityLevels=[gws.TemplateQualityLevel(dpi=72)],
60)
62DEFAULT_CSS_FILENAME = 'style.css'
64class Config(gws.ConfigWithAccess):
65 """Main application configuration"""
67 actions: Optional[list[gws.ext.config.action]]
68 """System-wide server actions."""
69 auth: Optional[gws.base.auth.manager.Config]
70 """Authorization methods and options."""
71 cache: Optional[gws.gis.cache.Config]
72 """Global cache configuration."""
73 client: Optional[gws.base.client.Config]
74 """Gws client configuration."""
75 database: Optional[gws.base.database.manager.Config]
76 """Database configuration."""
77 developer: Optional[dict]
78 """Developer options."""
79 exporters: Optional[list[gws.ext.config.exporter]]
80 """Exporters configuration."""
81 finders: Optional[list[gws.ext.config.finder]]
82 """Global search providers."""
83 fonts: Optional[gws.lib.font.Config]
84 """Fonts configuration."""
85 helpers: Optional[list[gws.ext.config.helper]]
86 """Helpers configurations."""
87 locales: Optional[list[gws.LocaleUid]]
88 """Default locales for all projects."""
89 metadata: Optional[gws.base.metadata.Config]
90 """Application metadata."""
91 models: Optional[list[gws.ext.config.model]]
92 """Global data models."""
93 owsServices: Optional[list[gws.ext.config.owsService]]
94 """OWS services configuration."""
95 projectDirs: Optional[list[gws.DirPath]]
96 """Directories with additional projects."""
97 projectPaths: Optional[list[gws.FilePath]]
98 """Additional project paths."""
99 printers: Optional[list[gws.ext.config.printer]]
100 """Print configurations."""
101 projects: Optional[list[gws.ext.config.project]]
102 """Project configurations."""
103 server: Optional[gws.server.Config]
104 """Server engine options."""
105 storage: Optional[gws.base.storage.manager.Config]
106 """Database configuration."""
107 templates: Optional[list[gws.ext.config.template]]
108 """Default templates."""
109 templateOptions: Optional[gws.TemplateOptions]
110 """Options for default templates."""
111 title: Optional[str]
112 """Application title."""
113 vars: Optional[dict]
114 """Custom variables."""
115 web: Optional[gws.base.web.manager.Config]
116 """Web server options."""
117 lastUid: int = 1
118 """Last used uid for auto-generated uids."""
121class Object(gws.Application):
122 """Main Application object"""
124 _helperMap: dict[str, gws.Node]
126 _developerOptions: dict
128 mpxUrl = ''
129 mpxConfig = ''
131 def configure(self):
132 self.version = self.root.specs.version
133 self.versionString = f'GWS version {self.version}'
135 if gws.u.is_file('/GWS_REVISION'):
136 self.versionString += ' (rev. ' + gws.u.read_file('/GWS_REVISION') + ')'
138 if not gws.env.GWS_IN_TEST:
139 gws.log.info('*' * 80)
140 gws.log.info(self.versionString)
141 gws.log.info('*' * 80)
143 self.vars = self.cfg('vars') or {}
145 self.title = self.cfg('title') or ''
147 self.serverMgr = self.create_child(gws.server.manager.Object, self.cfg('server'))
148 # NB need defaults from the server
149 self.config.server = self.serverMgr.config
151 gws.log.set_level(self.cfg('server.log.level'))
153 self._developerOptions = self.cfg('developer') or {}
154 if self._developerOptions:
155 gws.log.warning(f'developer mode enabled: {self._developerOptions}')
157 self.monitor = self.create_child(gws.server.monitor.Object, self.serverMgr.cfg('monitor'))
159 self.localeUids = self.cfg('locales') or DEFAULT_LOCALE
160 self.metadata = gws.base.metadata.from_config(self.cfg('metadata'))
162 self.middlewareMgr = self.create_child(gws.base.application.middleware.Object)
164 p = self.cfg('fonts')
165 if p:
166 gws.lib.font.configure(p)
168 # NB the order of initialization is important
169 # - db
170 # - helpers
171 # - auth providers
172 # - actions, client, web
173 # - finally, projects
175 self.databaseMgr = self.create_child(gws.base.database.manager.Object, self.cfg('database'))
177 helpers = self.create_children(gws.ext.object.helper, self.cfg('helpers'))
178 self._helperMap = {p.extType: p for p in helpers}
180 self.storageMgr = self.create_child(gws.base.storage.manager.Object, self.cfg('storage'))
181 self.authMgr = self.create_child(gws.base.auth.manager.Object, self.cfg('auth'))
183 # @TODO default API
184 self.actionMgr = self.create_child(gws.base.action.manager.Object)
185 self.actions = self.create_children(gws.ext.object.action, self.cfg('actions'))
187 self.webMgr = self.create_child(gws.base.web.manager.Object, self.cfg('web'))
189 self.searchMgr = self.create_child(gws.base.search.manager.Object)
190 self.finders = self.create_children(gws.ext.object.finder, self.cfg('finders'))
192 self.modelMgr = self.create_child(gws.base.model.manager.Object)
193 self.models = self.create_children(gws.ext.object.model, self.cfg('models'))
195 self.templateMgr = self.create_child(gws.base.template.manager.Object)
196 self.templates = self.create_children(gws.ext.object.template, self.cfg('templates'))
197 for cfg in DEFAULT_TEMPLATES:
198 self.templates.append(self.root.create_shared(gws.ext.object.template, cfg))
200 p = self.cfg('templateOptions')
201 defaults = gws.TemplateOptions(
202 withLogin = any(a.extType == 'auth' for a in self.actions),
203 homeResources = [],
204 projectResources = [],
205 )
206 if gws.u.is_file(self.webMgr.site.staticRoot.dir + f'/{DEFAULT_CSS_FILENAME}'):
207 defaults.homeResources = [f'/{DEFAULT_CSS_FILENAME}']
208 defaults.projectResources = [f'/{DEFAULT_CSS_FILENAME}']
210 self.templateOptions = gws.u.merge(defaults, self.cfg('templateOptions'))
212 self.exporterMgr = self.create_child(gws.base.exporter.manager.Object)
213 self.exporters = self.create_children(gws.ext.object.exporter, self.cfg('exporters'))
215 self.jobMgr = self.create_child(gws.base.job.manager.Object)
217 self.printerMgr = self.create_child(gws.base.printer.manager.Object)
218 self.printers = self.create_children(gws.ext.object.printer, self.cfg('printers'))
219 self.defaultPrinter = self.root.create_shared(gws.ext.object.printer, DEFAULT_PRINTER)
221 self.owsServices = self.create_children(gws.ext.object.owsService, self.cfg('owsServices'))
223 self.client = self.create_child(gws.base.client.Object, self.cfg('client'))
225 self.projects = self.create_children(gws.ext.object.project, self.cfg('projects'))
227 def post_configure(self):
228 if not self.cfg('server.mapproxy.disabled'):
229 self.mpxUrl = f'http://{self.cfg("server.mapproxy.host")}:{self.cfg("server.mapproxy.port")}'
230 self.mpxConfig = gws.gis.mpx.config.create_and_save(self.root)
232 def activate(self):
233 gws.log.set_level(self.cfg('server.log.level'))
235 for p in self.root.configPaths:
236 if p.startswith(gws.c.CONFIG_DIR):
237 # do not watch derived config paths
238 continue
239 self.monitor.watch_file(p)
240 for d in self.config.get('projectDirs') or []:
241 self.monitor.watch_directory(d, gws.config.CONFIG_PATH_PATTERN)
243 def project(self, uid):
244 for p in self.projects:
245 if p.uid == uid:
246 return p
248 def helper(self, ext_type):
249 if ext_type not in self._helperMap:
250 p = self.create_child(gws.ext.object.helper, type=ext_type)
251 if not p:
252 raise gws.Error(f'helper {ext_type!r} not found')
253 gws.log.info(f'created helper {ext_type!r}')
254 self._helperMap[ext_type] = p
255 return self._helperMap.get(ext_type)
257 def developer_option(self, key):
258 return self._developerOptions.get(key)