diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..e0d5f5a7c
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+.git
+docs/
+tests/
diff --git a/cookiecutter.json b/cookiecutter.json
index c04ca5c99..2360b9cd0 100644
--- a/cookiecutter.json
+++ b/cookiecutter.json
@@ -12,8 +12,10 @@
"add_pyup_badge": "n",
"command_line_interface": ["Click", "Argparse", "No command-line interface"],
"create_author_file": "y",
- "open_source_license": ["MIT license", "BSD license", "ISC license", "Apache Software License 2.0", "GNU General Public License v3", "Not open source"],
+ "open_source_license": ["Apache Software License 2.0", "MIT license", "BSD license", "ISC license", "GNU General Public License v3", "Not open source"],
"port_digits": "94",
"http_port": "80{{ cookiecutter.port_digits }}",
- "https_port": "280{{ cookiecutter.port_digits }}"
+ "https_port": "280{{ cookiecutter.port_digits }}",
+ "_copy_without_render": [
+ "{{cookiecutter.project_slug}}/templates/*.cfg",
}
diff --git a/{{cookiecutter.project_slug}}/Dockerfile b/{{cookiecutter.project_slug}}/Dockerfile
index 5e98604e6..2a5800c22 100644
--- a/{{cookiecutter.project_slug}}/Dockerfile
+++ b/{{cookiecutter.project_slug}}/Dockerfile
@@ -1,47 +1,33 @@
# vim:set ft=dockerfile:
-FROM birdhouse/bird-base:latest
+FROM continuumio/miniconda3
MAINTAINER https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}
+LABEL Description="{{ cookiecutter.project_slug }} WPS" Vendor="Birdhouse" Version="{{ cookiecutter.version }}"
-LABEL Description="{{ cookiecutter.project_slug }} WPS" Vendor="Birdhouse"
+# Update Debian system
+RUN apt-get update && apt-get install -y \
+ build-essential \
+&& rm -rf /var/lib/apt/lists/*
-# Configure hostname and ports for services
-ENV HTTP_PORT 5000
-ENV OUTPUT_PORT 8000
-ENV HOSTNAME localhost
+# Update conda
+RUN conda update -n base conda
-# Set current home
-ENV HOME /root
+# Copy WPS project
+COPY . /opt/wps
-# Copy application sources
-COPY . /opt/birdhouse/src/{{ cookiecutter.project_slug }}
+WORKDIR /opt/wps
-# cd into application
-WORKDIR /opt/birdhouse/src/{{ cookiecutter.project_slug }}
+# Create conda environment
+RUN conda env create -n wps -f environment.yml
-# Provide custom.cfg with settings for docker image
-COPY .docker.cfg custom.cfg
+# Install WPS
+RUN ["/bin/bash", "-c", "source activate wps && python setup.py develop"]
-# Install system dependencies
-RUN bash bootstrap.sh -i
+# Start WPS service on port {{ cookiecutter.http_port }} on 0.0.0.0
+EXPOSE {{ cookiecutter.http_port }}
+ENTRYPOINT ["/bin/bash", "-c"]
+CMD ["source activate wps && exec emu --config /opt/wps/etc/demo.cfg"]
-# Set conda enviroment
-ENV ANACONDA_HOME /opt/conda
-ENV CONDA_ENVS_DIR /opt/conda/envs
-
-# Run install and fix permissions
-RUN make clean install && chmod 755 /opt/birdhouse/etc && chmod 755 /opt/birdhouse/var/run
-
-# Volume for data, cache, logfiles, ...
-VOLUME /opt/birdhouse/var/lib
-VOLUME /opt/birdhouse/var/log
-# Volume for configs
-VOLUME /opt/birdhouse/etc
-
-# Ports used in birdhouse
-EXPOSE $HTTP_PORT $OUTPUT_PORT
-
-# Start supervisor in foreground
-ENV DAEMON_OPTS --nodaemon
-
-# Start service ...
-CMD ["make", "update-config", "start"]
+# docker build -t {{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }} .
+# docker run -p {{ cookiecutter.http_port }}:{{ cookiecutter.http_port }} {{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}
+# http://localhost:{{ cookiecutter.http_port }}/wps?request=GetCapabilities&service=WPS
+# http://localhost:{{ cookiecutter.http_port }}/wps?request=DescribeProcess&service=WPS&identifier=all&version=1.0.0
diff --git a/{{cookiecutter.project_slug}}/Makefile b/{{cookiecutter.project_slug}}/Makefile
index 482b54065..225fa623b 100644
--- a/{{cookiecutter.project_slug}}/Makefile
+++ b/{{cookiecutter.project_slug}}/Makefile
@@ -20,9 +20,6 @@ BUILDOUT_VERSION := 2.11
# Anaconda
ANACONDA_HOME ?= $(HOME)/anaconda
CONDA_ENV ?= $(APP_NAME)
-CONDA_ENVS_DIR ?= $(HOME)/.conda/envs
-CONDA_ENV_PATH := $(CONDA_ENVS_DIR)/$(CONDA_ENV)
-CONDA_PINNED := $(APP_ROOT)/requirements/conda_pinned
# Configuration used by update-config
HOSTNAME ?= localhost
@@ -32,16 +29,14 @@ OUTPUT_PORT ?= 8090
# choose anaconda installer depending on your OS
ANACONDA_URL = https://repo.continuum.io/miniconda
ifeq "$(OS_NAME)" "Linux"
-FN := Miniconda2-latest-Linux-x86_64.sh
+FN := Miniconda3-latest-Linux-x86_64.sh
else ifeq "$(OS_NAME)" "Darwin"
-FN := Miniconda2-latest-MacOSX-x86_64.sh
+FN := Miniconda3-latest-MacOSX-x86_64.sh
else
FN := unknown
endif
-# Buildout files and folders
-DOWNLOAD_CACHE := $(APP_ROOT)/downloads
-BUILDOUT_FILES := parts eggs develop-eggs bin .installed.cfg .mr.developer.cfg *.egg-info bootstrap-buildout.py *.bak.* $(DOWNLOAD_CACHE)
+TEMP_FILES := *.egg-info *.log *.sqlite
# Docker
DOCKER_IMAGE := birdhouse/$(APP_NAME)
@@ -49,8 +44,7 @@ DOCKER_CONTAINER := $(APP_NAME)
# end of configuration
-.PHONY: clean clean-test clean-pyc clean-build docs help
-.DEFAULT_GOAL := help
+.DEFAULT_GOAL := all
define BROWSER_PYSCRIPT
import os, webbrowser, sys
@@ -207,73 +201,42 @@ anaconda:
@echo "Installing Anaconda ..."
@test -d $(ANACONDA_HOME) || curl $(ANACONDA_URL)/$(FN) --silent --insecure --output "$(DOWNLOAD_CACHE)/$(FN)"
@test -d $(ANACONDA_HOME) || bash "$(DOWNLOAD_CACHE)/$(FN)" -b -p $(ANACONDA_HOME)
- @echo "Add '$(ANACONDA_HOME)/bin' to your PATH variable in '.bashrc'."
-
-.PHONY: conda_config
-conda_config: anaconda
- @echo "Update ~/.condarc"
- @-"$(ANACONDA_HOME)/bin/conda" install -y conda=$(CONDA_VERSION) requests
- @"$(ANACONDA_HOME)/bin/conda" config --add envs_dirs $(CONDA_ENVS_DIR)
- @"$(ANACONDA_HOME)/bin/conda" config --set ssl_verify true
- @"$(ANACONDA_HOME)/bin/conda" config --set use_pip true
- @"$(ANACONDA_HOME)/bin/conda" config --set channel_priority true
- @"$(ANACONDA_HOME)/bin/conda" config --set auto_update_conda false
- @"$(ANACONDA_HOME)/bin/conda" config --add channels defaults
- @"$(ANACONDA_HOME)/bin/conda" config --append channels birdhouse
- @"$(ANACONDA_HOME)/bin/conda" config --append channels conda-forge
+ @echo "Please add '$(ANACONDA_HOME)/bin' to your PATH variable in '.bashrc'."
.PHONY: conda_env
-conda_env: anaconda conda_config
- @echo "Update conda environment $(CONDA_ENV) ..."
- @test -d $(CONDA_ENV_PATH) || "$(ANACONDA_HOME)/bin/conda" env create -n $(CONDA_ENV) -f environment.yml
- "$(ANACONDA_HOME)/bin/conda" install -y -n $(CONDA_ENV) setuptools=$(SETUPTOOLS_VERSION)
-
-.PHONY: conda_pinned
-conda_pinned: conda_env
- @echo "Update pinned conda packages ..."
- @-test -d $(CONDA_ENV_PATH) && test -f $(CONDA_PINNED) && cp -f "$(CONDA_PINNED)" "$(CONDA_ENV_PATH)/conda-meta/pinned"
-
-.PHONY: export
-export:
- @echo "Exporting conda enviroment ..."
- @test -d $(CONDA_ENV_PATH) && "$(ANACONDA_HOME)/bin/conda" env export -n $(CONDA_ENV) -f environment.yml
+conda_env: anaconda
+ @echo "Updating conda environment $(CONDA_ENV) ..."
+ "$(ANACONDA_HOME)/bin/conda" env update -n $(CONDA_ENV) -f environment.yml
## Build targets
.PHONY: bootstrap
-bootstrap: init conda_env conda_pinned bootstrap-buildout.py
- @echo "Bootstrap buildout ..."
- @test -f bin/buildout || bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV);python bootstrap-buildout.py -c custom.cfg --allow-site-packages --setuptools-version=$(SETUPTOOLS_VERSION) --buildout-version=$(BUILDOUT_VERSION)"
+bootstrap: conda_env bootstrap_dev
+ @echo "Bootstrap ..."
-.PHONY: sysinstall
-sysinstall:
- @echo "\nInstalling system packages for bootstrap ..."
- @bash bootstrap.sh -i
- @echo "\nInstalling system packages for your application ..."
- @-test -f requirements.sh && bash requirements.sh
+.PHONY: bootstrap_dev
+bootstrap_dev:
+ @echo "Installing development requirements for tests and docs ..."
+ @-bash -c "$(ANACONDA_HOME)/bin/conda install -y -n $(CONDA_ENV) pytest flake8 sphinx"
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV) && pip install -r requirements_dev.txt"
.PHONY: install
install: bootstrap
- @echo "Installing application with buildout ..."
- @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV);bin/buildout buildout:anaconda-home=$(ANACONDA_HOME) -c custom.cfg"
+ @echo "Installing application..."
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV) && python setup.py develop"
@echo "\nStart service with \`make start'"
-.PHONY: update
-update:
- @echo "Update application config with buildout (offline mode) ..."
- @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV);bin/buildout buildout:anaconda-home=$(ANACONDA_HOME) -o -c custom.cfg"
-
-.PHONY: update-config
-update-config:
- @echo "Update application config with buildout (offline mode) and environment variables..."
- @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV);bin/buildout buildout:anaconda-home=$(ANACONDA_HOME) settings:hostname=$(HOSTNAME) settings:output-port=$(OUTPUT_PORT) settings:http-port=$(HTTP_PORT) -o -c custom.cfg"
+.PHONY: start
+start:
+ @echo "Starting application ..."
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV) && $(APP_NAME) -a -d"
.PHONY: clean
clean: srcclean envclean
- @echo "Cleaning buildout files ..."
- @-for i in $(BUILDOUT_FILES); do \
- test -e $$i && rm -v -rf $$i; \
- done
+ @echo "Cleaning generated files ..."
+ @-for i in $(TEMP_FILES); do \
+ test -e $$i && rm -v -rf $$i; \
+ done
.PHONY: envclean
envclean: stop
@@ -286,10 +249,10 @@ srcclean:
@-find $(APP_ROOT) -type f -name "*.pyc" -print | xargs rm
.PHONY: distclean
-distclean: backup clean
- @echo "Cleaning distribution ..."
+distclean: clean
+ @echo "Cleaning ..."
@git diff --quiet HEAD || echo "There are uncommited changes! Not doing 'git clean' ..."
- @-git clean -dfx -e *.bak -e custom.cfg -e Makefile.config
+ @-git clean -dfx -e *.bak -e custom.cfg
.PHONY: passwd
passwd: custom.cfg
@@ -302,22 +265,24 @@ passwd: custom.cfg
.PHONY: test
test:
@echo "Running tests (skip slow and online tests) ..."
- bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV); bin/py.test -v -m 'not slow and not online'"
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV);pytest -v -m 'not slow and not online'"
.PHONY: testall
testall:
@echo "Running all tests (including slow and online tests) ..."
- bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV); bin/py.test -v"
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV) && pytest -v"
.PHONY: pep8
pep8:
@echo "Running pep8 code style checks ..."
- $(CONDA_ENV_PATH)/bin/flake8
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV) && flake8"
+
+## Sphinx targets
.PHONY: docs
docs:
@echo "Generating docs with Sphinx ..."
- $(MAKE) -C $@ clean html
+ @-bash -c "source $(ANACONDA_HOME)/bin/activate $(CONDA_ENV);$(MAKE) -C $@ clean html"
@echo "open your browser: firefox docs/build/html/index.html"
.PHONY: linkcheck
diff --git a/{{cookiecutter.project_slug}}/Makefile.config.example b/{{cookiecutter.project_slug}}/Makefile.config.example
deleted file mode 100644
index fccdcaa54..000000000
--- a/{{cookiecutter.project_slug}}/Makefile.config.example
+++ /dev/null
@@ -1,3 +0,0 @@
-# Anaconda
-ANACONDA_HOME ?= /opt/anaconda
-CONDA_ENVS_DIR ?= /opt/anaconda/envs
diff --git a/{{cookiecutter.project_slug}}/bootstrap.sh b/{{cookiecutter.project_slug}}/bootstrap.sh
deleted file mode 100755
index 8f4dc1c0e..000000000
--- a/{{cookiecutter.project_slug}}/bootstrap.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-
-usage() {
- cat <`_ and run as the installation user.
+Install from GitHub
+-------------------
-Now, check out the {{ cookiecutter.project_slug }} code from GitHub and start the installation:
+Check out code from the {{ cookiecutter.project_name }} GitHub repo and start the installation:
.. code-block:: sh
$ git clone https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}.git
$ cd {{ cookiecutter.project_slug }}
- $ make clean install
+ $ conda env create -f environment.yml
+ $ source activate {{ cookiecutter.project_slug }}
+ $ python setup.py develop
-After successful installation you need to start the services:
+Install the lazy way
+--------------------
+
+The previous installation instructions assume you have Anaconda installed.
+We provide also a ``Makefile`` to run this installation without additional steps:
.. code-block:: sh
- $ make start # starts supervisor services
- $ make status # shows supervisor status
+ $ git clone https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}.git
+ $ cd {{ cookiecutter.project_slug }}
+ $ make clean # cleans up a previous Conda environment
+ $ make install # installs Conda if necessary and runs the above installation steps
-The depolyed WPS service is by default available on http://localhost:{{ cookiecutter.http_port }}/wps?service=WPS&version=1.0.0&request=GetCapabilities.
+Start {{ cookiecutter.project_name }} PyWPS service
+-----------------------
-Check the log files for errors:
+After successful installation you can start the service using the ``{{ cookiecutter.project_slug }}`` command-line.
.. code-block:: sh
- $ tail -f ~/birdhouse/var/log/pywps/{{ cookiecutter.project_slug }}.log
- $ tail -f ~/birdhouse/var/log/supervisor/{{ cookiecutter.project_slug }}.log
+ $ {{ cookiecutter.project_slug }} --help # show help
+ $ {{ cookiecutter.project_slug }} # start service with default configuration
-You will find more information about the installation in the `Makefile documentation `_.
+ OR
-Non-default installation
-------------------------
+ $ {{ cookiecutter.project_slug }} --daemon # start service as daemon
+ loading configuration
+ forked process id: 42
-You can customize the installation to use different ports, locations and run user.
+The deployed WPS service is by default available on:
-To change the anaconda location edit the ``Makefile.config``, for example::
+http://localhost:{{ cookiecutter.http_port }}/wps?service=WPS&version=1.0.0&request=GetCapabilities.
- ANACONDA_HOME ?= /opt/anaconda
- CONDA_ENVS_DIR ?= /opt/anaconda/envs
+.. NOTE:: Remember the process ID (PID) so you can stop the service with ``kill PID``.
-You can install {{ cookiecutter.project_slug }} as ``root`` and run it as unprivileged user like ``www-data``:
+Check the log files for errors:
.. code-block:: sh
- root$ mkdir -p /opt/birdhouse/src
- root$ cd /opt/birdhouse/src
- root$ git clone https://github.com/bird-house/{{ cookiecutter.project_slug }}.git
- root$ cd {{ cookiecutter.project_slug }}
+ $ tail -f pywps.log
-Edit ``custom.cfg``:
+Run {{ cookiecutter.project_name }} as Docker container
+---------------------------
-.. code-block:: ini
+You can also run {{ cookiecutter.project_name }} as a Docker container, see the :ref:`Tutorial `.
- [buildout]
- extends = buildout.cfg
-
- [settings]
- hostname = {{ cookiecutter.project_slug }}
- http-port = 80
- output-port = 8000
- log-level = WARN
-
- # deployment options
- prefix = /opt/birdhouse
- user = www-data
- etc-user = root
-
-Run the installtion and start the services:
-
-.. code-block:: sh
+Use Ansible to deploy {{ cookiecutter.project_name }} on your System
+----------------------------------------
- root$ make clean install
- root$ make start # stop or restart
- root$ make status
+Use the `Ansible playbook`_ for PyWPS to deploy {{ cookiecutter.project_name }} on your system.
+Follow the `example`_ for {{ cookiecutter.project_name }} given in the playbook.
-.. _Anaconda: https://www.continuum.io/
+.. _Ansible playbook: http://ansible-wps-playbook.readthedocs.io/en/latest/index.html
+.. _example: http://ansible-wps-playbook.readthedocs.io/en/latest/tutorial.html
diff --git a/{{cookiecutter.project_slug}}/environment.yml b/{{cookiecutter.project_slug}}/environment.yml
index 7882d0566..41f2d88b7 100644
--- a/{{cookiecutter.project_slug}}/environment.yml
+++ b/{{cookiecutter.project_slug}}/environment.yml
@@ -4,32 +4,6 @@ channels:
- conda-forge
- defaults
dependencies:
-- python=2.7
-- pyopenssl=0.16
-- cryptography=1.4
-- pyyaml=3.11
-- curl=7.45.0
-- icu=58
-# buildout
-- mako
-# tests
-- pytest
-# pep8
-- flake8
-# py2/3 compat
-- six
-# docs
-- sphinx
-- doc8
-# wps
-- pywps=4.0.0
-- click=6
-- nginx=1.10.3
-- supervisor=3.3
-- gunicorn=19
-- lxml
-- libxslt
-- genshi=0.7
-- pip:
- - sphinx-autoapi==0.5.0
- - -e git+https://github.com/huard/sphinx-autodoc-pywps.git#egg=sphinx_autodoc_pywps
+- pywps=4.1.0
+- jinja2
+- click
diff --git a/{{cookiecutter.project_slug}}/etc/debug.cfg b/{{cookiecutter.project_slug}}/etc/debug.cfg
new file mode 100644
index 000000000..c00a2b7ff
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/etc/debug.cfg
@@ -0,0 +1,2 @@
+[logging]
+level = DEBUG
diff --git a/{{cookiecutter.project_slug}}/etc/demo.cfg b/{{cookiecutter.project_slug}}/etc/demo.cfg
new file mode 100644
index 000000000..52145a38e
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/etc/demo.cfg
@@ -0,0 +1,2 @@
+[logging]
+level = WARN
diff --git a/{{cookiecutter.project_slug}}/etc/sample-custom.cfg b/{{cookiecutter.project_slug}}/etc/sample-custom.cfg
new file mode 100644
index 000000000..e708743cd
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/etc/sample-custom.cfg
@@ -0,0 +1,6 @@
+[server]
+url = http://demo.org:{{ cookiecutter.http_port }}/wps
+outputurl = http://demo.org:{{ cookiecutter.http_port }}/outputs
+
+[logging]
+level = DEBUG
diff --git a/{{cookiecutter.project_slug}}/etc/sample-postgres.cfg b/{{cookiecutter.project_slug}}/etc/sample-postgres.cfg
new file mode 100644
index 000000000..a16b9049f
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/etc/sample-postgres.cfg
@@ -0,0 +1,3 @@
+[logging]
+level = INFO
+database = postgresql+psycopg2://postgres:postgres@localhost:5432/postgres
diff --git a/{{cookiecutter.project_slug}}/requirements.txt b/{{cookiecutter.project_slug}}/requirements.txt
index bc7979b5f..3a41542b5 100644
--- a/{{cookiecutter.project_slug}}/requirements.txt
+++ b/{{cookiecutter.project_slug}}/requirements.txt
@@ -1,3 +1,3 @@
pywps>=4.0.0
-werkzeug
+jinja2
click
diff --git a/{{cookiecutter.project_slug}}/setup.py b/{{cookiecutter.project_slug}}/setup.py
index 38db9171e..7e9ad3bcc 100644
--- a/{{cookiecutter.project_slug}}/setup.py
+++ b/{{cookiecutter.project_slug}}/setup.py
@@ -17,10 +17,10 @@
test_requirements = [{%- if cookiecutter.use_pytest == 'y' %}'pytest>=3',{%- endif %} ]
{%- set license_classifiers = {
+ 'Apache Software License 2.0': 'License :: OSI Approved :: Apache Software License',
'MIT license': 'License :: OSI Approved :: MIT License',
'BSD license': 'License :: OSI Approved :: BSD License',
'ISC license': 'License :: OSI Approved :: ISC License (ISCL)',
- 'Apache Software License 2.0': 'License :: OSI Approved :: Apache Software License',
'GNU General Public License v3': 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)'
} %}
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py
index 6e541cca1..3c61e94bb 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py
@@ -1,7 +1,7 @@
"""Top-level package for {{ cookiecutter.project_name }}."""
from .wsgi import application
-from .cli import main
+from .cli import cli
__author__ = """{{ cookiecutter.full_name }}"""
__email__ = '{{ cookiecutter.email }}'
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/cli.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/cli.py
index 2d1bb23cf..7c20e32f3 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/cli.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/cli.py
@@ -1,5 +1,11 @@
"""Console script for {{cookiecutter.project_slug}}."""
+###########################################################
+# Demo WPS service for testing and debugging.
+#
+# See the werkzeug documentation on how to use the debugger:
+# http://werkzeug.pocoo.org/docs/0.12/debug/
+###########################################################
import os
import sys
@@ -9,6 +15,7 @@
{%- if cookiecutter.command_line_interface|lower == 'click' %}
import click
{%- endif %}
+from jinja2 import Environment, PackageLoader, select_autoescape
from pywps import configuration
from . import wsgi
@@ -18,12 +25,24 @@
logging.basicConfig(format='%(message)s', level=logging.INFO)
LOGGER = logging.getLogger('DEMO')
+template_env = Environment(
+ loader=PackageLoader('{{ cookiecutter.project_slug }}', 'templates'),
+ autoescape=select_autoescape(['yml', 'xml'])
+)
+
+def write_user_config(**kwargs):
+ config_templ = template_env.get_template('pywps.cfg')
+ rendered_config = config_templ.render(**kwargs)
+ config_file = os.path.abspath(os.path.join(os.path.curdir, "custom.cfg"))
+ with open(config_file, 'w') as fp:
+ fp.write(rendered_config)
+ return config_file
def get_host():
url = configuration.get_config_value('server', 'url')
- url = url or 'http://localhost:5000/wps'
+ url = url or 'http://localhost:{{ cookiecutter.http_port }}/wps'
- LOGGER.warn("starting WPS service on %s", url)
+ LOGGER.warn("starting WPS service on %s" % url)
parsed_url = urlparse(url)
if ':' in parsed_url.netloc:
@@ -48,63 +67,66 @@ def _run(application, bind_host=None, daemon=False):
hostname=bind_host,
port=port,
application=application,
- use_debugger=True,
- use_reloader=True,
+ use_debugger=False,
+ use_reloader=False,
+ threaded=True,
+ # processes=2,
use_evalex=not daemon,
static_files=static_files)
{% if cookiecutter.command_line_interface|lower == 'click' %}
@click.command()
-def main(args=None):
- """Console script for {{cookiecutter.project_slug}}."""
- click.echo("Replace this message by putting your code into "
- "{{cookiecutter.project_slug}}.cli.main")
- click.echo("See click documentation at https://click.palletsprojects.com/")
- return 0
-{%- endif %}
-{%- if cookiecutter.command_line_interface|lower == 'argparse' %}
-def main():
- parser = argparse.ArgumentParser(
- description="""Script for starting a demo WPS instance.
- This service is by default available at http://localhost:5000/wps""",
- epilog="""Do not use this service in a production environment.
- It's intended to be running in a test environment only!
- For more documentation, visit http://bird-house.github.io/
- """
- )
- parser.add_argument('--debug',
- action="store_true", help="enable debug logging mode")
- parser.add_argument('-c', '--config',
- help="path to pywps configuration file")
- parser.add_argument('-a', '--all-addresses',
- action='store_true', help="run service using IPv4 0.0.0.0 (all network interfaces), "
- "otherwise bind to 127.0.0.1 (localhost).")
- parser.add_argument('-d', '--daemon',
- action='store_true', help="run in daemon mode")
- args = parser.parse_args()
+@click.option('--config', metavar='PATH', help='path to pywps configuration file.')
+@click.option('--bind-host', metavar='IP-ADDRESS', default='0.0.0.0',
+ help='IP address used to bind service.')
+@click.option('--daemon/--no-daemon', default=False, help='run in daemon mode.')
+@click.option('--hostname', metavar='HOSTNAME', default='localhost', help='hostname in PyWPS configuration.')
+@click.option('--port', metavar='PORT', default='{{ cookiecutter.http_port }}', help='port in PyWPS configuration.')
+@click.option('--maxsingleinputsize', default='200mb', help='maxsingleinputsize in PyWPS configuration.')
+@click.option('--maxprocesses', metavar='INT', default='10', help='maxprocesses in PyWPS configuration.')
+@click.option('--parallelprocesses', metavar='INT', default='2', help='parallelprocesses in PyWPS configuration.')
+@click.option('--log-level', metavar='LEVEL', default='INFO', help='log level in PyWPS configuration.')
+@click.option('--log-file', metavar='PATH', default='pywps.log', help='log file in PyWPS configuration.')
+@click.option('--database', default='sqlite:///pywps-logs.sqlite', help='database in PyWPS configuration')
+def cli(config, bind_host, daemon, hostname, port,
+ maxsingleinputsize, maxprocesses, parallelprocesses,
+ log_level, log_file, database):
+ """Command line for starting a PyWPS service.
+ This service is by default available at http://localhost:{{ cookiecutter.http_port }}/wps
+
+ Do not use this service in a production environment.
+ It's intended to be running in a test environment only!
+ For more documentation, visit http://pywps.org/doc
+ """
cfgfiles = []
- if args.config:
- cfgfiles.append(args.config)
- LOGGER.warn('using pywps configuration: %s', args.config)
- if args.debug:
- cfgfiles.append(os.path.join(os.path.dirname(__file__), 'debug.cfg'))
- if args.all_addresses:
- bind_host = '0.0.0.0'
- else:
- bind_host = '127.0.0.1'
+ cfgfiles.append(write_user_config(
+ wps_hostname=hostname,
+ wps_port=port,
+ wps_maxsingleinputsize=maxsingleinputsize,
+ wps_maxprocesses=maxprocesses,
+ wps_parallelprocesses=parallelprocesses,
+ wps_log_level=log_level,
+ wps_log_file=log_file,
+ wps_database=database,
+ ))
+ if config:
+ cfgfiles.append(config)
app = wsgi.create_app(cfgfiles)
# let's start the service ...
- if args.daemon:
+ # See:
+ # * https://github.com/geopython/pywps-flask/blob/master/demo.py
+ # * http://werkzeug.pocoo.org/docs/0.14/serving/
+ if daemon:
# daemon (fork) mode
pid = None
try:
pid = os.fork()
if pid:
- LOGGER.warn('forked process id: %s', pid)
+ LOGGER.warn('forked process id: {}'.format(pid))
except OSError as e:
raise Exception("%s [%d]" % (e.strerror, e.errno))
- if (pid == 0):
+ if pid == 0:
os.setsid()
_run(app, bind_host=bind_host, daemon=True)
else:
@@ -113,7 +135,3 @@ def main():
# no daemon
_run(app, bind_host=bind_host)
{%- endif %}
-
-
-if __name__ == "__main__":
- sys.exit(main()) # pragma: no cover
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/default.cfg b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/default.cfg
index e94bdb8cd..1bc7f1bc4 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/default.cfg
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/default.cfg
@@ -7,12 +7,12 @@ provider_name = {{ cookiecutter.project_name }}
provider_url=http://{{ cookiecutter.project_slug }}.readthedocs.org/en/latest/
[server]
-url = http://localhost:5000/wps
-outputurl = http://localhost:5000/outputs
+url = http://localhost:{{ cookiecutter.http_port }}/wps
+outputurl = http://localhost:{{ cookiecutter.http_port }}/outputs
allowedinputpaths = /
maxsingleinputsize = 200mb
-sethomedir = true
-setworkdir = true
+maxprocesses = 10
+parallelprocesses = 2
[logging]
level = INFO
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pywps.cfg b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pywps.cfg
new file mode 100644
index 000000000..20951f8ae
--- /dev/null
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pywps.cfg
@@ -0,0 +1,27 @@
+[server]
+{% if wps_url %}
+url = {{ wps_url }}
+{% else %}
+url = http://{{ wps_hostname }}:{{ wps_port }}/wps
+{% endif %}
+{% if wps_outputurl %}
+outputurl = {{ wps_outputurl }}
+{% else %}
+outputurl = http://{{ wps_hostname }}:{{ wps_port }}/outputs
+{% endif %}
+allowedinputpaths = /
+maxsingleinputsize = {{ wps_maxsingleinputsize|default('200mb') }}
+maxprocesses = {{ wps_maxprocesses|default('10') }}
+parallelprocesses = {{ wps_parallelprocesses|default('2') }}
+{% if wps_outputpath %}
+outputpath= {{ wps_outputpath }}
+{% endif %}
+{% if wps_workdir %}
+workdir={{ wps_workdir }}
+{% endif %}
+
+[logging]
+level = {{ wps_log_level|default('INFO') }}
+file = {{ wps_log_file|default('pywps.log') }}
+database = {{ wps_database|default('sqlite:///pywps-logs.sqlite') }}
+format = %(asctime)s] [%(levelname)s] line=%(lineno)s module=%(module)s %(message)s