def get_metadata(self, dataset, server_url, layer=None, tileset=None, tilejson=True, **kwargs): """ Gets tile metadata :param dataset: dataset name :param server_url: server base url :param layer: mvt tile layer name :param tileset: mvt tileset name :param tilejson: `bool` for the returning json structure if True it returns MapBox TileJSON 3.0 otherwise the raw JSON is served :returns: `dict` of JSON metadata """ if is_url(self.data): url = urlparse(self.data) base_url = '{}://{}'.format(url.scheme, url.netloc) with requests.Session() as session: session.get(base_url) resp = session.get('{base_url}/{lyr}/metadata.json'.format( base_url=base_url, lyr=layer)) resp.raise_for_status() content = resp.json() else: if not isinstance(self.service_metadata_url, Path): msg = 'Wrong data path configuration: {}'.format( self.service_metadata_url) LOGGER.error(msg) raise ProviderConnectionError(msg) with open(self.service_metadata_url, 'r') as md_file: content = json.loads(md_file.read()) if tilejson: service_url = urljoin( server_url, 'collections/{}/tiles/{}/{{{}}}/{{{}}}/{{{}}}{}'.format( dataset, tileset, 'tileMatrix', 'tileRow', 'tileCol', '?f=mvt')) content = { "tilejson": "3.0.0", "name": content["name"], "tiles": service_url, "minzoom": content["minzoom"], "maxzoom": content["maxzoom"], "bounds": content["bounds"], "center": content["center"], "attribution": None, "description": None, "vector_layers": json.loads(content["json"])["vector_layers"] } else: content['json'] = json.loads(content['json']) return content
def get_layer(self): if is_url(self.data): url = urlparse(self.data) return url.path.split("/{z}/{x}/{y}")[0][1:] else: return None
def geojson2geojsonld(config, data, dataset, identifier=None): """ Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be read from, and extended by, the pygeoapi configuration for a particular dataset. :param config: dict of configuration :param data: dict of data: :param dataset: dataset identifier :param identifier: item identifier (optional) :returns: string of rendered JSON (GeoJSON-LD) """ context = config['resources'][dataset].get('context', []) data['id'] = ('{}/collections/{}/items/{}' if identifier else '{}/collections/{}/items').format( *[config['server']['url'], dataset, identifier]) if data.get('timeStamp', False): data['https://schema.org/sdDatePublished'] = data.pop('timeStamp') defaultVocabulary = "https://geojson.org/geojson-ld/geojson-context.jsonld" ldjsonData = {"@context": [defaultVocabulary, *(context or [])], **data} isCollection = identifier is None if isCollection: for i, feature in enumerate(data['features']): featureId = feature.get('id', None) or feature.get( 'properties', {}).get('id', None) if featureId is None: continue # Note: @id or https://schema.org/url or both or something else? if is_url(str(featureId)): feature['id'] = featureId else: feature['id'] = '{}/{}'.format(data['id'], featureId) return json.dumps(ldjsonData)
def get_tiles(self, layer=None, tileset=None, z=None, y=None, x=None, format_=None): """ Gets tile :param layer: mvt tile layer :param tileset: mvt tileset :param z: z index :param y: y index :param x: x index :param format_: tile format :returns: an encoded mvt tile """ if format_ == "mvt": format_ = self.format_type if is_url(self.data): url = urlparse(self.data) base_url = '{}://{}'.format(url.scheme, url.netloc) with requests.Session() as session: session.get(base_url) resp = session.get('{base_url}/{lyr}/{z}/{y}/{x}.{f}'.format( base_url=base_url, lyr=layer, z=z, y=y, x=x, f=format_)) resp.raise_for_status() return resp.content else: if not isinstance(self.service_url, Path): msg = 'Wrong data path configuration: {}'.format( self.service_url) LOGGER.error(msg) raise ProviderConnectionError(msg) else: try: with open( self.service_url.joinpath('{z}/{y}/{x}.{f}'.format( z=z, y=y, x=x, f=format_)), 'rb') as tile: return tile.read() except FileNotFoundError as err: raise ProviderTileNotFoundError(err)
def __init__(self, provider_def): """ Initialize object :param provider_def: provider definition :returns: pygeoapi.provider.MVT.MVTProvider """ super().__init__(provider_def) if is_url(self.data): url = urlparse(self.data) baseurl = '{}://{}'.format(url.scheme, url.netloc) param_type = '?f=mvt' servicepath = \ '{}/tiles/{{{}}}/{{{}}}/{{{}}}/{{{}}}{}'.format( url.path.split('/{z}/{x}/{y}')[0], 'tileMatrixSetId', 'tileMatrix', 'tileRow', 'tileCol', param_type) self._service_url = url_join(baseurl, servicepath) self._service_metadata_url = urljoin( self.service_url.split('{tileMatrix}/{tileRow}/{tileCol}')[0], 'metadata') else: data_path = Path(self.data) if not data_path.exists(): msg = 'Service does not exist: {}'.format(self.data) LOGGER.error(msg) raise ProviderConnectionError(msg) self._service_url = data_path metadata_path = data_path.joinpath('metadata.json') if not metadata_path.exists(): msg = 'Service metadata does not exist: {}'.format( metadata_path.name) LOGGER.error(msg) raise ProviderConnectionError(msg) self._service_metadata_url = metadata_path
def geojson2jsonld(config, data, dataset, identifier=None, id_field='id'): """ Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be read from, and extended by, the pygeoapi configuration for a particular dataset. :param config: dict of configuration :param data: dict of data: :param dataset: dataset identifier :param identifier: item identifier (optional) :param id_field: item identifier_field (optional) :returns: string of rendered JSON (GeoJSON-LD) """ context = config['resources'][dataset].get('context', []).copy() defaultVocabulary = { 'schema': 'https://schema.org/', id_field: '@id', 'type': '@type' } if identifier: # Single jsonld defaultVocabulary.update( {'geosparql': 'http://www.opengis.net/ont/geosparql#'}) # Expand properties block data.update(data.pop('properties')) # Include multiple geometry encodings data['type'] = 'schema:Place' jsonldify_geometry(data) data[id_field] = identifier else: # Collection of jsonld defaultVocabulary.update({ 'features': 'schema:itemListElement', 'FeatureCollection': 'schema:itemList' }) data['@id'] = '{}/collections/{}/items/'.format( config['server']['url'], dataset) for i, feature in enumerate(data['features']): # Get URI for each feature identifier = feature.get(id_field, feature['properties'].get(id_field, '')) if not is_url(str(identifier)): identifier = '{}/collections/{}/items/{}'.format( config['server']['url'], dataset, feature['id']) data['features'][i] = { id_field: identifier, 'type': 'schema:Place' } if data.get('timeStamp', False): data['https://schema.org/sdDatePublished'] = data.pop('timeStamp') data['links'] = data.pop('links') ldjsonData = {'@context': [defaultVocabulary, *(context or [])], **data} return ldjsonData
def geojson2geojsonld(config, data, dataset, identifier=None, id_field='id'): """ Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be read from, and extended by, the pygeoapi configuration for a particular dataset. :param config: dict of configuration :param data: dict of data: :param dataset: dataset identifier :param identifier: item identifier (optional) :param id_field: item identifier_field (optional) :returns: string of rendered JSON (GeoJSON-LD) """ context = config['resources'][dataset].get('context', []) geojsonld = config['resources'][dataset].get('geojsonld', True) if identifier: # Single geojsonld if not geojsonld: data, geocontext = make_jsonld(data) data[id_field] = identifier else: data['id'] = identifier else: # Collection of geojsonld data['@id'] = '{}/collections/{}/items/'.format( config['server']['url'], dataset) for i, feature in enumerate(data['features']): identifier = feature.get(id_field, feature['properties'].get(id_field, '')) if not is_url(str(identifier)): identifier = '{}/collections/{}/items/{}'.format( config['server']['url'], dataset, feature['id']) if not geojsonld: feature, geocontext = make_jsonld(feature) geocontext.append({ "features": "schema:itemListElement", "FeatureCollection": "schema:itemList" }) # Note: @id or https://schema.org/url, both or something else? feature[id_field] = identifier else: feature['id'] = identifier data['features'][i] = feature if data.get('timeStamp', False): data['https://schema.org/sdDatePublished'] = data.pop('timeStamp') defaultVocabulary = "https://geojson.org/geojson-ld/geojson-context.jsonld" if not geojsonld: ldjsonData = { "@context": [{ "schema": "https://schema.org/", id_field: "@id", "type": "@type", }, *(context or []), *(geocontext or [])], **data } else: ldjsonData = { "@context": [defaultVocabulary, *(context or [])], **data } return ldjsonData