Skip to content
Snippets Groups Projects
Commit f67e7937 authored by m431m's avatar m431m :speech_balloon:
Browse files

Merge branch 'redmine-issues/14221' into 'develop'

Resolve REDMINE_ISSUE-14221

See merge request !5
parents a7e05ca5 1f4777f9
No related branches found
No related tags found
1 merge request!5REDMINE_ISSUE-14221 Numero de version accessible depuis l'API
web.py>=0.50,<0.60
web.py>=0.60,<0.70
gdal<2.5.0
pyyaml<5.4
......@@ -24,9 +24,7 @@
import os.path
from setuptools import setup
version = '1.1.8'
from src import __version__
def parse_requirements(filename):
......@@ -42,7 +40,7 @@ reqs = [str(req) for req in parse_requirements(reqs_filename)]
setup(
name="MapServer Rest API",
version=version,
version=__version__,
description="A RESTFul interface for MapServer",
author="Neogeo Technologies",
author_email="contact@neogeo.fr",
......
......@@ -20,3 +20,6 @@
# GNU General Public License for more details. #
# #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
__version__ = '1.1.9'
......@@ -96,7 +96,7 @@ OUTPUTFORMAT = {
imagemode=mapscript.MS_IMAGEMODE_FEATURE,
transparent=mapscript.MS_OFF,
options={"FORM": "SIMPLE", "STORAGE": "stream"})
},
},
'WMS': {
'PNG8': outputformat(
"AGG/PNG8", "png8", mimetype="image/png; mode=8bit",
......@@ -109,8 +109,8 @@ OUTPUTFORMAT = {
"AGG/JPEG", "jpeg", mimetype="image/jpeg",
imagemode=mapscript.MS_IMAGEMODE_RGB,
extension="jpg", options={"GAMMA": "0.75"})
}
}
}
class MetadataMixin(object):
......@@ -134,7 +134,8 @@ class Layer(MetadataMixin):
self.ms = backend
def enable(self, enabled=True):
wms = ("GetCapabilities", "GetMap", "GetFeatureInfo", "GetLegendGraphic", "DescribeLayer", "GetStyles")
wms = ("GetCapabilities", "GetMap", "GetFeatureInfo",
"GetLegendGraphic", "DescribeLayer", "GetStyles")
wcs = ("GetCapabilities", "GetCoverage", "DescribeCoverage")
wfs = ("GetCapabilities", "GetFeature", "DescribeFeatureType")
......@@ -147,11 +148,14 @@ class Layer(MetadataMixin):
self.set_metadata("wfs_enable_request", " ".join(wfs))
else:
self.ms.status = mapscript.MS_OFF
self.set_metadata("wms_enable_request", " ".join(["!%s" % m for m in wms]))
self.set_metadata("wms_enable_request",
" ".join(["!%s" % m for m in wms]))
if self.ms.type == 3:
self.set_metadata("wcs_enable_request", " ".join(["!%s" % m for m in wcs]))
self.set_metadata("wcs_enable_request",
" ".join(["!%s" % m for m in wcs]))
else:
self.set_metadata("wfs_enable_request", " ".join(["!%s" % m for m in wfs]))
self.set_metadata("wfs_enable_request",
" ".join(["!%s" % m for m in wfs]))
def get_type_name(self):
return {
......@@ -160,7 +164,7 @@ class Layer(MetadataMixin):
2: "POLYGON",
3: "RASTER",
4: "ANNOTATION",
}[self.ms.type]
}[self.ms.type]
def get_proj4(self):
return self.ms.getProjection()
......@@ -232,7 +236,8 @@ class Layer(MetadataMixin):
xmlsld.firstChild.getElementsByTagNameNS("*", "NamedLayer")[0]\
.getElementsByTagNameNS("*", "Name")[0].firstChild.data = sld_layer_name
except Exception as e:
logging.error("mra.py::Layer::add_style_sld: Bad sld (No NamedLayer/Name): %s", e)
logging.error(
"mra.py::Layer::add_style_sld: Bad sld (No NamedLayer/Name): %s", e)
raise ValueError("Bad sld (No NamedLayer/Name)")
new_sld = xmlsld.toxml()
......@@ -245,7 +250,8 @@ class Layer(MetadataMixin):
try:
ms_template_layer.applySLD(new_sld, sld_layer_name)
except Exception as e:
logging.error("mra.py::Layer::add_style_sld: Unable to access storage : %s", e)
logging.error(
"mra.py::Layer::add_style_sld: Unable to access storage : %s", e)
raise ValueError("Unable to access storage.")
for i in range(ms_template_layer.numclasses):
......@@ -270,9 +276,11 @@ class Layer(MetadataMixin):
return None
try:
style = open(os.path.join(os.path.dirname(__file__), "%s.sld" % s_name), encoding="utf-8").read()
style = open(os.path.join(os.path.dirname(__file__),
"%s.sld" % s_name), encoding="utf-8").read()
except IOError as OSError:
logging.warning("mra.py::Layer::set_default_style IOError %s", OSError)
logging.warning(
"mra.py::Layer::set_default_style IOError %s", OSError)
return
self.add_style_sld(mf, s_name, style)
......@@ -379,7 +387,8 @@ class Mapfile(MetadataMixin):
self.set_metadata("%s_enable_request" % ows, "*")
if 'onlineresource' in config:
onlineresource = urljoin(config.get('onlineresource'), self.ms.name)
onlineresource = urljoin(config.get(
'onlineresource'), self.ms.name)
self.set_metadata('ows_onlineresource', onlineresource)
fontset and self.ms.setFontSet(fontset)
......@@ -443,7 +452,7 @@ class Mapfile(MetadataMixin):
# Add metadata.
metadata = {
"wms_srs": self.get_metadata("ows_srs"),
}
}
metadata.update(l_metadata)
layer.update_metadatas(metadata)
......@@ -534,8 +543,10 @@ class FeatureTypeModel(LayerModel):
cparam = info["connectionParameters"]
if cparam.get("dbtype", None) in ["postgis", "postgres", "postgresql"]:
self.ms.connectiontype = mapscript.MS_POSTGIS
connection = "dbname=%s port=%s host=%s " % (cparam.get("database", "postgres"), cparam.get("port", "5432"), cparam.get("host", "localhost"))
connection += " ".join("%s=%s" % (p, cparam[p]) for p in ["user", "password"] if p in cparam)
connection = "dbname=%s port=%s host=%s " % (cparam.get(
"database", "postgres"), cparam.get("port", "5432"), cparam.get("host", "localhost"))
connection += " ".join("%s=%s" % (p, cparam[p])
for p in ["user", "password"] if p in cparam)
self.ms.connection = connection
self.ms.data = '%s FROM %s.%s' % (
ds[ft_name].get_geometry_column(),
......@@ -554,7 +565,8 @@ class FeatureTypeModel(LayerModel):
# Update mra metadata, and make sure the mandatory ones are left untouched.
self.update_mra_metadatas(metadata)
self.update_mra_metadatas({"name": ft_name, "type": "featuretype", "storage": ds_name})
self.update_mra_metadatas(
{"name": ft_name, "type": "featuretype", "storage": ds_name})
def configure_layer(self, layer, enabled=True):
ws = self.ws
......@@ -578,7 +590,7 @@ class FeatureTypeModel(LayerModel):
"type": self.get_mra_metadata("type"),
"storage": self.get_mra_metadata("storage"),
"workspace": ws.name,
})
})
layer.enable(enabled)
......@@ -596,7 +608,7 @@ class FeatureTypeModel(LayerModel):
"gml_%s_type" % field_name: field.get_type_gml(),
# "gml_%s_precision" % field_name
# "gml_%s_width" % field_name
})
})
geometry_column = ft.get_geometry_column()
if geometry_column is None:
......@@ -611,7 +623,7 @@ class FeatureTypeModel(LayerModel):
self.ms.extent.miny,
self.ms.extent.maxx,
self.ms.extent.maxy,
),
),
"ows_include_items": ",".join(field_names),
"gml_include_items": ",".join(field_names),
"gml_geometries": geometry_column,
......@@ -619,13 +631,13 @@ class FeatureTypeModel(LayerModel):
# TODO: Add gml_<geometry name>_occurances,
"wfs_srs": ws.get_metadata("ows_srs"),
"wfs_getfeature_formatlist": ",".join(list(OUTPUTFORMAT["WFS"].keys()))
})
})
if ft.get_fid_column() is not None:
layer.set_metadatas({
"wfs_featureid": ft.get_fid_column(),
"gml_featureid": ft.get_fid_column(),
})
})
plugins.extend("post_configure_vector_layer", self, ws, ds, ft, layer)
......@@ -645,7 +657,8 @@ class CoverageModel(LayerModel):
try:
crs = metadata.pop("crs")
proj4 = "+init=%s:%s" % (crs["authority_name"], crs["authority_code"])
proj4 = "+init=%s:%s" % (crs["authority_name"],
crs["authority_code"])
except Exception as e:
logging.warn('mra.py::MRA::CoverageModel.update error %s', e)
proj4 = cs.get_proj4()
......@@ -672,12 +685,12 @@ class CoverageModel(LayerModel):
url = urlparse(cparam["url"])
filename = self.ws.mra.get_file_path(url.path)
if cs.tindex is None:
#if cparam["dbtype"] in ["tif", "tiff"]:
# if cparam["dbtype"] in ["tif", "tiff"]:
self.ms.data = filename
self.ms.tileindex = None
self.ms.tileitem = None
# TODO: strip extention.
#else:
# else:
# raise ValueError("Unhandled type \"%s\"." % cparam["dbtype"])
else:
self.ms.data = None
......@@ -719,7 +732,7 @@ class CoverageModel(LayerModel):
"type": self.get_mra_metadata("type"),
"storage": self.get_mra_metadata("storage"),
"workspace": ws.name,
})
})
layer.set_metadatas({
"ows_name": layer_name,
......@@ -730,11 +743,11 @@ class CoverageModel(LayerModel):
self.ms.extent.miny,
self.ms.extent.maxx,
self.ms.extent.maxy,
),
),
"wcs_name": layer.get_metadata("wcs_name", None) or layer_name,
"wcs_label": layer.get_metadata("wcs_label", None) or layer_name,
"wcs_description": layer.get_metadata("wcs_description", None) or layer_name
})
})
layer.enable(enabled)
......@@ -843,7 +856,8 @@ class Workspace(Mapfile):
except (StopIteration, SystemError):
pass # No layers use our store, all OK.
else:
raise ValueError("The datastore \"%s\" can't be delete because it is used." % name)
raise ValueError(
"The datastore \"%s\" can't be delete because it is used." % name)
return self.delete_store("datastore", name)
# Coveragestores (this is c/p from datastores):
......@@ -886,7 +900,8 @@ class Workspace(Mapfile):
except (StopIteration, SystemError):
pass # No layers use our store, all OK.
else:
raise ValueError("The coveragestore \"%s\" can't be delete because it is used." % name)
raise ValueError(
"The coveragestore \"%s\" can't be delete because it is used." % name)
return self.delete_store("coveragestore", name)
# LayerModels:
......@@ -945,7 +960,8 @@ class Workspace(Mapfile):
def delete_layermodel(self, st_type, ds_name, ft_name):
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))
raise ValueError(
"The %s \"%s\" can't be delete because it is used." % (st_type, ft_name))
self.ms.removeLayer(lm.ms.index)
# Featuretypes
......@@ -998,7 +1014,7 @@ class MRA(object):
self.config = yaml.load(
open(config_path, "r"),
# Loader=yaml.FullLoader
)
)
except yaml.YAMLError as e:
exit("Error in configuration file: %s" % e)
......@@ -1025,7 +1041,8 @@ class MRA(object):
return os.path.relpath(path, self.get_path())
def get_resource_path(self, *args):
root = self.config["storage"].get("resources", self.get_path("resources"))
root = self.config["storage"].get(
"resources", self.get_path("resources"))
return self.get_path(root, *args)
def pub_resource_path(self, path):
......@@ -1052,7 +1069,8 @@ class MRA(object):
fontset.close
def get_font_path(self, *args):
root = self.config["storage"].get("fonts", self.get_resource_path("fonts"))
root = self.config["storage"].get(
"fonts", self.get_resource_path("fonts"))
return self.get_resource_path(root, *args)
def create_font(self, name, data=None):
......@@ -1074,7 +1092,8 @@ class MRA(object):
# Styles:
def get_style_path(self, *args):
root = self.config["storage"].get("styles", self.get_resource_path("styles"))
root = self.config["storage"].get(
"styles", self.get_resource_path("styles"))
return self.get_resource_path(root, *args)
def pub_style_path(self, path):
......@@ -1118,7 +1137,8 @@ class MRA(object):
# Files:
def get_file_path(self, *args):
root = self.config["storage"].get("data", self.get_resource_path("data"))
root = self.config["storage"].get(
"data", self.get_resource_path("data"))
return self.get_resource_path(root, *args)
def pub_file_path(self, path):
......@@ -1134,7 +1154,8 @@ class MRA(object):
# Available (get):
def get_available_path(self, *args):
root = self.config["storage"].get("available", self.get_path("available"))
root = self.config["storage"].get(
"available", self.get_path("available"))
return self.get_path(root, *args)
def pub_available_path(self, path):
......@@ -1169,12 +1190,14 @@ class MRA(object):
def delete_workspace(self, name):
# path = self.get_available_path("%s.ws.map" % name)
raise NotImplementedError("Method 'delete_workspace' is not yet available. (TODO)")
raise NotImplementedError(
"Method 'delete_workspace' is not yet available. (TODO)")
# Services:
def get_service_path(self, *args):
root = self.config["storage"].get("services", self.get_path("services"))
root = self.config["storage"].get(
"services", self.get_path("services"))
return self.get_path(root, *args)
def pub_service_path(self, path):
......@@ -1210,9 +1233,11 @@ class MRA(object):
cparam = info["connectionParameters"]
if cparam.get("dbtype", "") == "postgis":
# First mandatory
url = "PG:dbname=%s port=%s host=%s " % (cparam["database"], cparam["port"], cparam["host"])
url = "PG:dbname=%s port=%s host=%s " % (
cparam["database"], cparam["port"], cparam["host"])
# Then optionals:
url += " ".join("%s=%s" % (p, cparam[p]) for p in ["user", "password"] if p in cparam)
url += " ".join("%s=%s" % (p, cparam[p])
for p in ["user", "password"] if p in cparam)
return url
elif "url" in cparam:
url = urlparse(cparam["url"])
......@@ -1220,4 +1245,5 @@ class MRA(object):
raise ValueError("Only local files are suported.")
return self.get_file_path(url.path)
else:
raise ValueError("Unhandled type \"%s\"." % cparam.get("dbtype", "<unknown>"))
raise ValueError("Unhandled type \"%s\"." %
cparam.get("dbtype", "<unknown>"))
......@@ -44,6 +44,7 @@ import webapp
from webapp import get_data
from webapp import HTTPCompatible
from webapp import urlmap
from src import __version__
# Some helper functions first.
......@@ -64,6 +65,7 @@ class index(object):
@HTTPCompatible(authorized=["html"])
def GET(self, format):
return {
"version": href("version"),
"about/version": href("about/version"),
"workspaces": href("workspaces"),
"styles": href("styles"),
......@@ -76,6 +78,15 @@ class index(object):
}
class app_version(object):
"""To know about application version
"""
@HTTPCompatible()
def GET(self, format):
return {"mra": __version__}
class version(object):
"""To know about used versions...
......@@ -1661,6 +1672,8 @@ class OWSWorkspaceSettings(object):
# Index:
urlmap(index, "")
# App Version:
urlmap(app_version, "version")
# About version:
urlmap(version, "about", "version")
# Workspaces:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment