[processing] removed geoserver algorithms and moved postgis ones to qgis agorithms group

This commit is contained in:
Victor Olaya 2014-06-08 09:01:51 +02:00
parent 414d371376
commit 2073026f7c
29 changed files with 8 additions and 2240 deletions

View File

@ -1,6 +1,5 @@
FILE(GLOB PY_FILES *.py)
ADD_SUBDIRECTORY(admintools)
ADD_SUBDIRECTORY(gdal)
ADD_SUBDIRECTORY(grass)
ADD_SUBDIRECTORY(grass7)

View File

@ -1,81 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
AdminToolsAlgorithmProvider.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from PyQt4 import QtGui
from processing.core.AlgorithmProvider import AlgorithmProvider
from PostGISExecuteSQL import PostGISExecuteSQL
from ImportIntoPostGIS import ImportIntoPostGIS
from ImportVectorIntoGeoServer import ImportVectorIntoGeoServer
from CreateWorkspace import CreateWorkspace
from ImportRasterIntoGeoServer import ImportRasterIntoGeoServer
from DeleteWorkspace import DeleteWorkspace
from DeleteDatastore import DeleteDatastore
from CreateStyleGeoServer import CreateStyleGeoServer
class AdminToolsAlgorithmProvider(AlgorithmProvider):
def __init__(self):
AlgorithmProvider.__init__(self)
self.alglist = [
ImportVectorIntoGeoServer(),
ImportRasterIntoGeoServer(),
CreateWorkspace(),
DeleteWorkspace(),
DeleteDatastore(),
CreateStyleGeoServer(),
]
try:
self.alglist.append(ImportIntoPostGIS())
self.alglist.append(PostGISExecuteSQL())
except:
pass
def initializeSettings(self):
AlgorithmProvider.initializeSettings(self)
def unload(self):
AlgorithmProvider.unload(self)
def getName(self):
return 'gspg'
def getDescription(self):
return 'GeoServer/PostGIS tools'
def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__)
+ '/../../images/database.png')
def _loadAlgorithms(self):
self.algs = self.alglist
def supportsNonFileBasedOutput(self):
return False

View File

@ -1,7 +0,0 @@
FILE(GLOB PY_FILES *.py)
SET (WITH_INTERNAL_HTTPLIB TRUE CACHE BOOL "Use internal httplib2")
ADD_SUBDIRECTORY(geoserver)
PLUGIN_INSTALL(processing ./algs/admintools ${PY_FILES})

View File

@ -1,58 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
CreateMosaicDatastore.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterString import ParameterString
from processing.tools import dataobjects
class CreateMosaicDatastore(GeoServerToolsAlgorithm):
INPUT = "INPUT"
WORKSPACE = "WORKSPACE"
def processAlgorithm(self, progress):
self.createCatalog()
input = self.getParameterValue(self.INPUT)
workspaceName = self.getParameterValue(self.WORKSPACE)
connection = {
'shp': basepathname + '.shp',
'shx': basepathname + '.shx',
'dbf': basepathname + '.dbf',
'prj': basepathname + '.prj'}
workspace = self.catalog.get_workspace(workspaceName)
self.catalog.create_featurestore(basefilename, connection, workspace)
def defineCharacteristics(self):
self.addcaddBaseParameters()
self.name = "Import into GeoServer"
self.group = "GeoServer management tools"
self.addParameter(ParameterVector(self.INPUT, "Layer to import",
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterString(self.WORKSPACE, "Workspace"))

View File

@ -1,55 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
CreateStyleGeoServer.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterString import ParameterString
from processing.parameters.ParameterFile import ParameterFile
from processing.parameters.ParameterBoolean import ParameterBoolean
class CreateStyleGeoServer(GeoServerToolsAlgorithm):
STYLE = 'STYLE'
OVERWRITE = 'OVERWRITE'
NAME = 'NAME'
def processAlgorithm(self, progress):
self.createCatalog()
stylefile = self.getParameterValue(self.STYLE)
overwrite = self.getParameterValue(self.OVERWRITE)
name = self.getParameterValue(self.NAME)
self.catalog.create_style(name, stylefile, overwrite)
def defineCharacteristics(self):
self.addBaseParameters()
self.name = 'Add style'
self.group = 'GeoServer management tools'
self.addParameter(ParameterString(self.NAME, 'Style name'))
self.addParameter(ParameterFile(self.STYLE, 'Style SLD file'))
self.addParameter(ParameterBoolean(self.OVERWRITE, 'Overwrite'))

View File

@ -1,52 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
CreateWorkspace.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterString import ParameterString
from processing.outputs.OutputString import OutputString
class CreateWorkspace(GeoServerToolsAlgorithm):
WORKSPACE = 'WORKSPACE'
WORKSPACEURI = 'WORKSPACEURI'
def processAlgorithm(self, progress):
self.createCatalog()
workspaceName = self.getParameterValue(self.WORKSPACE)
workspaceUri = self.getParameterValue(self.WORKSPACEURI)
self.catalog.create_workspace(workspaceName, workspaceUri)
def defineCharacteristics(self):
self.addBaseParameters()
self.name = 'Create workspace'
self.group = 'GeoServer management tools'
self.addParameter(ParameterString(self.WORKSPACE, 'Workspace'))
self.addParameter(ParameterString(self.WORKSPACEURI, 'Workspace URI'))
self.addOutput(OutputString(self.WORKSPACE, 'Workspace'))

View File

@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
DeleteDatastore.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterString import ParameterString
class DeleteDatastore(GeoServerToolsAlgorithm):
DATASTORE = 'DATASTORE'
WORKSPACE = 'WORKSPACE'
def processAlgorithm(self, progress):
self.createCatalog()
datastoreName = self.getParameterValue(self.DATASTORE)
workspaceName = self.getParameterValue(self.WORKSPACE)
ds = self.catalog.get_store(datastoreName, workspaceName)
self.catalog.delete(ds, recurse=True)
def defineCharacteristics(self):
self.addBaseParameters()
self.name = 'Delete datastore'
self.group = 'GeoServer management tools'
self.addParameter(ParameterString(self.DATASTORE, 'Datastore name'))
self.addParameter(ParameterString(self.WORKSPACE, 'Workspace'))

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
DeleteWorkspace.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterString import ParameterString
class DeleteWorkspace(GeoServerToolsAlgorithm):
WORKSPACE = 'WORKSPACE'
def processAlgorithm(self, progress):
self.createCatalog()
workspaceName = self.getParameterValue(self.WORKSPACE)
ws = self.catalog.get_workspace(workspaceName)
self.catalog.delete(ws)
def defineCharacteristics(self):
self.addBaseParameters()
self.name = 'Delete workspace'
self.group = 'GeoServer management tools'
self.addParameter(ParameterString(self.WORKSPACE, 'Workspace'))

View File

@ -1,56 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
GeoserverToolsAlgorithm.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from PyQt4 import QtGui
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.parameters.ParameterString import ParameterString
from geoserver.catalog import Catalog
class GeoServerToolsAlgorithm(GeoAlgorithm):
URL = 'URL'
USER = 'USER'
PASSWORD = 'PASSWORD'
def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__)
+ '/../../images/geoserver.png')
def addBaseParameters(self):
self.addParameter(ParameterString(self.URL, 'URL',
'http://localhost:8080/geoserver/rest'))
self.addParameter(ParameterString(self.USER, 'User', 'admin'))
self.addParameter(ParameterString(self.PASSWORD, 'Password',
'geoserver'))
def createCatalog(self):
url = self.getParameterValue(self.URL)
user = self.getParameterValue(self.USER)
password = self.getParameterValue(self.PASSWORD)
self.catalog = Catalog(url, user, password)

View File

@ -1,61 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
ImportVectorIntoGeoServer.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterString import ParameterString
from processing.parameters.ParameterRaster import ParameterRaster
class ImportRasterIntoGeoServer(GeoServerToolsAlgorithm):
INPUT = 'INPUT'
WORKSPACE = 'WORKSPACE'
NAME = 'NAME'
def exportRasterLayer(self, inputFilename):
return inputFilename
def processAlgorithm(self, progress):
self.createCatalog()
inputFilename = self.getParameterValue(self.INPUT)
name = self.getParameterValue(self.NAME)
workspaceName = self.getParameterValue(self.WORKSPACE)
filename = self.exportRasterLayer(inputFilename)
workspace = self.catalog.get_workspace(workspaceName)
ds = self.catalog.create_coveragestore2(name, workspace)
ds.data_url = 'file:' + filename
self.catalog.save(ds)
def defineCharacteristics(self):
self.addBaseParameters()
self.name = 'Import raster into GeoServer'
self.group = 'GeoServer management tools'
self.addParameter(ParameterRaster(self.INPUT, 'Layer to import'))
self.addParameter(ParameterString(self.WORKSPACE, 'Workspace'))
self.addParameter(ParameterString(self.NAME, 'Store name'))

View File

@ -1,67 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
ImportVectorIntoGeoServer.py
---------------------
Date : October 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'October 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from qgis.core import *
from GeoServerToolsAlgorithm import \
GeoServerToolsAlgorithm
from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterString import ParameterString
from processing.tools import dataobjects
class ImportVectorIntoGeoServer(GeoServerToolsAlgorithm):
INPUT = 'INPUT'
WORKSPACE = 'WORKSPACE'
def processAlgorithm(self, progress):
self.createCatalog()
inputFilename = self.getParameterValue(self.INPUT)
layer = dataobjects.getObjectFromUri(inputFilename)
workspaceName = self.getParameterValue(self.WORKSPACE)
filename = dataobjects.exportVectorLayer(layer)
basefilename = os.path.basename(filename)
basepathname = os.path.dirname(filename) + os.sep \
+ basefilename[:basefilename.find('.')]
connection = {
'shp': basepathname + '.shp',
'shx': basepathname + '.shx',
'dbf': basepathname + '.dbf',
'prj': basepathname + '.prj',
}
workspace = self.catalog.get_workspace(workspaceName)
self.catalog.create_featurestore(basefilename, connection, workspace)
def defineCharacteristics(self):
self.addBaseParameters()
self.name = 'Import vector into GeoServer'
self.group = 'GeoServer management tools'
self.addParameter(ParameterVector(self.INPUT, 'Layer to import',
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterString(self.WORKSPACE, 'Workspace'))

View File

@ -1,3 +0,0 @@
FILE(GLOB PY_FILES *.py)
PLUGIN_INSTALL(processing ./algs/admintools/geoserver ${PY_FILES})

View File

@ -1,572 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
catalog.py
---------------------
Date : November 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from datetime import datetime, timedelta
import logging
from os import unlink
from xml.etree.ElementTree import XML
from xml.parsers.expat import ExpatError
from urlparse import urlparse
from layer import Layer
from style import Style
from store import coveragestore_from_index, \
datastore_from_index, UnsavedDataStore, UnsavedCoverageStore
from support import prepare_upload_bundle, url
from layergroup import LayerGroup, \
UnsavedLayerGroup
from workspace import workspace_from_index, \
Workspace
import httplib2
logger = logging.getLogger('gsconfig.catalog')
class UploadError(Exception):
pass
class ConflictingDataError(Exception):
pass
class AmbiguousRequestError(Exception):
pass
class FailedRequestError(Exception):
pass
def _name(named):
"""Get the name out of an object.
This varies based on the type of the input:
* the "name" of a string is itself
* the "name" of None is itself
* the "name" of an object with a property named name is that
property - as long as it's a string
* otherwise, we raise a ValueError
"""
if isinstance(named, basestring) or named is None:
return named
elif hasattr(named, 'name') and isinstance(named.name, basestring):
return named.name
else:
raise ValueError(
"Can't interpret %s as a name or a configuration object"
% named)
class Catalog(object):
"""The GeoServer catalog represents all of the information in the
GeoServer configuration. This includes:
- Stores of geospatial data
- Resources, or individual coherent datasets within stores
- Styles for resources
- Layers, which combine styles with resources to create a visible map
layer
- LayerGroups, which alias one or more layers for convenience
- Workspaces, which provide logical grouping of Stores
- Maps, which provide a set of OWS services with a subset of the server's
Layers
- Namespaces, which provide unique identifiers for resources
"""
def __init__(self, service_url, username='admin', password='geoserver',
disable_ssl_certificate_validation=False):
self.service_url = service_url
if self.service_url.endswith('/'):
self.service_url = self.service_url.strip('/')
self.http = httplib2.Http(
disable_ssl_certificate_validation=disable_ssl_certificate_validation)
self.username = username
self.password = password
self.http.add_credentials(self.username, self.password)
netloc = urlparse(service_url).netloc
self.http.authorizations.append(httplib2.BasicAuthentication(
(username, password),
netloc,
service_url,
{},
None,
None,
self.http,
))
self._cache = dict()
def delete(self, config_object, purge=False, recurse=False):
"""Send a delete request
"""
rest_url = config_object.href
# params aren't supported fully in httplib2 yet, so:
params = []
# purge deletes the SLD from disk when a style is deleted
if purge:
params.append('purge=true')
# recurse deletes the resource when a layer is deleted.
if recurse:
params.append('recurse=true')
if params:
rest_url = rest_url + '?' + '&'.join(params)
headers = {'Content-type': 'application/xml',
'Accept': 'application/xml'}
(response, content) = self.http.request(rest_url, 'DELETE',
headers=headers)
self._cache.clear()
if response.status == 200:
return (response, content)
else:
raise FailedRequestError(
'Tried to make a DELETE request to %s but got a %d \
status code: \n%s'
% (rest_url, response.status, content))
def get_xml(self, rest_url):
logger.debug('GET %s', rest_url)
cached_response = self._cache.get(rest_url)
def is_valid(cached_response):
return cached_response is not None and datetime.now() \
- cached_response[0] < timedelta(seconds=5)
def parse_or_raise(xml):
try:
return XML(xml)
except (ExpatError, SyntaxError), e:
msg = 'GeoServer gave non-XML response for [GET %s]: %s'
msg = msg % (rest_url, xml)
raise Exception(msg, e)
if is_valid(cached_response):
raw_text = cached_response[1]
return parse_or_raise(raw_text)
else:
(response, content) = self.http.request(rest_url)
if response.status == 200:
self._cache[rest_url] = (datetime.now(), content)
return parse_or_raise(content)
else:
raise FailedRequestError(
'Tried to make a GET request to %s but got a %d \
status code: \n%s'
% (url, response.status, content))
def reload(self):
reload_url = url(self.service_url, ['reload'])
response = self.http.request(reload_url, 'POST')
self._cache.clear()
return response
def save(self, obj):
"""Saves an object to the REST service.
Gets the object's REST location and the XML from the object,
then POSTS the request.
"""
rest_url = obj.href
message = obj.message()
headers = {'Content-type': 'application/xml',
'Accept': 'application/xml'}
logger.debug('%s %s', obj.save_method, obj.href)
response = self.http.request(rest_url, obj.save_method, message,
headers)
(headers, body) = response
self._cache.clear()
if 400 <= int(headers['status']) < 600:
raise FailedRequestError('Error code (%s) from GeoServer: %s'
% (headers['status'], body))
return response
def get_store(self, name, workspace=None):
if workspace is None:
store = None
for ws in self.get_workspaces():
found = None
try:
found = self.get_store(name, ws)
except:
# Don't expect every workspace to contain the named store
pass
if found:
if store:
raise AmbiguousRequestError(
'Multiple stores found named: ' + name)
else:
store = found
if not store:
raise FailedRequestError('No store found named: ' + name)
return store
else:
# Workspace is not None
if isinstance(workspace, basestring):
workspace = self.get_workspace(workspace)
if workspace is None:
return None
logger.debug('datastore url is [%s]', workspace.datastore_url)
ds_list = self.get_xml(workspace.datastore_url)
cs_list = self.get_xml(workspace.coveragestore_url)
datastores = [n for n in ds_list.findall('dataStore')
if n.find('name').text == name]
coveragestores = [n for n in cs_list.findall('coverageStore')
if n.find('name').text == name]
(ds_len, cs_len) = (len(datastores), len(coveragestores))
if ds_len == 1 and cs_len == 0:
return datastore_from_index(self, workspace, datastores[0])
elif ds_len == 0 and cs_len == 1:
return coveragestore_from_index(self, workspace,
coveragestores[0])
elif ds_len == 0 and cs_len == 0:
raise FailedRequestError('No store found in ' + str(workspace)
+ ' named: ' + name)
else:
raise AmbiguousRequestError(str(workspace) + ' and name: '
+ name + ' do not uniquely identify a layer')
def get_stores(self, workspace=None):
if workspace is not None:
if isinstance(workspace, basestring):
workspace = self.get_workspace(workspace)
ds_list = self.get_xml(workspace.datastore_url)
cs_list = self.get_xml(workspace.coveragestore_url)
datastores = [datastore_from_index(self, workspace, n) for n in
ds_list.findall('dataStore')]
coveragestores = [coveragestore_from_index(self, workspace, n)
for n in cs_list.findall('coverageStore')]
return datastores + coveragestores
else:
stores = []
for ws in self.get_workspaces():
a = self.get_stores(ws)
stores.extend(a)
return stores
def create_datastore(self, name, workspace=None):
if isinstance(workspace, basestring):
workspace = self.get_workspace(workspace)
elif workspace is None:
workspace = self.get_default_workspace()
return UnsavedDataStore(self, name, workspace)
def create_coveragestore2(self, name, workspace=None):
"""Hm we already named the method that creates a coverage *resource*
create_coveragestore... time for an API break?
"""
if isinstance(workspace, basestring):
workspace = self.get_workspace(workspace)
elif workspace is None:
workspace = self.get_default_workspace()
return UnsavedCoverageStore(self, name, workspace)
def add_data_to_store(self, store, name, data, workspace=None,
overwrite=False, charset=None):
if isinstance(store, basestring):
store = self.get_store(store, workspace=workspace)
if workspace is not None:
workspace = _name(workspace)
assert store.workspace.name == workspace, \
'Specified store (%s) is not in specified workspace (%s)!' \
% (store, workspace)
else:
workspace = store.workspace.name
store = store.name
if isinstance(data, dict):
bundle = prepare_upload_bundle(name, data)
else:
bundle = data
params = dict()
if overwrite:
params['update'] = 'overwrite'
if charset is not None:
params['charset'] = charset
message = open(bundle)
headers = {'Content-Type': 'application/zip',
'Accept': 'application/xml'}
upload_url = url(self.service_url, ['workspaces', workspace,
'datastores', store, 'file.shp'], params)
try:
(headers, response) = self.http.request(upload_url, 'PUT',
message, headers)
self._cache.clear()
if headers.status != 201:
raise UploadError(response)
finally:
unlink(bundle)
def create_featurestore(self, name, data, workspace=None, overwrite=False,
charset=None):
if not overwrite:
try:
store = self.get_store(name, workspace)
msg = 'There is already a store named ' + name
if workspace:
msg += ' in ' + str(workspace)
raise ConflictingDataError(msg)
except FailedRequestError:
# We don't really expect that every layer name will be taken
pass
if workspace is None:
workspace = self.get_default_workspace()
workspace = _name(workspace)
params = dict()
if charset is not None:
params['charset'] = charset
ds_url = url(self.service_url, ['workspaces', workspace, 'datastores',
name, 'file.shp'], params)
# PUT /workspaces/<ws>/datastores/<ds>/file.shp
headers = {'Content-type': 'application/zip',
'Accept': 'application/xml'}
if isinstance(data, dict):
logger.debug('Data is NOT a zipfile')
archive = prepare_upload_bundle(name, data)
else:
logger.debug('Data is a zipfile')
archive = data
message = open(archive)
try:
(headers, response) = self.http.request(ds_url, 'PUT', message,
headers)
self._cache.clear()
if headers.status != 201:
raise UploadError(response)
finally:
unlink(archive)
def create_coveragestore(self, name, data, workspace=None,
overwrite=False):
if not overwrite:
try:
store = self.get_store(name, workspace)
msg = 'There is already a store named ' + name
if workspace:
msg += ' in ' + str(workspace)
raise ConflictingDataError(msg)
except FailedRequestError:
# We don't really expect that every layer name will be taken
pass
if workspace is None:
workspace = self.get_default_workspace()
headers = {'Content-type': 'image/tiff', 'Accept': 'application/xml'}
archive = None
ext = 'geotiff'
if isinstance(data, dict):
archive = prepare_upload_bundle(name, data)
message = open(archive)
if 'tfw' in data:
headers['Content-type'] = 'application/archive'
ext = 'worldimage'
elif isinstance(data, basestring):
message = open(data)
else:
message = data
cs_url = url(self.service_url, ['workspaces', workspace.name,
'coveragestores', name, 'file.' + ext])
try:
(headers, response) = self.http.request(cs_url, 'PUT', message,
headers)
self._cache.clear()
if headers.status != 201:
raise UploadError(response)
finally:
if archive is not None:
unlink(archive)
def get_resource(self, name, store=None, workspace=None):
if store is not None:
candidates = [s for s in self.get_resources(store) if s.name
== name]
if len(candidates) == 0:
return None
elif len(candidates) > 1:
raise AmbiguousRequestError
else:
return candidates[0]
if workspace is not None:
for store in self.get_stores(workspace):
resource = self.get_resource(name, store)
if resource is not None:
return resource
return None
for ws in self.get_workspaces():
resource = self.get_resource(name, workspace=ws)
if resource is not None:
return resource
return None
def get_resources(self, store=None, workspace=None):
if isinstance(workspace, basestring):
workspace = self.get_workspace(workspace)
if isinstance(store, basestring):
store = self.get_store(store, workspace)
if store is not None:
return store.get_resources()
if workspace is not None:
resources = []
for store in self.get_stores(workspace):
resources.extend(self.get_resources(store))
return resources
resources = []
for ws in self.get_workspaces():
resources.extend(self.get_resources(workspace=ws))
return resources
def get_layer(self, name):
try:
lyr = Layer(self, name)
lyr.fetch()
return lyr
except FailedRequestError:
return None
def get_layers(self, resource=None):
if isinstance(resource, basestring):
resource = self.get_resource(resource)
layers_url = url(self.service_url, ['layers.xml'])
description = self.get_xml(layers_url)
lyrs = [Layer(self, l.find('name').text) for l in
description.findall('layer')]
if resource is not None:
lyrs = [l for l in lyrs if l.resource.href == resource.href]
# TODO: filter by style
return lyrs
def get_layergroup(self, name=None):
try:
group_url = url(self.service_url, ['layergroups', name + '.xml'])
group = self.get_xml(group_url)
return LayerGroup(self, group.find('name').text)
except FailedRequestError:
return None
def get_layergroups(self):
groups = self.get_xml('%s/layergroups.xml' % self.service_url)
return [LayerGroup(self, g.find('name').text) for g in
groups.findall('layerGroup')]
def create_layergroup(self, name, layers=(), styles=(), bounds=None):
if any(g.name == name for g in self.get_layergroups()):
raise ConflictingDataError('LayerGroup named %s already exists!'
% name)
else:
return UnsavedLayerGroup(self, name, layers, styles, bounds)
def get_style(self, name):
try:
style_url = url(self.service_url, ['styles', name + '.xml'])
dom = self.get_xml(style_url)
return Style(self, dom.find('name').text)
except FailedRequestError:
return None
def get_styles(self):
styles_url = url(self.service_url, ['styles.xml'])
description = self.get_xml(styles_url)
return [Style(self, s.find('name').text) for s in
description.findall('style')]
def create_style(self, name, data, overwrite=False):
if not overwrite and self.get_style(name) is not None:
raise ConflictingDataError('There is already a style named %s'
% name)
headers = {'Content-type': 'application/vnd.ogc.sld+xml',
'Accept': 'application/xml'}
if overwrite:
style_url = url(self.service_url, ['styles', name + '.sld'])
(headers, response) = self.http.request(style_url, 'PUT', data,
headers)
else:
style_url = url(self.service_url, ['styles'], dict(name=name))
(headers, response) = self.http.request(style_url, 'POST', data,
headers)
self._cache.clear()
if headers.status < 200 or headers.status > 299:
raise UploadError(response)
def create_workspace(self, name, uri):
xml = '<namespace><prefix>{name}</prefix><uri>{uri}</uri>\
</namespace>'.format(name=name, uri=uri)
headers = {'Content-Type': 'application/xml'}
workspace_url = self.service_url + '/namespaces/'
(headers, response) = self.http.request(workspace_url, 'POST', xml,
headers)
assert 200 <= headers.status < 300, \
'Tried to create workspace but got ' + str(headers.status) + ': ' \
+ response
self._cache.clear()
return self.get_workspace(name)
def get_workspaces(self):
description = self.get_xml('%s/workspaces.xml' % self.service_url)
return [workspace_from_index(self, node) for node in
description.findall('workspace')]
def get_workspace(self, name):
candidates = [w for w in self.get_workspaces() if w.name == name]
if len(candidates) == 0:
return None
elif len(candidates) > 1:
raise AmbiguousRequestError()
else:
return candidates[0]
def get_default_workspace(self):
return Workspace(self, 'default')
def set_default_workspace(self):
raise NotImplementedError()

View File

@ -1,161 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
layer.py
---------------------
Date : November 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from style import Style
from support import ResourceInfo, \
xml_property, write_bool, url
class _attribution(object):
def __init__(self, title, width, height):
self.title = title
self.width = width
self.height = height
def _read_attribution(node):
title = node.find('title')
width = node.find('logoWidth')
height = node.find('logoHeight')
if title is not None:
title = title.text
if width is not None:
width = width.text
if height is not None:
height = height.text
return _attribution(title, width, height)
def _write_attribution(builder, attr):
builder.start('attribution', dict())
if attr.title is not None:
builder.start('title', dict())
builder.data(attr.title)
builder.end('title')
if attr.width is not None:
builder.start('logoWidth', dict())
builder.data(attr.width)
builder.end('logoWidth')
if attr.height is not None:
builder.start('logoHeight', dict())
builder.data(attr.height)
builder.end('logoHeight')
builder.end('attribution')
def _write_default_style(builder, name):
builder.start('defaultStyle', dict())
if name is not None:
builder.start('name', dict())
builder.data(name)
builder.end('name')
builder.end('defaultStyle')
def _write_alternate_styles(builder, styles):
builder.start('styles', dict())
for s in styles:
builder.start('style', dict())
builder.start('name', dict())
builder.data(s.name)
builder.end('name')
builder.end('style')
builder.end('styles')
class Layer(ResourceInfo):
def __init__(self, catalog, name):
super(Layer, self).__init__()
self.catalog = catalog
self.name = name
resource_type = 'layer'
save_method = 'PUT'
@property
def href(self):
return url(self.catalog.service_url, ['layers', self.name + '.xml'])
@property
def resource(self):
if self.dom is None:
self.fetch()
name = self.dom.find('resource/name').text
return self.catalog.get_resource(name)
def _get_default_style(self):
if 'default_style' in self.dirty:
return self.dirty['default_style']
if self.dom is None:
self.fetch()
name = self.dom.find('defaultStyle/name')
# Aborted data uploads can result in no default style
if name is not None:
return self.catalog.get_style(name.text)
else:
return None
def _set_default_style(self, style):
if isinstance(style, Style):
style = style.name
self.dirty['default_style'] = style
def _get_alternate_styles(self):
if 'alternate_styles' in self.dirty:
return self.dirty['alternate_styles']
if self.dom is None:
self.fetch()
styles = self.dom.findall('styles/style/name')
return [Style(self.catalog, s.text) for s in styles]
def _set_alternate_styles(self, styles):
self.dirty['alternate_styles'] = styles
default_style = property(_get_default_style, _set_default_style)
styles = property(_get_alternate_styles, _set_alternate_styles)
attribution_object = xml_property('attribution', _read_attribution)
enabled = xml_property('enabled', lambda x: x.text == 'true')
def _get_attr_text(self):
return self.attribution_object.title
def _set_attr_text(self, text):
self.dirty['attribution'] = _attribution(text,
self.attribution_object.width, self.attribution_object.height)
assert self.attribution_object.title == text
attribution = property(_get_attr_text, _set_attr_text)
writers = dict(attribution=_write_attribution, enabled=write_bool('enabled'
), default_style=_write_default_style,
alternate_styles=_write_alternate_styles)

View File

@ -1,117 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
layergroup.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from support import ResourceInfo, bbox, \
write_bbox, write_string, xml_property, url
def _maybe_text(n):
if n is None:
return None
else:
return n.text
def _layer_list(node):
if node is not None:
return [_maybe_text(n.find('name')) for n in node.findall('layer')]
def _style_list(node):
if node is not None:
return [_maybe_text(n.find('name')) for n in node.findall('style')]
def _write_layers(builder, layers):
builder.start('layers', dict())
for l in layers:
builder.start('layer', dict())
if l is not None:
builder.start('name', dict())
builder.data(l)
builder.end('name')
builder.end('layer')
builder.end('layers')
def _write_styles(builder, styles):
builder.start('styles', dict())
for s in styles:
builder.start('style', dict())
if s is not None:
builder.start('name', dict())
builder.data(s)
builder.end('name')
builder.end('style')
builder.end('styles')
class LayerGroup(ResourceInfo):
"""Represents a layer group in geoserver.
"""
resource_type = 'layerGroup'
save_method = 'PUT'
def __init__(self, catalog, name):
super(LayerGroup, self).__init__()
assert isinstance(name, basestring)
self.catalog = catalog
self.name = name
@property
def href(self):
return url(self.catalog.service_url, ['layergroups', self.name + '.xml'
])
styles = xml_property('styles', _style_list)
layers = xml_property('layers', _layer_list)
bounds = xml_property('bounds', bbox)
writers = dict(name=write_string('name'), styles=_write_styles,
layers=_write_layers, bounds=write_bbox('bounds'))
def __str__(self):
return '<LayerGroup %s>' % self.name
__repr__ = __str__
class UnsavedLayerGroup(LayerGroup):
save_method = 'POST'
def __init__(self, catalog, name, layers, styles, bounds):
super(UnsavedLayerGroup, self).__init__(catalog, name)
self.dirty.update(name=name, layers=layers, styles=styles,
bounds=bounds)
@property
def href(self):
return '%s/layergroups?name=%s' % (self.catalog.service_url, self.name)

View File

@ -1,229 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
resource.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from support import ResourceInfo, \
xml_property, write_string, bbox, write_bbox, string_list, \
write_string_list, attribute_list, write_bool, url
def md_link(node):
"""Extract a metadata link tuple from an xml node"""
mimetype = node.find('type')
mdtype = node.find('metadataType')
content = node.find('content')
if None in [mimetype, mdtype, content]:
return None
else:
return (mimetype.text, mdtype.text, content.text)
def metadata_link_list(node):
if node is not None:
return [md_link(n) for n in node.findall('metadataLink')]
def write_metadata_link_list(name):
def write(builder, md_links):
builder.start(name, dict())
for (mime, md_type, content_url) in md_links:
builder.start('metadataLink', dict())
builder.start('type', dict())
builder.data(mime)
builder.end('type')
builder.start('metadataType', dict())
builder.data(md_type)
builder.end('metadataType')
builder.start('content', dict())
builder.data(content_url)
builder.end('content')
builder.end('metadataLink')
builder.end('metadataLinks')
return write
def featuretype_from_index(catalog, workspace, store, node):
name = node.find('name')
return FeatureType(catalog, workspace, store, name.text)
def coverage_from_index(catalog, workspace, store, node):
name = node.find('name')
return Coverage(catalog, workspace, store, name.text)
class FeatureType(ResourceInfo):
resource_type = 'featureType'
save_method = 'PUT'
def __init__(self, catalog, workspace, store, name):
super(FeatureType, self).__init__()
assert isinstance(store, ResourceInfo)
assert isinstance(name, basestring)
self.catalog = catalog
self.workspace = workspace
self.store = store
self.name = name
@property
def href(self):
return url(self.catalog.service_url, [
'workspaces',
self.workspace.name,
'datastores',
self.store.name,
'featuretypes',
self.name + '.xml',
])
title = xml_property('title')
abstract = xml_property('abstract')
enabled = xml_property('enabled')
native_bbox = xml_property('nativeBoundingBox', bbox)
latlon_bbox = xml_property('latLonBoundingBox', bbox)
projection = xml_property('srs')
projection_policy = xml_property('projectionPolicy')
keywords = xml_property('keywords', string_list)
attributes = xml_property('attributes', attribute_list)
metadata_links = xml_property('metadataLinks', metadata_link_list)
writers = dict(
title=write_string('title'),
abstract=write_string('abstract'),
enabled=write_bool('enabled'),
nativeBoundingBox=write_bbox('nativeBoundingBox'),
latLonBoundingBox=write_bbox('latLonBoundingBox'),
srs=write_string('srs'),
projectionPolicy=write_string('projectionPolicy'),
keywords=write_string_list('keywords'),
metadataLinks=write_metadata_link_list('metadataLinks'),
)
class CoverageDimension(object):
def __init__(self, name, description, dimension_range):
self.name = name
self.description = description
self.dimension_range = dimension_range
def coverage_dimension(node):
name = node.find('name')
name = (name.text if name is not None else None)
description = node.find('description')
description = (description.text if description is not None else None)
range_min = node.find('range/min')
range_max = node.find('range/max')
dimension_range = None
if None not in [min, max]:
dimension_range = (float(range_min.text), float(range_max.text))
if None not in [name, description]:
return CoverageDimension(name, description, dimension_range)
else:
# Should we bomb out more spectacularly here?
return None
def coverage_dimension_xml(builder, dimension):
builder.start('coverageDimension', dict())
builder.start('name', dict())
builder.data(dimension.name)
builder.end('name')
builder.start('description', dict())
builder.data(dimension.description)
builder.end('description')
if dimension.range is not None:
builder.start('range', dict())
builder.start('min', dict())
builder.data(str(dimension.range[0]))
builder.end('min')
builder.start('max', dict())
builder.data(str(dimension.range[1]))
builder.end('max')
builder.end('range')
builder.end('coverageDimension')
class Coverage(ResourceInfo):
def __init__(self, catalog, workspace, store, name):
super(Coverage, self).__init__()
self.catalog = catalog
self.workspace = workspace
self.store = store
self.name = name
@property
def href(self):
return url(self.catalog.service_url, [
'workspaces',
self.workspace.name,
'coveragestores',
self.store.name,
'coverages',
self.name + '.xml',
])
resource_type = 'coverage'
save_method = 'PUT'
title = xml_property('title')
abstract = xml_property('abstract')
enabled = xml_property('enabled')
native_bbox = xml_property('nativeBoundingBox', bbox)
latlon_bbox = xml_property('latLonBoundingBox', bbox)
projection = xml_property('srs')
projection_policy = xml_property('projectionPolicy')
keywords = xml_property('keywords', string_list)
request_srs_list = xml_property('requestSRS', string_list)
response_srs_list = xml_property('responseSRS', string_list)
supported_formats = xml_property('supportedFormats', string_list)
metadata_links = xml_property('metadataLinks', metadata_link_list)
writers = dict(
title=write_string('title'),
abstract=write_string('abstract'),
enabled=write_bool('enabled'),
nativeBoundingBox=write_bbox('nativeBoundingBox'),
latLonBoundingBox=write_bbox('latLonBoundingBox'),
srs=write_string('srs'),
projection_policy=write_string('projectionPolicy'),
keywords=write_string_list('keywords'),
metadataLinks=write_metadata_link_list('metadataLinks'),
requestSRS=write_string_list('requestSRS'),
responseSRS=write_string_list('responseSRS'),
supportedFormats=write_string_list('supportedFormats'),
)

View File

@ -1,156 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
store.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from workspace import Workspace
from resource import featuretype_from_index, \
coverage_from_index
from support import ResourceInfo, \
xml_property, key_value_pairs, write_bool, write_dict, write_string, url
def datastore_from_index(catalog, workspace, node):
name = node.find('name')
return DataStore(catalog, workspace, name.text)
def coveragestore_from_index(catalog, workspace, node):
name = node.find('name')
return CoverageStore(catalog, workspace, name.text)
class DataStore(ResourceInfo):
resource_type = 'dataStore'
save_method = 'PUT'
def __init__(self, catalog, workspace, name):
super(DataStore, self).__init__()
assert isinstance(workspace, Workspace)
assert isinstance(name, basestring)
self.catalog = catalog
self.workspace = workspace
self.name = name
@property
def href(self):
return url(self.catalog.service_url, ['workspaces',
self.workspace.name, 'datastores', self.name + '.xml'])
enabled = xml_property('enabled', lambda x: x.text == 'true')
name = xml_property('name')
connection_parameters = xml_property('connectionParameters',
key_value_pairs)
writers = dict(enabled=write_bool('enabled'), name=write_string('name'),
connectionParameters=write_dict('connectionParameters'))
def get_resources(self):
res_url = url(self.catalog.service_url, ['workspaces',
self.workspace.name, 'datastores', self.name,
'featuretypes.xml'])
xml = self.catalog.get_xml(res_url)
def ft_from_node(node):
return featuretype_from_index(self.catalog, self.workspace, self,
node)
return [ft_from_node(node) for node in xml.findall('featureType')]
class UnsavedDataStore(DataStore):
save_method = 'POST'
def __init__(self, catalog, name, workspace):
super(UnsavedDataStore, self).__init__(catalog, workspace, name)
self.dirty.update(dict(name=name, enabled=True,
connectionParameters=dict()))
@property
def href(self):
path = ['workspaces', self.workspace.name, 'datastores']
query = dict(name=self.name)
return url(self.catalog.service_url, path, query)
class CoverageStore(ResourceInfo):
resource_type = 'coverageStore'
save_method = 'PUT'
def __init__(self, catalog, workspace, name):
super(CoverageStore, self).__init__()
assert isinstance(workspace, Workspace)
assert isinstance(name, basestring)
self.catalog = catalog
self.workspace = workspace
self.name = name
@property
def href(self):
return url(self.catalog.service_url, ['workspaces',
self.workspace.name, 'coveragestores', self.name + '.xml'])
enabled = xml_property('enabled', lambda x: x.text == 'true')
name = xml_property('name')
url = xml_property('url')
type = xml_property('type')
writers = dict(enabled=write_bool('enabled'), name=write_string('name'),
url=write_string('url'), type=write_string('type'))
def get_resources(self):
res_url = url(self.catalog.service_url, ['workspaces',
self.workspace.name, 'coveragestores', self.name,
'coverages.xml'])
xml = self.catalog.get_xml(res_url)
def cov_from_node(node):
return coverage_from_index(self.catalog, self.workspace, self,
node)
return [cov_from_node(node) for node in xml.findall('coverage')]
class UnsavedCoverageStore(CoverageStore):
save_method = 'POST'
def __init__(self, catalog, name, workspace):
super(UnsavedCoverageStore, self).__init__(catalog, workspace, name)
self.dirty.update(name=name, enabled=True, type='GeoTIFF',
url='file:data/')
@property
def href(self):
return url(self.catalog.service_url, ['workspaces',
self.workspace.name, 'coveragestores'],
dict(name=self.name))

View File

@ -1,77 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
style.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from support import ResourceInfo, url, \
xml_property
class Style(ResourceInfo):
def __init__(self, catalog, name):
super(Style, self).__init__()
assert isinstance(name, basestring)
self.catalog = catalog
self.name = name
self._sld_dom = None
@property
def href(self):
return url(self.catalog.service_url, ['styles', self.name + '.xml'])
def body_href(self):
return url(self.catalog.service_url, ['styles', self.name + '.sld'])
filename = xml_property('filename')
def _get_sld_dom(self):
if self._sld_dom is None:
self._sld_dom = self.catalog.get_xml(self.body_href())
return self._sld_dom
@property
def sld_title(self):
user_style = \
self._get_sld_dom().find('{http://www.opengis.net/sld}NamedLayer/{http://www.opengis.net/sld}UserStyle')
title_node = user_style.find('{http://www.opengis.net/sld}Title')
return (title_node.text if title_node is not None else None)
@property
def sld_name(self):
user_style = \
self._get_sld_dom().find('{http://www.opengis.net/sld}NamedLayer/{http://www.opengis.net/sld}UserStyle')
name_node = user_style.find('{http://www.opengis.net/sld}Name')
return (name_node.text if name_node is not None else None)
@property
def sld_body(self):
content = self.catalog.http.request(self.body_href())[1]
return content
def update_body(self, body):
headers = {'Content-Type': 'application/vnd.ogc.sld+xml'}
self.catalog.http.request(self.body_href(), 'PUT', body, headers)

View File

@ -1,277 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
support.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import logging
from xml.etree.ElementTree import TreeBuilder, tostring
import urllib
import urlparse
from zipfile import ZipFile
from processing.tools.system import *
logger = logging.getLogger('gsconfig.support')
# The projection handling policy for layers that should use coordinates
# directly while reporting the configured projection to clients. This
# should be used when projection information is missing from the
# underlying datastore.
FORCE_DECLARED = 'FORCE_DECLARED'
# The projection handling policy for layers that should use the
# projection information from the underlying storage mechanism directly,
# and ignore the projection setting.
FORCE_NATIVE = 'FORCE_NATIVE'
# The projection handling policy for layers that should use the
# projection information from the underlying storage mechanism to
# reproject to the configured projection.
REPROJECT = 'REPROJECT'
def url(base, seg, query=None):
"""Create a URL from a list of path segments and an optional dict
of query parameters.
"""
seg = (urllib.quote(s.strip('/')) for s in seg)
if query is None or len(query) == 0:
query_string = ''
else:
query_string = '?' + urllib.urlencode(query)
path = '/'.join(seg) + query_string
adjusted_base = base.rstrip('/') + '/'
return urlparse.urljoin(adjusted_base, path)
def xml_property(path, converter=lambda x: x.text):
def getter(self):
if path in self.dirty:
return self.dirty[path]
else:
if self.dom is None:
self.fetch()
node = self.dom.find(path)
return (converter(self.dom.find(path)) if node
is not None else None)
def setter(self, value):
self.dirty[path] = value
def delete(self):
self.dirty[path] = None
return property(getter, setter, delete)
def bbox(node):
if node is not None:
minx = node.find('minx')
maxx = node.find('maxx')
miny = node.find('miny')
maxy = node.find('maxy')
crs = node.find('crs')
crs = (crs.text if crs is not None else None)
if None not in [minx, maxx, miny, maxy]:
return (minx.text, maxx.text, miny.text, maxy.text, crs)
else:
return None
else:
return None
def string_list(node):
if node is not None:
return [n.text for n in node.findall('string')]
def attribute_list(node):
if node is not None:
return [n.text for n in node.findall('attribute/name')]
def key_value_pairs(node):
if node is not None:
return dict((entry.attrib['key'], entry.text) for entry in
node.findall('entry'))
def write_string(name):
def write(builder, value):
builder.start(name, dict())
if value is not None:
builder.data(value)
builder.end(name)
return write
def write_bool(name):
def write(builder, b):
builder.start(name, dict())
builder.data(('true' if b else 'false'))
builder.end(name)
return write
def write_bbox(name):
def write(builder, b):
builder.start(name, dict())
bbox_xml(builder, b)
builder.end(name)
return write
def write_string_list(name):
def write(builder, words):
builder.start(name, dict())
for w in words:
builder.start('string', dict())
builder.data(w)
builder.end('string')
builder.end(name)
return write
def write_dict(name):
def write(builder, pairs):
builder.start(name, dict())
for (k, v) in pairs.iteritems():
builder.start('entry', dict(key=k))
builder.data(v)
builder.end('entry')
builder.end(name)
return write
class ResourceInfo(object):
def __init__(self):
self.dom = None
self.dirty = dict()
def fetch(self):
self.dom = self.catalog.get_xml(self.href)
def clear(self):
self.dirty = dict()
def refresh(self):
self.clear()
self.fetch()
def serialize(self, builder):
# GeoServer will disable the resource if we omit the <enabled>
# tag, so force it into the dirty dict before writing
if hasattr(self, 'enabled'):
self.dirty['enabled'] = self.enabled
for (k, writer) in self.writers.items():
if k in self.dirty:
writer(builder, self.dirty[k])
def message(self):
builder = TreeBuilder()
builder.start(self.resource_type, dict())
self.serialize(builder)
builder.end(self.resource_type)
msg = tostring(builder.close())
return msg
def prepare_upload_bundle(name, data):
"""GeoServer's REST API uses ZIP archives as containers for file
formats such as Shapefile and WorldImage which include several
'boxcar' files alongside the main data.
In such archives, GeoServer assumes that all of the relevant files
will have the same base name and appropriate extensions, and live
in the root of the ZIP archive. This method produces a zip file
that matches these expectations, based on a basename, and a dict of
extensions to paths or file-like objects. The client code is
responsible for deleting the zip archive when it's done.
"""
# We put the zip file in the Processing temp dir, so it is
# deleted at the end.
f = getTempFilename('zip')
zip_file = ZipFile(f, 'w')
for (ext, stream) in data.iteritems():
fname = '%s.%s' % (name, ext)
if isinstance(stream, basestring):
zip_file.write(stream, fname)
else:
zip_file.writestr(fname, stream.read())
zip_file.close()
return f
def atom_link(node):
if 'href' in node.attrib:
return node.attrib['href']
else:
l = node.find('{http://www.w3.org/2005/Atom}link')
return l.get('href')
def atom_link_xml(builder, href):
builder.start('atom:link', {
'rel': 'alternate',
'href': href,
'type': 'application/xml',
'xmlns:atom': 'http://www.w3.org/2005/Atom',
})
builder.end('atom:link')
def bbox_xml(builder, box):
(minx, maxx, miny, maxy, crs) = box
builder.start('minx', dict())
builder.data(minx)
builder.end('minx')
builder.start('maxx', dict())
builder.data(maxx)
builder.end('maxx')
builder.start('miny', dict())
builder.data(miny)
builder.end('miny')
builder.start('maxy', dict())
builder.data(maxy)
builder.end('maxy')
if crs is not None:
builder.start('crs', {'class': 'projected'})
builder.data(crs)
builder.end('crs')

View File

@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
util.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
def shapefile_and_friends(path):
return dict((ext, path + '.' + ext) for ext in ['shx', 'shp', 'dbf', 'prj'
])

View File

@ -1,65 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
workspace.py
---------------------
Date : November 2012
Copyright : (C) 2012 by David Winslow
Email : dwins at opengeo dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'David Winslow'
__date__ = 'November 2012'
__copyright__ = '(C) 2012, David Winslow'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from support import xml_property, write_bool, \
ResourceInfo, url
def workspace_from_index(catalog, node):
name = node.find('name')
return Workspace(catalog, name.text)
class Workspace(ResourceInfo):
resource_type = 'workspace'
def __init__(self, catalog, name):
super(Workspace, self).__init__()
self.catalog = catalog
self.name = name
@property
def href(self):
return url(self.catalog.service_url, ['workspaces', self.name + '.xml'
])
@property
def coveragestore_url(self):
return url(self.catalog.service_url, ['workspaces', self.name,
'coveragestores.xml'])
@property
def datastore_url(self):
return url(self.catalog.service_url, ['workspaces', self.name,
'datastores.xml'])
enabled = xml_property('enabled', lambda x: x.lower() == 'true')
writers = dict(enabled=write_bool('enabled'))
def __repr__(self):
return '%s @ %s' % (self.name, self.href)

View File

@ -38,7 +38,7 @@ from processing.parameters.ParameterString import ParameterString
from processing.parameters.ParameterSelection import ParameterSelection
from processing.parameters.ParameterTableField import ParameterTableField
from processing.tools import dataobjects
import postgis_utils
from processing.algs.qgis import postgis_utils
class ImportIntoPostGIS(GeoAlgorithm):
@ -54,9 +54,6 @@ class ImportIntoPostGIS(GeoAlgorithm):
DROP_STRING_LENGTH = 'DROP_STRING_LENGTH'
PRIMARY_KEY = 'PRIMARY_KEY'
def getIcon(self):
return QIcon(os.path.dirname(__file__) + '/../../images/postgis.png')
def processAlgorithm(self, progress):
connection = self.DB_CONNECTIONS[self.getParameterValue(self.DATABASE)]
schema = self.getParameterValue(self.SCHEMA)
@ -135,7 +132,7 @@ class ImportIntoPostGIS(GeoAlgorithm):
def defineCharacteristics(self):
self.name = 'Import into PostGIS'
self.group = 'PostGIS management tools'
self.group = 'Database'
self.addParameter(ParameterVector(self.INPUT, 'Layer to import'))
self.DB_CONNECTIONS = self.dbConnectionNames()

View File

@ -33,7 +33,7 @@ from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \
GeoAlgorithmExecutionException
from processing.parameters.ParameterString import ParameterString
import postgis_utils
from processing.algs.qgis import postgis_utils
class PostGISExecuteSQL(GeoAlgorithm):
@ -41,11 +41,7 @@ class PostGISExecuteSQL(GeoAlgorithm):
DATABASE = 'DATABASE'
SQL = 'SQL'
def getIcon(self):
return QIcon(os.path.dirname(__file__) + '/../../images/postgis.png')
def processAlgorithm(self, progress):
connection = self.getParameterValue(self.DATABASE)
settings = QSettings()
mySettings = '/PostgreSQL/connections/' + connection
@ -74,6 +70,6 @@ class PostGISExecuteSQL(GeoAlgorithm):
def defineCharacteristics(self):
self.name = 'PostGIS execute SQL'
self.group = 'PostGIS management tools'
self.group = 'Database'
self.addParameter(ParameterString(self.DATABASE, 'Database'))
self.addParameter(ParameterString(self.SQL, 'SQL query', '', True))

View File

@ -17,6 +17,7 @@
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'December 2012'
__copyright__ = '(C) 2012, Victor Olaya'
@ -96,7 +97,8 @@ from RandomPointsPolygonsFixed import RandomPointsPolygonsFixed
from RandomPointsPolygonsVariable import RandomPointsPolygonsVariable
from RandomPointsAlongLines import RandomPointsAlongLines
from PointsToPaths import PointsToPaths
from PostGISExecuteSQL import PostGISExecuteSQL
from ImportIntoPostGIS import ImportIntoPostGIS
# from VectorLayerHistogram import VectorLayerHistogram
# from VectorLayerScatterplot import VectorLayerScatterplot
# from MeanAndStdDevPlot import MeanAndStdDevPlot
@ -152,6 +154,7 @@ class QGISAlgorithmProvider(AlgorithmProvider):
RandomPointsLayer(), RandomPointsPolygonsFixed(),
RandomPointsPolygonsVariable(),
RandomPointsAlongLines(), PointsToPaths(),
PostGISExecuteSQL(), ImportIntoPostGIS()
# ------ raster ------
# CreateConstantRaster(),
# ------ graphics ------

View File

@ -57,8 +57,6 @@ from processing.algs.r.RAlgorithmProvider import RAlgorithmProvider
from processing.algs.saga.SagaAlgorithmProvider import SagaAlgorithmProvider
from processing.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider
from processing.algs.taudem.TauDEMAlgorithmProvider import TauDEMAlgorithmProvider
from processing.algs.admintools.AdminToolsAlgorithmProvider import \
AdminToolsAlgorithmProvider
from processing.tools import dataobjects
@ -143,7 +141,6 @@ class Processing:
Processing.addProvider(Grass7AlgorithmProvider())
Processing.addProvider(ScriptAlgorithmProvider())
Processing.addProvider(TauDEMAlgorithmProvider())
Processing.addProvider(AdminToolsAlgorithmProvider())
Processing.modeler.initializeSettings()
# And initialize