def configure(self): self.db = t.cast( gws.ext.db.provider.postgres.Object, gws.base.db.require_provider(self, 'gws.ext.db.provider.postgres')) self.table = self.db.configure_table(self.var('collectionTable')) self.item_table = self.db.configure_table(self.var('itemTable')) self.document_table = self.db.configure_table( self.var('documentTable')) self.link_col = self.var('linkColumn') self.type_col = 'type' p = self.var('dataModel') or self.db.table_data_model_config( self.table) self.data_model: gws.IDataModel = t.cast( gws.IDataModel, self.create_child('gws.base.model', p)) self.type = self.var('type') self.name = self.var('name') self.item_prototypes = [] for p in self.var('items'): ip = t.cast(ItemPrototype, self.create_child(ItemPrototype, p)) ip.db = self.db ip.table = self.item_table ip.link_col = self.link_col self.item_prototypes.append(ip) p = self.var('style') self.style: gws.IStyle = ( gws.base.style.from_config(p) if p else gws.base.style.from_props( gws.StyleProps(type='css', values=_DEFAULT_STYLE_VALUES)))
def _validate(self, validator: AttributeValidator, value, attr_values) -> bool: if validator.type == 'required': return not gws.is_empty(value) if validator.type == 'length': s = gws.to_str(value).strip() return t.cast(float, validator.min) <= len(s) <= t.cast( float, validator.max) if validator.type == 'regex': s = gws.to_str(value).strip() return bool(re.search(t.cast(str, validator.pattern), s)) if validator.type == 'greaterThan': other = attr_values.get(t.cast(str, validator.attribute)) try: return value > other except TypeError: return False if validator.type == 'lessThan': other = attr_values.get(t.cast(str, validator.attribute)) try: return value < other except TypeError: return False
def configure(self): self.alkis = t.cast(gws.ext.helper.alkis.Object, self.root.find_first('gws.ext.helper.alkis')) self.crs: gws.Crs = self.var('crs') self.db = t.cast( gws.ext.db.provider.postgres.Object, gws.base.db.require_provider(self, 'gws.ext.db.provider.postgres')) self.templates: t.List[gws.ITemplate] = gws.base.template.bundle( self, self.var('templates'), _DEFAULT_TEMPLATES)
def configure_search(obj: gws.IOwsClient, search_class): slf = gws.gis.source.LayerFilter(is_queryable=True) queryable_layers = gws.gis.source.filter_layers(obj.source_layers, slf) if queryable_layers: t.cast(gws.ILayer, obj).search_providers.append( obj.require_child( search_class, gws.Config(_provider=obj.provider, _source_layers=queryable_layers))) return True
def configure(self): self.db = t.cast( gws.ext.db.provider.postgres.Object, gws.base.db.require_provider(self, 'gws.ext.db.provider.postgres')) self.collection_prototypes: t.List[CollectionPrototype] = [] for p in self.var('collections'): self.collection_prototypes.append( t.cast(CollectionPrototype, self.create_child(CollectionPrototype, p)))
def close_session(self, auth, sess, req, res): if sess.typ == _DELETED: gws.log.debug('session cookie=deleted') res.delete_cookie(self.cookie_name, path=self.cookie_path) if sess.typ == _ACTIVE and res.status_code < 400: gws.log.debug('session cookie=', sess.uid) res.set_cookie( self.cookie_name, value=sess.uid, path=self.cookie_path, secure=self.secure, httponly=True, ) t.cast(manager.Object, auth).save_stored_session(sess)
def _worker(root: gws.RootObject, job: gws.lib.job.Job): args = gws.lib.json2.from_string(job.args) action = t.cast(Object, root.find('gws.ext.action', args['actionUid'])) job.update(state=gws.lib.job.State.running) stats = importer.run(action, args['path'], args['replace'], args['auUid'], job) job.update(result={'stats': stats}) action.signal_reload('worker')
def api_csv_export(self, req: gws.IWebRequest, p: ExportParams) -> ExportResponse: au_uid = self._check_au(req, p.auUid) features = self.db.select(gws.SqlSelectArgs( table=self.plan_table, extra_where=[f'_au = %s', au_uid], sort='name', )) helper: gws.ext.helper.csv.Object = t.cast( gws.ext.helper.csv.Object, self.root.find_first('gws.ext.helper.csv')) writer = helper.writer() has_headers = False for f in features: if self.export_data_model: f.apply_data_model(self.export_data_model) if not has_headers: writer.write_headers([a.name for a in f.attributes]) has_headers = True writer.write_attributes(f.attributes) return ExportResponse( fileName='bauplaene_' + au_uid + '.csv', content=writer.as_bytes(), mime='text/csv' )
def sessions(self, p: gws.NoParams): """Print currently active sessions""" root = gws.config.load() auth = t.cast(manager.Object, root.application.auth) rs = [{ 'user': r['user_uid'], 'login': gws.lib.date.to_iso_local(gws.lib.date.from_timestamp( r['created'])), 'activity': gws.lib.date.to_iso_local(gws.lib.date.from_timestamp( r['updated'])), 'duration': r['updated'] - r['created'] } for r in auth.stored_session_records()] print(f'{len(rs)} active sessions\n') print( gws.lib.console.text_table(rs, header=('user', 'login', 'activity', 'duration'))) print('\n')
def configure_zoom(obj: gws.IOwsClient): zoom = gws.gis.zoom.config_from_source_layers(obj.source_layers) if zoom: la = t.cast(gws.ILayer, obj) la.resolutions = gws.gis.zoom.resolutions_from_config( zoom, la.resolutions) return True
def open_session(self, auth, req): sid = req.cookie(self.cookie_name) if not sid: return if self.secure and not req.is_secure: gws.log.debug(f'insecure context, session {sid!r} ignored') return sess = t.cast(manager.Object, auth).find_stored_session(sid) if sess and sess.typ == _ACTIVE: return sess gws.log.debug(f'sid={sid} not found or invalid') return t.cast(manager.Object, auth).new_session(_DELETED, user=auth.guest_user, method=self)
def _get_provider(self, uid) -> t.Optional[provider.Object]: root = gws.config.load() action = root.find(uid=uid) if uid else root.find( klass='gws.ext.action.alkissearch') if not action: gws.log.error('no ALKIS action found') return None return t.cast(search.Object, action).provider
def from_svg(xmlstr: str, size: gws.Size, mime=None) -> 'Image': sz = _int_size(size) with wand.image.Image(blob=xmlstr.encode('utf8'), format='svg', background=t.cast(wand.image.Color, None), width=sz[0], height=sz[1]) as wi: return from_bytes(wi.make_blob(_mime_to_format(mime).lower()))
def compose(self, other, opacity=1) -> 'Image': oth = t.cast('Image', other).img.convert('RGBA') if oth.size != self.img.size: oth = oth.resize(size=self.img.size, resample=PIL.Image.BICUBIC) if opacity < 1: alpha = oth.getchannel('A').point(lambda x: x * opacity) oth.putalpha(alpha) self.img = PIL.Image.alpha_composite(self.img, oth) return self
def configure(self): self.db: gws.ext.db.provider.postgres.Object = t.cast( gws.ext.db.provider.postgres.Object, None) self.table: gws.SqlTable = t.cast(gws.SqlTable, None) self.link_col: str = '' self.type_col: str = 'type' self.data_model: gws.IDataModel = t.cast( gws.IDataModel, self.create_child('gws.base.model', self.var('dataModel'))) self.type = self.var('type') self.name = self.var('name') self.icon = gws.lib.style.parse_icon(self.var('icon')) p = self.var('style') self.style: gws.IStyle = ( gws.base.style.from_config(p) if p else gws.base.style.from_props( gws.StyleProps(type='css', values=_DEFAULT_STYLE_VALUES)))
def configure(self): self.db = t.cast( gws.ext.db.provider.postgres.Object, gws.base.db.require_provider(self, 'gws.ext.db.provider.postgres')) self.data_table = self.db.configure_table(self.var('dataTable')) self.document_table = self.db.configure_table( self.var('documentTable')) self.templates: t.List[gws.ITemplate] = gws.base.template.bundle( self, self.var('templates')) self.details_template: gws.ITemplate = gws.base.template.find( self.templates, subject='fsinfo.details') self.title_template: gws.ITemplate = gws.base.template.find( self.templates, subject='fsinfo.title')
def _geometry(geom: shapely.geometry.base.BaseGeometry, atts: dict = None) -> gws.XmlElement: def _xy(xy): x, y = xy return f'{x} {y}' def _lpath(coords): ps = [] cs = iter(coords) for c in cs: ps.append(f'M {_xy(c)}') break for c in cs: ps.append(f'L {_xy(c)}') return ' '.join(ps) gt = _geom_type(geom) if gt == _TYPE_POINT: g = t.cast(shapely.geometry.Point, geom) return xml2.tag('circle', {'cx': int(g.x), 'cy': int(g.y)}, atts) if gt == _TYPE_LINESTRING: g = t.cast(shapely.geometry.LineString, geom) d = _lpath(g.coords) return xml2.tag('path', {'d': d}, atts) if gt == _TYPE_POLYGON: g = t.cast(shapely.geometry.Polygon, geom) d = ' '.join( _lpath(interior.coords) + ' z' for interior in g.interiors) d = _lpath(g.exterior.coords) + ' z ' + d return xml2.tag('path', {'fill-rule': 'evenodd', 'd': d.strip()}, atts) if gt > _TYPE_MULTI: g = t.cast(shapely.geometry.base.BaseMultipartGeometry, geom) return xml2.tag('g', *[_geometry(p, atts) for p in g.geoms])
def configure(self): self.au_filter: t.List[str] = self.var('gemeindeFilter', default=[]) self.data_table_name: str = self.var('dataTableName') self.request_table_name: str = self.var('requestTableName') self.request_url: str = self.var('requestUrl') self.templates: t.List[gws.ITemplate] = gws.base.template.bundle( self, self.var('templates'), _DEFAULT_TEMPLATES) self.alkis: gws.ext.helper.alkis.Object = t.cast( gws.ext.helper.alkis.Object, self.root.find_first('gws.ext.helper.alkis')) if not self.alkis or not self.alkis.has_index: gws.log.warn('dprocon cannot init, no alkis index found') return
def configure(self): self.db: gws.ext.db.provider.postgres.Object = t.cast( gws.ext.db.provider.postgres.Object, gws.base.db.require_provider(self, 'gws.ext.db.provider.postgres')) self.tables: t.List[Table] = [] for p in self.var('tables'): table = self.db.configure_table(p.table) m = p.dataModel or self.db.table_data_model_config(table) self.tables.append( Table( uid=p.uid or gws.as_uid(table.name), title=p.title or table.name, table=table, data_model=t.cast(gws.IDataModel, self.create_child('gws.base.model', m)), sort=p.sort or table.key_column, widths=p.widths or [], with_filter=bool(p.withFilter), with_add=bool(p.withAdd), with_delete=False, ))
def handle_record(self, rd: core.Request): # Record is our internal method to return bare metadata without the GetRecordByIdResponse envelope # see _make_link below md = self.records.get(rd.req.param('id')) if not md: raise gws.base.web.error.NotFound() return self.template_response(rd, t.cast(gws.OwsVerb, 'Record'), context={ 'record': md.values, 'with_soap': False, 'profile': self.profile, 'version': self.request_version(rd), })
def open_session(self, auth, req): if self.secure and not req.is_secure: return login_pass = _parse_header(req) if not login_pass: return user = auth.authenticate( self, gws.Data(username=login_pass[0], password=login_pass[1])) if user: return t.cast(manager.Object, auth).new_session('http-basic', method=self, user=user) # if the header is provided, it has to be correct raise error.LoginNotFound()
def _handle_request2(req: WebRequest) -> WebResponse: site = t.cast(gws.base.web.site.Object, req.site) cors = site.cors_options if cors and req.method == 'OPTIONS': return _with_cors_headers( cors, req.content_response( gws.ContentResponse(content='', mime='text/plain'))) req.auth_open() res = _handle_request3(req) req.auth_close(res) if cors and req.method == 'POST': res = _with_cors_headers(cors, res) return res
def logout(self, req: gws.IWebRequest, p: gws.Params) -> Response: """Perform a logout""" if req.user.is_guest: return self._resp(req) wr = t.cast(wsgi.WebRequest, req) web_method = wr.auth.get_method(ext_type='web') if not web_method: gws.log.error('web method not configured') raise gws.base.web.error.Forbidden() session = wr.session if session.method != web_method: gws.log.error(f'wrong method for logout: {session.method!r}') raise gws.base.web.error.Forbidden() wr.session = web_method.logout(wr.auth, session, req) return self._resp(req)
def login(self, req: gws.IWebRequest, p: LoginParams) -> Response: """Perform a login""" if not req.user.is_guest: gws.log.error('login while logged-in') raise gws.base.web.error.Forbidden() wr = t.cast(wsgi.WebRequest, req) web_method = wr.auth.get_method(ext_type='web') if not web_method: gws.log.error('web method not configured') raise gws.base.web.error.Forbidden() new_session = web_method.login(wr.auth, p, req) if not new_session: raise gws.base.web.error.Forbidden() wr.session = new_session return self._resp(req)
def ensure_dir(dir_path: str, base_dir: str = None, mode: int = 0o755, user: int = None, group: int = None) -> str: """Check if a (possibly nested) directory exists and create if it does not. Args: dir_path: Path to a directory. base_dir: Base directory. mode: Directory creation mode. user: Directory user (defaults to gws.UID) group: Directory group (defaults to gws.GID) Retruns: The absolute path to the directory. """ if base_dir: if os.path.isabs(dir_path): raise ValueError( f'cannot use an absolute path {dir_path!r} with a base dir') bpath = cast( bytes, os.path.join(base_dir.encode('utf8'), dir_path.encode('utf8'))) else: if not os.path.isabs(dir_path): raise ValueError( f'cannot use a relative path {dir_path!r} without a base dir') bpath = dir_path.encode('utf8') parts = [] for p in bpath.split(b'/'): parts.append(p) path = b'/'.join(parts) if path and not os.path.isdir(path): os.mkdir(path, mode) _chown(bpath, user, group) return bpath.decode('utf8')
def caps(self, p: CapsParams): """Print the capabilities of a service in JSON format""" protocol = None if p.type: protocol = p.type.lower() else: u = p.src.lower() for s in ('wms', 'wmts', 'wfs'): if s in u: protocol = s break if not protocol: raise gws.Error('unknown service') if p.src.startswith(('http:', 'https:')): xml = gws.gis.ows.request.get_text( p.src, protocol=t.cast(gws.OwsProtocol, protocol.upper()), verb=gws.OwsVerb.GetCapabilities) else: xml = gws.read_file(p.src) mod = gws.import_from_path( f'gws/plugin/ows_provider/{protocol}/caps.py') res = mod.parse(xml) js = gws.lib.json2.to_pretty_string(res, default=_caps_json) if p.out: gws.write_file(p.out, js) gws.log.info(f'saved to {p.out!r}') else: print(js)
def _handle_error(req: WebRequest, err: gws.base.web.error.HTTPException) -> WebResponse: # @TODO: image errors site = t.cast(gws.base.web.site.Object, req.site) if req.output_struct_type: return req.struct_response( gws.Response(error=gws.ResponseError( status=err.code, info=gws.get(err, 'description', '')))) if not site.error_page: return req.error_response(err) try: context = {'request': req, 'error': err.code} res = site.error_page.render(gws.TemplateRenderInput(context=context)) return req.content_response( gws.ContentResponse(content=res.content, mime=res.mime, status=err.code)) except: gws.log.exception() return req.error_response(gws.base.web.error.InternalServerError())
def configure(self): self.crs = self.var('crs') self.db = t.cast( gws.ext.db.provider.postgres.Object, gws.base.db.require_provider(self, 'gws.ext.db.provider.postgres')) self.templates: t.List[gws.ITemplate] = gws.base.template.bundle(self, self.var('templates')) self.qgis_template: gws.ITemplate = gws.base.template.find(self.templates, subject='bplan.qgis') self.info_template: gws.ITemplate = gws.base.template.find(self.templates, subject='bplan.info') self.plan_table = self.db.configure_table(self.var('planTable')) self.meta_table = self.db.configure_table(self.var('metaTable')) self.data_dir = self.var('dataDir') self.au_list = self.var('administrativeUnits') self.type_list = self.var('planTypes') self.image_quality = self.var('imageQuality') p = self.var('exportDataModel') self.export_data_model: t.Optional[gws.IDataModel] = self.create_child('gws.base.model', p) if p else None for sub in 'png', 'pdf', 'cnv', 'qgs': gws.ensure_dir(self.data_dir + '/' + sub) self.key_col = 'plan_id' self.au_key_col = 'ags' self.au_name_col = 'gemeinde' self.type_col = 'typ' self.time_col = 'rechtskr' self.x_coord_col = 'utm_ost' self.y_coord_col = 'utm_nord' gws.write_file(_RELOAD_FILE, gws.random_string(16)) self.root.application.monitor.add_path(_RELOAD_FILE)
def shape_to_fragment(shape: gws.IShape, view: gws.MapView, style: gws.IStyle = None, label: str = None) -> t.List[gws.XmlElement]: if not shape: return [] geom = t.cast(gws.gis.shape.Shape, shape).geom if geom.is_empty: return [] trans = gws.gis.render.map_view_transformer(view) geom = shapely.ops.transform(trans, geom) if not style: return [_geometry(geom)] sv = style.values with_geometry = sv.with_geometry == 'all' with_label = label and _is_label_visible(view, sv) gt = _geom_type(geom) text = None if with_label: extra_y_offset = 0 if sv.label_offset_y is None: if gt == _TYPE_POINT: extra_y_offset = 12 if gt == _TYPE_LINESTRING: extra_y_offset = 6 text = _label(geom, label, sv, extra_y_offset) marker = None marker_id = None if with_geometry and sv.marker: marker_id = '_M' + gws.random_string(8) marker = _marker(marker_id, sv) icon = None atts: dict = {} if with_geometry and sv.icon: res = _parse_icon(sv.icon, view.dpi) if res: el, w, h = res x, y, w, h = _icon_size_position(geom, sv, w, h) atts = { 'x': f'{int(x)}', 'y': f'{int(y)}', 'width': f'{int(w)}', 'height': f'{int(h)}', } icon = xml2.element(name=el.name, attributes=gws.merge(el.attributes, atts), children=el.children) body = None if with_geometry: _add_paint_atts(atts, sv) if marker: atts['marker-start'] = atts['marker-mid'] = atts[ 'marker-end'] = f'url(#{marker_id})' if gt == _TYPE_POINT or gt == _TYPE_MULTIPOINT: atts['r'] = (sv.point_size or DEFAULT_POINT_SIZE) // 2 if gt == _TYPE_LINESTRING or gt == _TYPE_MUTLILINESTRING: atts['fill'] = 'none' body = _geometry(geom, atts) return gws.compact([marker, body, icon, text])
def do_reload(self, p: ReloadParams): """Reload specific (or all) server modules""" if not reload(p.modules): gws.log.info('server not running, starting') self.do_start(t.cast(StartParams, p))