Пример #1
0
def create(root: gws.IRoot,
           cfg: gws.Config,
           parent: gws.Node = None,
           shared: bool = False) -> Object:
    key = gws.get(cfg, 'uid') or gws.get(cfg, 'path') or gws.sha256(
        gws.get(cfg, 'text', default=''))
    return root.create_object('gws.ext.template', cfg, parent, shared, key)
Пример #2
0
def _res_or_scale(cfg, r, s):
    x = gws.get(cfg, r)
    if x:
        return x
    x = gws.get(cfg, s)
    if x:
        return units.scale_to_res(x)
Пример #3
0
def _entries(root: gws.IRoot, mpx_config, layer_uids=None):
    caches: gws.Dict[str, Entry] = {}

    for layer in root.find_all('gws.ext.layer'):

        if layer_uids and layer.uid not in layer_uids:
            continue

        for uid, cc in mpx_config['caches'].items():
            if cc.get('disable_storage') or gws.get(layer, 'cache_uid') != uid:
                continue

            if uid in caches:
                caches[uid].layers.append(layer)
                continue

            cfg = gws.get(layer, 'cache')
            grids = [mpx_config['grids'][g] for g in cc['grids']]
            crs = grids[0]['srs'].replace(':', '')

            caches[uid] = Entry(
                uid=uid,
                layers=[layer],
                mpx_cache=cc,
                mpx_grids=grids,
                config=vars(cfg) if cfg else {},
                counts={},
                dirname=f'{gws.MAPPROXY_CACHE_DIR}/{uid}_{crs}',
            )

    return list(caches.values())
Пример #4
0
def _explicit_resolutions(cfg):
    ls = gws.get(cfg, 'resolutions')
    if ls:
        return ls

    ls = gws.get(cfg, 'scales')
    if ls:
        return [units.scale_to_res(x) for x in ls]
Пример #5
0
def _configure_extent(obj, crs: gws.ICrs, default_ext):
    layers = gws.get(obj, 'layers') or []

    # we have an explicit extent provided in the config

    config_ext = obj.var('extent')

    if config_ext:
        ext = gws.gis.extent.from_list(config_ext)
        if not ext:
            raise gws.Error(f'{obj.uid!r}: invalid extent {config_ext!r}')

        # configure sublayers using config_ext as a default
        for la in layers:
            _configure_extent(la, crs, ext)

        obj.extent = ext
        return obj.extent

    if layers:
        # no config extent, configure sublayers using the current default extent
        # set obj.extent to the sum of sublayers' extents

        layer_ext_list = []
        for la in layers:
            layer_ext = _configure_extent(la, crs, default_ext)
            if layer_ext:
                layer_ext_list.append(layer_ext)

        if layer_ext_list:
            obj.extent = gws.gis.extent.merge(layer_ext_list)
        else:
            obj.extent = default_ext
        return obj.extent

    # obj is a leaf layer and has no configured extent
    # check if it has an own extent (from its source)

    own_bounds: gws.Bounds = gws.get(obj, 'own_bounds')

    if own_bounds:
        own_ext = own_bounds.extent
        buf = obj.var('extentBuffer', with_parent=True)
        if buf:
            own_ext = gws.gis.extent.buffer(own_ext, buf)
        own_ext = gws.gis.extent.transform(own_ext, own_bounds.crs, crs)
        obj.extent = own_ext
        return obj.extent

    # obj is a leaf layer and has neither configured nor own extent
    # try using the default extent

    if default_ext:
        obj.extent = default_ext
        return obj.extent

    # no extent can be computed, it will be set to the map extent later on
    return None
Пример #6
0
    def _before_init(cfg):
        autorun = gws.get(cfg, 'server.autoRun')
        if autorun:
            gws.log.info(f'AUTORUN: {autorun!r}')
            cmds = shlex.split(autorun)
            gws.lib.os2.run(cmds, echo=True)

        timezone = gws.get(cfg, 'server.timeZone')
        if timezone:
            gws.lib.date.set_system_time_zone(timezone)
Пример #7
0
    def search_config(self, source_layers):
        default = {
            'type': 'qgiswms',
            '_provider': self,
            '_source_layers': source_layers,
        }

        if len(self.source_layers) > 1 or self.source_layers[0].is_group:
            return default

        sl = source_layers[0]
        ds = sl.data_source
        prov = ds.get('provider')

        if prov not in self.direct_search:
            return default

        if prov == 'wms':
            layers = ds.get('layers')
            if layers:
                return {
                    'type': 'wms',
                    'sourceLayers': {
                        'names': ds['layers']
                    },
                    'url': self.make_wms_url(ds['url'], ds['params']),
                }

        if prov == 'postgres':
            tab = sl.data_source.get('table')

            # 'table' can also be a select statement, in which case it might be enclosed in parens
            if not tab or tab.startswith('(') or tab.upper().startswith(
                    'SELECT '):
                return

            return {'type': 'qgispostgres', '_data_source': ds}

        if prov == 'wfs':
            cfg = {
                'type': 'wfs',
                'url': ds['url'],
            }
            if gws.get(ds, 'typeName'):
                cfg['sourceLayers'] = {'names': [ds['typeName']]}
            crs = gws.get(ds, 'params.srsname')
            inv = gws.get(ds, 'params.InvertAxisOrientation')
            if inv == '1' and crs:
                cfg['invertAxis'] = [crs]

            return cfg

        gws.log.warn(f'directSearch not supported for {prov!r}')
        return default
Пример #8
0
    def _load_db_meta(self):
        metas = {}
        meta_dates = {}

        def _date(s):
            return gws.lib.date.to_iso(gws.lib.date.to_utc(s), with_tz='Z')

        with self.db.connect() as conn:
            rs = conn.select(f'''SELECT * FROM {conn.quote_table(self.meta_table.name)}''')
            for r in rs:
                au_uid = r['_au']
                metas[au_uid] = gws.lib.metadata.from_dict(gws.lib.json2.from_string(r['meta']))
                meta_dates[au_uid] = _date(r['_updated'])

            rs = conn.select(f'''
                SELECT _au, 
                    MIN(_updated) AS min_updated, 
                    MAX(_updated) AS max_updated,
                    MIN(CASE WHEN {self.time_col} != '' THEN DATE({self.time_col}) ELSE _updated END) AS min_time,
                    MAX(CASE WHEN {self.time_col} != '' THEN DATE({self.time_col}) ELSE _updated END) AS max_time
                FROM {conn.quote_table(self.plan_table.name)}
                GROUP BY _au
            ''')

            for r in rs:
                au_uid = r['_au']
                if au_uid not in metas:
                    metas[au_uid] = gws.Values()

                metas[au_uid].dateCreated = _date(r['min_updated'])
                metas[au_uid].dateUpdated = _date(r['max_updated'])
                md = meta_dates.get(au_uid)
                if md and md < metas[au_uid].dateCreated:
                    metas[au_uid].dateCreated = md
                if md and md > metas[au_uid].dateUpdated:
                    metas[au_uid].dateUpdated = md

                metas[au_uid].dateBegin = _date(r['min_time'])
                metas[au_uid].dateEnd = _date(r['max_time'])

        # extend metadata for "our" objects

        for obj in self.root.find_all():
            uid = gws.get(obj, 'uid') or ''
            if uid and gws.get(obj, 'meta'):
                for au_uid, meta in metas.items():
                    if uid.endswith(au_uid):
                        obj.meta = gws.lib.metadata.extend(meta, obj.meta)
                        if gws.get(obj, 'update_sequence'):
                            obj.update_sequence = meta.dateUpdated
Пример #9
0
    def _create_index(self):
        self.index = []

        for uid, md in self.records.items():
            s = gws.get(md, 'title')
            if s:
                self.index.append(['title', s, s.lower(), uid])
            s = gws.get(md, 'abstract')
            if s:
                self.index.append(['abstract', s, s.lower(), uid])
            s = gws.get(md, 'keywords')
            if s:
                for kw in s:
                    self.index.append(('subject', kw, kw.lower(), uid))
Пример #10
0
    def _get_elements(self, parent_client):
        elements = self.var('elements')
        if elements:
            return elements

        if not parent_client:
            return []

        elements = list(gws.get(parent_client, 'elements', []))

        add = self.var('addElements', default=[])

        for c in add:
            n = self._find_element(elements, c.tag)
            if n >= 0:
                elements.pop(n)
            if c.before:
                n = self._find_element(elements, c.before)
                if n >= 0:
                    elements.insert(n, c)
            elif c.after:
                n = self._find_element(elements, c.after)
                if n >= 0:
                    elements.insert(n + 1, c)
            else:
                elements.append(c)

        remove = self.var('removeElements', default=[])
        remove_tags = [c.tag for c in remove]
        return [e for e in elements if e.tag not in remove_tags]
Пример #11
0
def parse_dict(d: dict, trusted, with_strict_mode) -> dict:
    res = dict(_DEFAULTS)

    for key, val in d.items():
        if val is None:
            continue
        k = key.replace('-', '_')
        if k.startswith('__'):
            k = k[2:]

        fn = gws.get(_ParseFunctions, k)

        if not fn:
            err = f'style: invalid css property {key!r}'
            if with_strict_mode:
                raise gws.Error(err)
            else:
                gws.log.error(err)
                continue

        try:
            v = fn(val, trusted)
            if v is not None:
                res[k] = v
        except Exception as exc:
            err = f'style: invalid css value for {key!r}'
            if with_strict_mode:
                raise gws.Error(err) from exc
            else:
                gws.log.error(err)

    return res
Пример #12
0
    def configure(self):
        parent_client = self.var('parentClient')

        self.elements = self.create_children(Element, self._get_elements(parent_client))

        opts = self.var('options')
        if not opts and parent_client:
            opts = gws.get(parent_client, 'options', {})
        self.options = opts or {}
Пример #13
0
def _run(
        req: gws.IWebRequest,
        args: gws.SearchArgs,
        provider: gws.ISearchProvider,
        total_limit,
        features,
        layer: t.Optional[gws.ILayer] = None,
        project: t.Optional[gws.IProject] = None,
):
    args.limit = total_limit - len(features)
    if args.limit <= 0:
        raise _LimitExceeded()

    gws.log.debug(
        'SEARCH_BEGIN: prov=%r layer=%r limit=%d' % (gws.get(provider, 'uid'), gws.get(layer, 'uid'), args.limit))

    if not req.user.can_use(provider, context=layer or project):
        gws.log.debug('SEARCH_END: NO_ACCESS')
        return

    if not provider.can_run(args):
        gws.log.debug(f'SEARCH_END: N_A')
        return

    try:
        fs: t.List[gws.IFeature] = provider.run(args, layer) or []
    except:
        gws.log.exception('SEARCH_FAILED')
        return

    tt = provider.templates or (layer.templates if layer else None)
    dm = provider.data_model or (layer.data_model if layer else None)

    for f in fs:
        f.layer = layer
        f.category = provider.title or (layer.title if layer else '')
        f.templates = tt
        f.data_model = dm

    gws.log.debug('SEARCH_END, found=%r', len(fs))

    features.extend(fs)
Пример #14
0
    def _xml_error(self, err: Exception):
        try:
            status = int(gws.get(err, 'code', 500))
        except Exception:
            status = 500

        description = xml2.encode(
            gws.get(err, 'description') or f'Error {status}')

        xml = (
            f'<?xml version="1.0" encoding="UTF-8"?>' +
            f'<ServiceExceptionReport>' +
            f'<ServiceException code="{status}">{description}</ServiceException>'
            + f'</ServiceExceptionReport>')

        # @TODO status, check OGC 17-007r1

        return gws.ContentResponse(mime=gws.lib.mime.XML,
                                   content=xml,
                                   status=200)
Пример #15
0
def create(root: gws.IRoot):
    mc = _Config()

    for layer in root.find_all('gws.ext.layer'):
        m = getattr(layer, 'mapproxy_config')
        if m:
            m(mc)

    cfg = mc.to_dict()
    if not cfg.get('layers'):
        return

    crs: t.List[gws.ICrs] = []
    for p in root.find_all('gws.base.map'):
        crs.append(gws.get(p, 'crs'))
    for p in root.find_all('gws.ext.ows.service'):
        crs.extend(gws.get(p, 'supported_crs', default=[]))
    cfg['services']['wms']['srs'] = sorted(set(c.epsg for c in crs))

    return cfg
Пример #16
0
    def _get_crs(self, js):
        p = js.get('crs')
        if not p:
            return

        if p.get('type') == 'name':
            crs = gws.gis.crs.get(gws.get(p, 'properties.name'))
            if crs:
                return crs

        raise gws.Error(f'unsupported geojson crs format')
Пример #17
0
    def _collect_metadata(self):
        # collect objects whose metadata should be published in the catalog
        #
        # - object should have `metadata`
        # - object must be public
        # - `metadata` should have `catalogUid`
        # - `metadata.metaLinks` should be empty
        #
        # `metadata.metaLinks[0]` will be set to our csw url

        self.records = {}

        for obj in self.root.find_all():
            md: gws.lib.metadata.Metadata = gws.get(obj, 'metadata')

            if not md or not md.get('catalogUid'):
                continue

            cid = gws.to_uid(md.get('catalogUid'))

            if md.get('metaLinks'):
                gws.log.debug(f'csw: skip {cid}: has metalinks')
                continue

            if not gws.is_public_object(obj):
                gws.log.debug(f'csw: skip {cid}: not public')
                continue

            md.set('catalogUid', cid)
            md.set('catalogCitationUid', cid)
            md.set('metaLinks', [self._make_link(cid)])

            extent = gws.get(obj, 'extent') or gws.get(obj, 'map.extent')
            crs = gws.get(obj, 'crs') or gws.get(obj, 'map.crs')
            if extent and crs:
                md.set('extent4326',
                       gws.gis.extent.transform_to_4326(extent, crs))
                md.set('crs', crs)
                # @TODO get boundingPolygonElement somehow

            self.records[cid] = md
Пример #18
0
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())
Пример #19
0
    def get_tile_url(self):
        resource_url = gws.get(self.source_layer, 'resource_urls.tile')

        if resource_url:
            return (resource_url
                    .replace('{TileMatrixSet}', self.tile_matrix_set.uid)
                    .replace('{TileMatrix}', '%(z)02d')
                    .replace('{TileCol}', '%(x)d')
                    .replace('{TileRow}', '%(y)d')
                    .replace('{Style}', self.style_name or 'default'))

        operation = self.provider.operation(gws.OwsVerb.GetTile)

        params = {
            'SERVICE': 'WMTS',
            'REQUEST': 'GetTile',
            'VERSION': self.provider.version,
            'LAYER': self.source_layer.name,
            'FORMAT': self.source_layer.image_format or 'image/jpeg',
            'TILEMATRIXSET': self.tile_matrix_set.uid,
            'TILEMATRIX': '%(z)02d',
            'TILECOL': '%(x)d',
            'TILEROW': '%(y)d',
        }

        if self.style_name:
            params['STYLE'] = self.style_name

        pu = gws.lib.net.parse_url(operation.get_url)
        params.update(pu.params)

        # NB cannot use as_query_string because of the MP's percent formatting

        qs = '&'.join(k + '=' + str(v or '') for k, v in params.items())

        return gws.lib.net.make_url(pu, params={}) + '?' + qs
Пример #20
0
 def __init__(self, options, instance, cache_lifetime=None):
     self.options = options
     self.instance = instance or 'none'
     self.cache_lifetime = cache_lifetime
     self.position = gws.get(self.options, 'position')
Пример #21
0
def _pval(props, key):
    return gws.get(props, key.lower())
Пример #22
0
def _set_default_extent(obj, extent):
    if not gws.get(obj, 'extent'):
        obj.extent = extent
    for la in gws.get(obj, 'layers', []):
        _set_default_extent(la, extent)