From cb973a10b03c7bcf2285f1013831fa2c6a4b925a Mon Sep 17 00:00:00 2001 From: m431m <4568458+m431m@users.noreply.github.com> Date: Thu, 9 Jul 2020 16:00:14 +0200 Subject: [PATCH] Added tileindex support for coverage store (#8) --- requirements.txt | 2 +- setup.py | 3 +-- src/metadata.py | 1 + src/mra.py | 34 ++++++++++++++++++++++------------ src/stores.py | 40 +++++++++++++++++++++++++++++++++------- 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/requirements.txt b/requirements.txt index 8b221e2..f9bfb48 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ web.py>=0.50,<0.60 +gdal<2.5.0 pyyaml -gdal<2.5.0 \ No newline at end of file diff --git a/setup.py b/setup.py index f47bc7b..45895dc 100644 --- a/setup.py +++ b/setup.py @@ -36,11 +36,10 @@ def parse_requirements(filename): dirname = os.path.dirname(__file__) -reqs_filename = os.path.join(dirname, 'requirements.txt') +reqs_filename = os.path.join(dirname, 'requirements.txt') reqs = [str(req) for req in parse_requirements(reqs_filename)] - setup( name="MapServer Rest API", version=version, diff --git a/src/metadata.py b/src/metadata.py index ffc0260..5911742 100644 --- a/src/metadata.py +++ b/src/metadata.py @@ -83,6 +83,7 @@ def get_metadata_keys(obj): def set_metadata(obj, key, value): + # TODO: Fix this with upgrade to py3 try: obj.setMetaData(key, value) except UnicodeEncodeError: diff --git a/src/mra.py b/src/mra.py index e0d7076..b60a2ad 100644 --- a/src/mra.py +++ b/src/mra.py @@ -642,13 +642,21 @@ class CoverageModel(LayerModel): info = ws.get_coveragestore_info(cs_name) cparam = info["connectionParameters"] - # if cparam["dbtype"] in ["tif", "tiff"]: self.ms.connectiontype = mapscript.MS_RASTER url = urllib.parse.urlparse(cparam["url"]) - self.ms.data = self.ws.mra.get_file_path(url.path) - # TODO: strip extention. - # else: - # raise ValueError("Unhandled type \"%s\"." % cparam["dbtype"]) + filename = self.ws.mra.get_file_path(url.path) + if cs.tindex is None: + #if cparam["dbtype"] in ["tif", "tiff"]: + self.ms.data = filename + self.ms.tileindex = None + self.ms.tileitem = None + # TODO: strip extention. + #else: + # raise ValueError("Unhandled type \"%s\"." % cparam["dbtype"]) + else: + self.ms.data = None + self.ms.tileindex = cs.get_tileindex() + self.ms.tileitem = cs.get_tileitem() # Update mra metadatas, and make sure the mandatory ones are left untouched. self.update_mra_metadatas(metadata) @@ -673,6 +681,8 @@ class CoverageModel(LayerModel): layer.ms.data = self.ms.data layer.ms.connectiontype = self.ms.connectiontype layer.ms.connection = self.ms.connection + layer.ms.tileindex = self.ms.tileindex + layer.ms.tileitem = self.ms.tileitem layer_name = self.get_mra_metadata("name") @@ -889,18 +899,18 @@ class Workspace(Mapfile): def create_layermodel(self, st_type, store, name, metadata={}): if self.has_layermodel(st_type, store, name): raise KeyExists((st_type, store, name)) - ft = self.__ms2model(mapscript.layerObj(self.ms), st_type=st_type) + lm = self.__ms2model(mapscript.layerObj(self.ms), st_type=st_type) - ft.update(store, name, metadata) - return ft + lm.update(store, name, metadata) + return lm def update_layermodel(self, st_type, store, name, metadata={}): - ft = self.get_layermodel(st_type, store, name) - ft.update(store, name, metadata) + lm = self.get_layermodel(st_type, store, name) + lm.update(store, name, metadata) def delete_layermodel(self, st_type, ds_name, ft_name): - model = self.get_layermodel(st_type, ds_name, ft_name) - if model.get_mra_metadata("layers", []): + lm = self.get_layermodel(st_type, ds_name, ft_name) + if lm.get_mra_metadata("layers", []): raise ValueError("The %s \"%s\" can't be delete because it is used." % (st_type, ft_name)) self.ms.removeLayer(model.ms.index) diff --git a/src/stores.py b/src/stores.py index 1a46b96..87a16ae 100644 --- a/src/stores.py +++ b/src/stores.py @@ -287,7 +287,7 @@ class Featuretype(object): def iterfeatures(self, what=[], when={}): if what != [] or when != {}: raise NotImplementedError("Iterfeature doesn't support filters yet.") - for i in range(self.backend.GetFeatureCount()): + for i in range(self.nbfeatures()): yield Feature(self.backend.GetFeature(i), self) def get_aditional_info(self): @@ -369,6 +369,8 @@ class Band(object): class Coveragestore(object): """A coveragestore implementation backed by gdal.""" + tindex = None + def __init__(self, path): """Path will be used to open the store, it can be a simple filesystem path or something more complex used by gdal/ogr to access databases for example. @@ -377,6 +379,14 @@ class Coveragestore(object): """ self.backend = path if isinstance(path, gdal.Dataset) else gdal.Open(path) + if self.backend is None: + ds = Datastore(path if isinstance(path, ogr.DataSource) else ogr.Open(path)) + if ds: + self.tindex = Featuretype(ds.backend.GetLayerByIndex(0), ds) + path = getattr( + self.tindex.backend.GetFeature(0), self.get_tileitem()) + self.backend = gdal.Open(str(path)) + if self.backend is None: raise ValueError("Coveragestore backend could not be opened. \"%s\"." % path) @@ -387,7 +397,7 @@ class Coveragestore(object): return self.iterbands() def __contains__(self, idx): - return 0 < idx and idx < self.backend.RasterCount + return idx > 0 and idx < self.backend.RasterCount def __getitem__(self, idx): band = self.backend.GetRasterBand(idx) @@ -408,12 +418,15 @@ class Coveragestore(object): return corners def get_extent(self): + if self.tindex is not None: + return self.tindex.get_extent() + #else: corners = self.get_corners() - minX = min(x for x, y in corners) - minY = min(y for x, y in corners) - maxX = max(x for x, y in corners) - maxY = max(y for x, y in corners) - return Extent(minX, minY, maxX, maxY) + minx = min(x for x, y in corners) + miny = min(y for x, y in corners) + maxx = max(x for x, y in corners) + maxy = max(y for x, y in corners) + return Extent(minx, miny, maxx, maxy) def get_latlon_extent(self): rect = mapscript.rectObj(*self.get_extent()) @@ -436,3 +449,16 @@ class Coveragestore(object): def iterbands(self): for i in range(1, self.backend.RasterCount + 1): yield Band(self.backend.GetRasterBand(i)) + + def get_tileindex(self): + """Return the path to the index file.""" + if self.tindex is None: + return None + return self.tindex.ds.backend.GetName() + + def get_tileitem(self): + """Return the field in the shapefile which contains + the filenames referenced by the index.""" + if self.tindex is None: + return None + return self.tindex.backend.GetLayerDefn().GetFieldDefn(0).name -- GitLab