Skip to content
Open
41 changes: 41 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python3

# Copyright (c) 2016 PyWPS Project Steering Committee
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import flask

# we need to set the root before we import the main_page as there are relative paths to this root (i.e. config files)
import sys
import os
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
os.chdir(project_root)

from app_main_page import main_page

app = flask.Flask(__name__)
app.register_blueprint(main_page)

application = app # application is the default name for mod_wsgi

if __name__ == "__main__":
app.run()
17 changes: 17 additions & 0 deletions app_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pywps.configuration as config
from app_set_server import set_server
from set_root import set_root

set_root()

config_path = 'config/'
cfgfiles = [config_path + 'pywps.cfg']
config.load_configuration(cfgfiles)

# these defaults will be overwritten with the url from by the server\url from the config file
server_hostname = 'http://localhost'
server_port = 5000
server_base_url = '{}:{}'.format(server_hostname, server_port)
server_wps_url = server_base_url + '/wps'

server_hostname, server_port, server_base_url, server_wps_url, _ = set_server(config.get_config_value("server", "url"))
67 changes: 67 additions & 0 deletions app_main_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import os
import sys
import flask
import pywps
import processes
import app_config

# This is, how you start PyWPS instance
service = pywps.Service(processes=processes.processes)
# config is read in app_config so we don't need to pass it to Service as well
# service = pywps.Service(processes=processes.processes, cfgfiles=cfgfiles)

main_page = flask.Blueprint('main_page', __name__, template_folder='templates')


@main_page.route('/test')
def test():
return 'hello test!'


@main_page.route("/sys_path")
def sys_path():
return str(sys.path)


# returns 'hello to the WPS server root'
@main_page.route('/wps', methods=['GET', 'POST'])
def wps():
return service


@main_page.route("/")
def hello():
request_url = flask.request.url
return flask.render_template('home.html', request_url=request_url,
server_url=app_config.server_wps_url,
process_descriptor=processes.process_descriptor)


def flask_response(targetfile):
if os.path.isfile(targetfile):
with open(targetfile, mode='rb') as f:
file_bytes = f.read()
file_ext = os.path.splitext(targetfile)[1]
mime_type = 'text/xml' if 'xml' in file_ext else None
return flask.Response(file_bytes, content_type=mime_type)
else:
flask.abort(404)


@main_page.route('/outputs/' + '<path:filename>')
def outputfile(filename):
targetfile = os.path.join('outputs', filename)
return flask_response(targetfile)


@main_page.route('/data/' + '<path:filename>')
def datafile(filename):
targetfile = os.path.join('static', 'data', filename)
return flask_response(targetfile)


# not sure how the static route works. static route doesn't reach this function.
@main_page.route('/static/' + '<path:filename>')
def staticfile(filename):
targetfile = os.path.join('static', filename)
return flask_response(targetfile)
39 changes: 39 additions & 0 deletions app_set_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import re
from exceptions import BadUserInputError


def set_server(new_server_wps_url: str):
pattern = r'((?:.*://)?(.*?)(?:(?::)(\d+))?(?:/.*?)?)$'
m = re.match(pattern, new_server_wps_url)
if not m:
raise BadUserInputError('cannot parse server url: {}'.format(new_server_wps_url))
# print(m.groups())
server_wps_url = m.group(1)
if server_wps_url.endswith('/'):
server_wps_url = server_wps_url.rstrip('/')
server_base_url = server_wps_url
if server_base_url.endswith('/wps'):
server_base_url = server_wps_url[:-4]
else:
server_wps_url = server_base_url + '/wps'
server_hostname = m.group(2)
server_port = m.group(3)
if server_port:
server_port = int(server_port)
else:
server_port = 80
return server_hostname, server_port, server_base_url, server_wps_url, new_server_wps_url


if __name__ == '__main__':
print(set_server('http://localhost:5000/abc/wps'))
print(set_server('http://localhost:5000/wps'))
print(set_server('http://localhost:5000/'))
print(set_server('http://localhost:5000'))
print(set_server('http://localhost/abc/wps'))
print(set_server('http://localhost/wps'))
print(set_server('http://localhost/'))
print(set_server('localhost'))
print(set_server('localhost:5000'))
print(set_server('localhost:5000/'))
print(set_server('localhost:5000/wps'))
5 changes: 3 additions & 2 deletions pywps.cfg → config/pywps.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ identification_keywords_type=theme
identification_fees=None
identification_accessconstraints=None
provider_name=PyWPS Developement team
provider_url=http://pywps.org/'
provider_url=http://pywps.org/
contact_name=Your Name
contact_position=Developer
contact_address=My Street
Expand All @@ -26,13 +26,14 @@ contact_role=pointOfContact
maxsingleinputsize=1mb
maxrequestsize=3mb
url=http://localhost:5000/wps
outputurl=http://localhost:5000/outputs/
outputurl=outputs
outputpath=outputs
workdir=workdir
wd_inp_subdir=inputs
wd_out_subdir=outputs
maxprocesses=10
parallelprocesses=2
allowedinputpaths=./static/

[processing]
mode=docker
Expand Down
111 changes: 16 additions & 95 deletions demo.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#!/usr/bin/env python3

# Copyright (c) 2016 PyWPS Project Steering Committee
#
#
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -22,88 +22,9 @@
# SOFTWARE.

import os
import flask

import pywps
from pywps import Service

from processes.sleep import Sleep
from processes.ultimate_question import UltimateQuestion
from processes.centroids import Centroids
from processes.sayhello import SayHello
from processes.feature_count import FeatureCount
from processes.buffer import Buffer
from processes.area import Area
from processes.bboxinout import Box
from processes.jsonprocess import TestJson


app = flask.Flask(__name__)

processes = [
FeatureCount(),
SayHello(),
Centroids(),
UltimateQuestion(),
Sleep(),
Buffer(),
Area(),
Box(),
TestJson()
]

# For the process list on the home page

process_descriptor = {}
for process in processes:
abstract = process.abstract
identifier = process.identifier
process_descriptor[identifier] = abstract

# This is, how you start PyWPS instance
service = Service(processes, ['pywps.cfg'])


@app.route("/")
def hello():
server_url = pywps.configuration.get_config_value("server", "url")
request_url = flask.request.url
return flask.render_template('home.html', request_url=request_url,
server_url=server_url,
process_descriptor=process_descriptor)


@app.route('/wps', methods=['GET', 'POST'])
def wps():

return service


@app.route('/outputs/'+'<path:filename>')
def outputfile(filename):
targetfile = os.path.join('outputs', filename)
if os.path.isfile(targetfile):
file_ext = os.path.splitext(targetfile)[1]
with open(targetfile, mode='rb') as f:
file_bytes = f.read()
mime_type = None
if 'xml' in file_ext:
mime_type = 'text/xml'
return flask.Response(file_bytes, content_type=mime_type)
else:
flask.abort(404)


@app.route('/static/'+'<path:filename>')
def staticfile(filename):
targetfile = os.path.join('static', filename)
if os.path.isfile(targetfile):
with open(targetfile, mode='rb') as f:
file_bytes = f.read()
mime_type = None
return flask.Response(file_bytes, content_type=mime_type)
else:
flask.abort(404)
from app import app
from app_config import server_port

if __name__ == "__main__":
import argparse
Expand All @@ -115,30 +36,30 @@ def staticfile(filename):
It's intended to be running in test environment only!
For more documentation, visit http://pywps.org/doc
"""
)
)
parser.add_argument('-d', '--daemon',
action='store_true', help="run in daemon mode")
parser.add_argument('-a','--all-addresses',
action='store_true', help="run flask using IPv4 0.0.0.0 (all network interfaces)," +
"otherwise bind to 127.0.0.1 (localhost). This maybe necessary in systems that only run Flask")
parser.add_argument('-a', '--all-addresses',
action='store_true', help="run flask using IPv4 0.0.0.0 (all network interfaces)," +
"otherwise bind to 127.0.0.1 (localhost). This maybe necessary in systems that only run Flask")
args = parser.parse_args()

if args.all_addresses:
bind_host='0.0.0.0'
bind_host = '0.0.0.0'
else:
bind_host='127.0.0.1'
bind_host = '127.0.0.1'

if args.daemon:
pid = None
try:
pid = os.fork()
except OSError as e:
raise Exception("%s [%d]" % (e.strerror, e.errno))
print("%s [%d]" % (e.strerror, e.errno))

if (pid == 0):
os.setsid()
app.run(threaded=True,host=bind_host)
app.run(threaded=True, host=bind_host, port=server_port)
else:
os._exit(0)
else:
app.run(threaded=True,host=bind_host)
app.run(threaded=True, host=bind_host, port=server_port)
11 changes: 7 additions & 4 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,14 @@
#'figure_align': 'htbp',
}

project_name = 'PyWPS-Flask'
project_doc = project_name+' Documentation'

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'PyWPS-Flask.tex', u'PyWPS-Flask Documentation',
(master_doc, 'PyWPS-Flask.tex', project_doc,
u'PyWPS Development Team', 'manual'),
]

Expand Down Expand Up @@ -277,7 +280,7 @@
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'pywps-flask', u'PyWPS-Flask Documentation',
(master_doc, project_name, project_doc,
[author], 1)
]

Expand All @@ -291,8 +294,8 @@
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'PyWPS-Flask', u'PyWPS-Flask Documentation',
author, 'PyWPS-Flask', 'One line description of project.',
(master_doc, project_name, project_doc,
author, project_name, 'One line description of project.',
'Miscellaneous'),
]

Expand Down
11 changes: 11 additions & 0 deletions exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class PyWPSError(Exception):
"""Exception class from which every exception in this library will derive.
It enables other projects using this library to catch all errors coming
from the library with a single "except" statement
"""
pass


class BadUserInputError(PyWPSError):
"""A specific error"""
pass
Loading