[Git][debian-gis-team/pywps][master] 11 commits: New upstream version 4.7.0
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Mon Dec 15 13:37:19 GMT 2025
Bas Couwenberg pushed to branch master at Debian GIS Project / pywps
Commits:
35a8a6bd by Bas Couwenberg at 2025-12-15T13:00:30+01:00
New upstream version 4.7.0
- - - - -
27f65188 by Bas Couwenberg at 2025-12-15T13:00:31+01:00
Update upstream source from tag 'upstream/4.7.0'
Update to upstream version '4.7.0'
with Debian dir 60f3c8ce57fbe3cde7c14ea1e727a8d275a3c669
- - - - -
4d5188e2 by Bas Couwenberg at 2025-12-15T13:00:51+01:00
New upstream release.
- - - - -
a525f598 by Bas Couwenberg at 2025-12-15T13:05:10+01:00
Refresh patches.
- - - - -
33279af4 by Bas Couwenberg at 2025-12-15T13:09:49+01:00
Make pytest output extra verbose.
- - - - -
87d62929 by Bas Couwenberg at 2025-12-15T13:21:29+01:00
Don't install joblauncher.
- - - - -
8529210c by Bas Couwenberg at 2025-12-15T13:32:42+01:00
Replace python3-gdal with python3-fiona.
- - - - -
472d1a43 by Bas Couwenberg at 2025-12-15T13:43:50+01:00
Copy all files to build directory.
- - - - -
6f95b3bf by Bas Couwenberg at 2025-12-15T13:55:20+01:00
Fix nodoc build.
- - - - -
9dc0dd71 by Bas Couwenberg at 2025-12-15T14:36:54+01:00
Use pytest marker to skip online tests.
- - - - -
d1f63691 by Bas Couwenberg at 2025-12-15T14:36:54+01:00
Use autopkgtest-pkg-pybuild testsuite.
- - - - -
29 changed files:
- .github/workflows/main.yml
- + .readthedocs.yml
- − INSTALL.md
- + Makefile
- README.md
- VERSION.txt
- debian/changelog
- debian/control
- debian/patches/offline-tests.patch
- − debian/python3-pywps.install
- + debian/pywps-doc.docs
- − debian/pywps-doc.install
- debian/rules
- default-sample.cfg
- + environment.yml
- pyproject.toml
- pywps/__init__.py
- pywps/configuration.py
- pywps/inout/literaltypes.py
- pywps/templates/1.0.0/execute/main.xml
- pywps/templates/2.0.0/capabilities/main.xml
- pywps/validator/complexvalidator.py
- requirements-dev.txt
- requirements.txt
- setup.cfg
- setup.py
- tests/test_assync.py
- tests/validator/test_complexvalidators.py
- tox.ini
Changes:
=====================================
.github/workflows/main.yml
=====================================
@@ -1,4 +1,4 @@
-name: build ⚙️
+name: Build PyWPS ⚙️
on:
push:
@@ -7,51 +7,69 @@ on:
pull_request:
jobs:
+ lint:
+ name: Linting Suite
+ runs-on: ubuntu-latest
+ steps:
+ - name: Cancel previous runs
+ uses: styfle/cancel-workflow-action at 0.11.0
+ with:
+ access_token: ${{ github.token }}
+ - uses: actions/checkout at v4
+ - uses: actions/setup-python at v5
+ with:
+ python-version: "3.10"
+ - name: Install tox
+ run: |
+ pip install tox>=4.0
+ - name: Run linting suite ⚙️
+ run: |
+ tox -e lint
+
test:
+ name: Testing with Python${{ matrix.python-version }}
+ needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
include:
- - tox-env: py38-extra
- python-version: "3.8"
- - tox-env: py39-extra
- python-version: "3.9"
- tox-env: py310-extra
python-version: "3.10"
- tox-env: py311-extra
python-version: "3.11"
+ - tox-env: py312-extra
+ python-version: "3.12"
+ - tox-env: py313-extra
+ python-version: "3.13"
steps:
- - uses: actions/checkout at v3
+ - uses: actions/checkout at v4
- name: Install packages 📦
run: |
sudo apt-get update
sudo apt-get -y install libnetcdf-dev libhdf5-dev
- - uses: actions/setup-python at v4
+ - uses: actions/setup-python at v5
name: Setup Python ${{ matrix.python-version }}
with:
python-version: ${{ matrix.python-version }}
- - name: Run flake8 ⚙️
- run: |
- pip install flake8
- flake8 pywps
- if: matrix.python-version == 3.8
- name: Install tox 📦
run: pip install "tox>=4.0"
- name: Run tests with tox ⚙️
run: tox -e ${{ matrix.tox-env }}
- name: Run coveralls ⚙️
- if: matrix.python-version == 3.8
+ if: matrix.python-version == 3.10
uses: AndreMiras/coveralls-python-action at develop
docs:
+ name: Build docs 🏗️
+ needs: lint
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout at v3
- - uses: actions/setup-python at v4
- name: Setup Python 3.8
+ - uses: actions/checkout at v4
+ - uses: actions/setup-python at v5
+ name: Setup Python 3.10
with:
- python-version: 3.8
- - name: Build docs 🏗️
+ python-version: "3.10"
+ - name: Build documentation 🏗️
run: |
pip install -e .[dev]
cd docs && make html
=====================================
.readthedocs.yml
=====================================
@@ -0,0 +1,27 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See: https://docs.readthedocs.io/en/stable/config-file/v2.html
+
+version: 2 # Required
+
+# Documentation formats to build and make available
+formats:
+ - pdf
+ - epub
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11" # Use standard CPython version; `mambaforge-22.9` is not valid here
+
+# Python-related configuration
+python:
+ install:
+ - method: pip
+ path: .
+ extra_requirements:
+ - dev
+
+# Sphinx configuration
+sphinx:
+ configuration: docs/conf.py
=====================================
INSTALL.md deleted
=====================================
@@ -1,44 +0,0 @@
-PyWPS 4 Installation
-====================
-
-Dependencies
-------------
-
-To use PyWPS 4 the third party libraries GIT and GDAL need to be installed in the system.
-
-In Debian based systems these can be installed with:
-
- $ sudo apt-get install git python-gdal
-
-In Windows systems a Git client should be installed (e.g. GitHub for Windows).
-
-Install PyWPS 4
----------------
-
-Using pip:
-
- $ sudo pip install -e git+https://github.com/geopython/pywps.git@main#egg=pywps
-
-Or in alternative install it manually:
-
- $ git clone https://github.com/geopython/pywps.git
-
- $ cd pywps/
-
- $ sudo pip install .
-
-Install example service
------------------------
-
- $ git clone https://github.com/geopython/pywps-flask.git pywps-flask
-
-
-Run example service
--------------------
-
- $ python demo.py
-
-Access example service
-----------------------
-
- http://localhost:5000
=====================================
Makefile
=====================================
@@ -0,0 +1,104 @@
+# Configuration
+APP_ROOT := $(abspath $(lastword $(MAKEFILE_LIST))/..)
+
+# end of configuration
+
+define PRINT_HELP_PYSCRIPT
+import re, sys
+
+for line in sys.stdin:
+ match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
+ if match:
+ target, help = match.groups()
+ print("%-20s %s" % (target, help))
+ else:
+ match = re.match(r'^## (.*)$$', line)
+ if match:
+ help = match.groups()[0]
+ print("\n%s" % (help))
+endef
+export PRINT_HELP_PYSCRIPT
+
+.DEFAULT_GOAL := help
+
+help: ## print this help message. (Default)
+ @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
+
+## Build targets:
+
+install: ## install pywps
+ @echo "Installing pywps ..."
+ @-bash -c 'pip install -e .'
+
+develop: ## install pywps with development libraries
+ @echo "Installing development requirements for tests and docs ..."
+ @-bash -c 'pip install -e ".[dev]"'
+
+clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
+
+clean-build: ## remove build artifacts
+ @echo "Removing build artifacts ..."
+ @-rm -fr build/
+ @-rm -fr dist/
+ @-rm -fr .eggs/
+ @-find . -name '*.egg-info' -exec rm -fr {} +
+ @-find . -name '*.egg' -exec rm -f {} +
+ @-find . -name '*.log' -exec rm -fr {} +
+ @-find . -name '*.sqlite' -exec rm -fr {} +
+
+clean-pyc: ## remove Python file artifacts
+ @echo "Removing Python file artifacts ..."
+ @-find . -name '*.pyc' -exec rm -f {} +
+ @-find . -name '*.pyo' -exec rm -f {} +
+ @-find . -name '*~' -exec rm -f {} +
+ @-find . -name '__pycache__' -exec rm -fr {} +
+
+clean-test: ## remove test and coverage artifacts
+ @echo "Removing test artifacts ..."
+ @-rm -fr .tox/
+ @-rm -f .coverage
+ @-rm -fr .pytest_cache
+
+clean-dist: clean ## remove git ignored files and directories
+ @echo "Running 'git clean' ..."
+ @git diff --quiet HEAD || echo "There are uncommitted changes! Aborting 'git clean' ..."
+ ## do not use git clean -e/--exclude here, add them to .gitignore instead
+ @-git clean -dfx
+
+clean-docs: ## remove documentation artifacts
+ @echo "Removing documentation artifacts ..."
+ $(MAKE) -C docs clean
+
+lint: ## check style with ruff
+ @echo "Running code style checks ..."
+ @bash -c 'ruff check pywps'
+
+## Testing targets:
+
+test: ## run tests quickly with the default Python (skip slow and online tests)
+ @echo "Running tests (skip slow and online tests) ..."
+ @bash -c 'pytest -v -m "not slow and not online" tests/'
+
+test-all: ## run all tests quickly with the default Python
+ @echo "Running all tests (including slow and online tests) ..."
+ @bash -c 'pytest -v tests/'
+
+## Sphinx targets:
+
+docs: clean-docs ## generate Sphinx HTML documentation, including API docs
+ @echo "Generating docs with Sphinx ..."
+ $(MAKE) -C docs html
+ @echo "Open your browser to: file:/$(APP_ROOT)/docs/build/html/index.html"
+ ## do not execute xdg-open automatically since it hangs ReadTheDocs and job does not complete
+ @echo "xdg-open $(APP_ROOT)/docs/build/html/index.html"
+
+
+## Deployment targets:
+
+# dist: clean ## builds source and wheel package
+# python -m flit build
+# ls -l dist
+
+# release: dist ## package and upload a release
+# python -m flit publish dist/*
+
=====================================
README.md
=====================================
@@ -7,21 +7,31 @@ the Open Geospatial Consortium. PyWPS is written in Python.
[](https://github.com/geopython/pywps/actions/workflows/main.yml)
[](https://coveralls.io/github/geopython/pywps?branch=main)
[](https://pypi.org/project/pywps/)
+[](https://anaconda.org/channels/conda-forge/packages/pywps/overview)
[]()
[](https://gitter.im/geopython/pywps?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-# License
+## License
As of PyWPS 4.0.0, PyWPS is released under an
[MIT](https://en.wikipedia.org/wiki/MIT_License) license
(see [LICENSE.txt](LICENSE.txt)).
-# Dependencies
+## Dependencies
See [requirements.txt](requirements.txt) file
-# Run tests
+## Install
+
+Install it from GitHub:
+```bash
+$ git clone https://github.com/geopython/pywps.git
+$ cd pywps/
+$ pip install .
+```
+
+## Run tests
```bash
pip install -r requirements-dev.txt
@@ -32,9 +42,37 @@ python -m coverage run --source=pywps -m unittest tests
python -m coverage report -m
```
-# Run web application
+## Quick Guide with Conda
-## Example service
+Checkout source from GitHub:
+```bash
+$ git clone https://github.com/geopython/pywps.git
+$ cd pywps/
+```
+
+Build conda environment:
+```bash
+conda env create -f environment.yml
+```
+
+Install pywps:
+```bash
+make install
+```
+
+Or the development version:
+```bash
+make develop
+```
+
+Run tests:
+```bash
+make tests
+```
+
+## Run web application
+
+### Example service
Clone the example service after having installed PyWPS:
@@ -44,7 +82,9 @@ cd pywps-flask
python demo.py
```
-## Apache configuration
+Access example service: http://localhost:5000
+
+### Apache configuration
1. Enable WSGI extension
@@ -92,7 +132,7 @@ python demo.py
```
-# Issues
+## Issues
On Windows PyWPS does not support multiprocessing which is used when making
requests storing the response document and updating the status to displaying
=====================================
VERSION.txt
=====================================
@@ -1 +1 @@
-4.6.0
+4.7.0
=====================================
debian/changelog
=====================================
@@ -1,14 +1,23 @@
-pywps (4.6.0-2) UNRELEASED; urgency=medium
+pywps (4.7.0-1) UNRELEASED; urgency=medium
* Team upload.
+ * New upstream release.
* Bump Standards-Version to 4.7.2, no changes.
* Fix old FSF address in copyright file.
* Mark pywps-doc as Multi-Arch: foreign.
* Update lintian overrides.
* Drop Rules-Requires-Root: no, default since dpkg 1.22.13.
* Use test-build-validate-cleanup instead of test-build-twice.
-
- -- Bas Couwenberg <sebastic at debian.org> Sun, 28 Jul 2024 20:00:42 +0200
+ * Refresh patches.
+ * Make pytest output extra verbose.
+ * Don't install joblauncher.
+ * Replace python3-gdal with python3-fiona.
+ * Copy all files to build directory.
+ * Fix nodoc build.
+ * Use pytest marker to skip online tests.
+ * Use autopkgtest-pkg-pybuild testsuite.
+
+ -- Bas Couwenberg <sebastic at debian.org> Mon, 15 Dec 2025 13:00:40 +0100
pywps (4.6.0-1) unstable; urgency=medium
=====================================
debian/control
=====================================
@@ -13,7 +13,7 @@ Build-Depends: debhelper-compat (= 13),
pybuild-plugin-pyproject,
python3-all,
python3-dateutil,
- python3-gdal,
+ python3-fiona,
python3-humanize,
python3-jinja2,
python3-jsonschema,
@@ -21,35 +21,23 @@ Build-Depends: debhelper-compat (= 13),
python3-markupsafe,
python3-netcdf4,
python3-owslib,
- python3-pytest,
+ python3-pytest <!nocheck>,
python3-requests,
python3-setuptools,
- python3-sphinx,
+ python3-sphinx <!nodoc>,
python3-sqlalchemy,
python3-werkzeug
Standards-Version: 4.7.2
Vcs-Browser: https://salsa.debian.org/debian-gis-team/pywps
Vcs-Git: https://salsa.debian.org/debian-gis-team/pywps.git
Homepage: https://pywps.org
+Testsuite: autopkgtest-pkg-pybuild
Package: python3-pywps
Architecture: all
-Depends: python3-dateutil,
- python3-gdal,
- python3-humanize,
- python3-jinja2,
- python3-jsonschema,
- python3-lxml,
- python3-markupsafe,
- python3-owslib,
- python3-requests,
- python3-sqlalchemy,
- python3-werkzeug,
- ${python3:Depends},
+Depends: ${python3:Depends},
${misc:Depends}
-Recommends: python3-mapscript,
- python3-netcdf4,
- python3-pyproj
+Recommends: python3-netcdf4
Suggests: grass-core,
r-base
Breaks: python-pywps (<< 4.2.1-2~)
=====================================
debian/patches/offline-tests.patch
=====================================
@@ -1,6 +1,6 @@
Description: Disable tests that require network.
Author: Bas Couwenberg <sebastic at debian.org>
-Forwarded: not-needed
+Forwarded: https://github.com/geopython/pywps/pull/698
--- a/tests/test_ows.py
+++ b/tests/test_ows.py
@@ -16,7 +16,7 @@ Forwarded: not-needed
supported_formats=[get_format('GEOTIFF')])],
grass_location='epsg:4326')
-+ @pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ @pytest.mark.online
def test_wfs(self):
if not service_ok('https://demo.mapserver.org'):
self.skipTest("mapserver is unreachable")
@@ -24,27 +24,41 @@ Forwarded: not-needed
# . the inclusion of output
# . the type of output
-+ @pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ @pytest.mark.online
def test_wcs(self):
if not config.CONFIG.get('grass', 'gisbase'):
self.skipTest('GRASS lib not found')
--- a/tests/validator/test_complexvalidators.py
+++ b/tests/validator/test_complexvalidators.py
-@@ -76,7 +76,8 @@ class ValidateTest(TestBase):
- self.assertTrue(validategml(gml_input, MODE.NONE), 'NONE validation')
- self.assertTrue(validategml(gml_input, MODE.SIMPLE), 'SIMPLE validation')
- self.assertTrue(validategml(gml_input, MODE.STRICT), 'STRICT validation')
-- self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
-+ if os.environ.get('OFFLINE_TESTS') == None:
-+ self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
+@@ -69,6 +69,7 @@ class ValidateTest(TestBase):
+
+ return fake_input
+
++ @pytest.mark.online
+ def test_gml_validator(self):
+ """Test GML validator
+ """
+@@ -79,6 +80,7 @@ class ValidateTest(TestBase):
+ # self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
gml_input.stream.close()
- def test_json_validator(self):
-@@ -133,6 +134,7 @@ class ValidateTest(TestBase):
++ @pytest.mark.online
+ @pytest.mark.xfail(reason="gml verystrict validation fails")
+ def test_gml_validator_verystrict(self):
+ """Test GML validator
+@@ -117,6 +119,7 @@ class ValidateTest(TestBase):
+ self.assertTrue(validateshapefile(shapefile_input, MODE.STRICT), 'STRICT validation')
+ shapefile_input.stream.close()
+
++ @pytest.mark.geotiff
+ def test_geotiff_validator(self):
+ """Test GeoTIFF validator
+ """
+@@ -141,6 +144,7 @@ class ValidateTest(TestBase):
else:
self.assertFalse(validatenetcdf(netcdf_input, MODE.STRICT), 'STRICT validation')
-+ @pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ @pytest.mark.online
@pytest.mark.xfail(reason="test.opendap.org is offline")
def test_dods_validator(self):
opendap_input = ComplexInput('dods', 'opendap test', [FORMATS.DODS,])
@@ -54,7 +68,7 @@ Forwarded: not-needed
class ExecuteTest(TestBase):
"""Test for Exeucte request KVP request"""
-+ @pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ @pytest.mark.online
@pytest.mark.xfail(reason="test.opendap.org is offline")
def test_dods(self):
if not WITH_NC4:
@@ -72,7 +86,7 @@ Forwarded: not-needed
with self.assertRaises(TypeError):
self.iohandler[0].data = '5'
-+ @pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ @pytest.mark.online
def test_url(self):
if not service_ok('https://demo.mapserver.org'):
self.skipTest("mapserver is unreachable")
@@ -80,7 +94,7 @@ Forwarded: not-needed
b = self.complex_out.base64
self.assertEqual(base64.b64decode(b).decode(), self.data)
-+ @pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ @pytest.mark.online
def test_url_handler(self):
wfsResource = 'http://demo.mapserver.org/cgi-bin/wfs?' \
'service=WFS&version=1.1.0&' \
@@ -88,7 +102,7 @@ Forwarded: not-needed
)
-+ at pytest.mark.skipif('OFFLINE_TESTS' in os.environ, reason="offline tests only")
++ at pytest.mark.online
class TestMetaLink(TestBase):
def setUp(self) -> None:
=====================================
debian/python3-pywps.install deleted
=====================================
@@ -1,2 +0,0 @@
-usr/bin/*
-usr/lib/python3*
=====================================
debian/pywps-doc.docs
=====================================
@@ -0,0 +1 @@
+docs/_build/html
=====================================
debian/pywps-doc.install deleted
=====================================
@@ -1 +0,0 @@
-docs/_build/html usr/share/doc/pywps/
=====================================
debian/rules
=====================================
@@ -12,15 +12,15 @@
# Enable hardening build flags
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
-export PYBUILD_BEFORE_TEST=cp -rv {dir}/pywps/schemas {build_dir}/pywps/
-export OFFLINE_TESTS=1
+export PYBUILD_NAME=pywps
+export PYBUILD_BEFORE_TEST=cp -rv {dir}/pywps {dir}/tests {build_dir}
+export PYBUILD_TEST_ARGS=-vv -m "not online and not geotiff"
%:
dh $@ --buildsystem=pybuild
execute_after_dh_auto_build:
+ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS)))
(cd docs && PYTHONPATH=$(CURDIR) $(MAKE) html && \
ln -s /usr/share/javascript/mathjax _build/html/_static/)
-
-override_dh_auto_test:
- dh_auto_test || echo "Ignoring test failures"
+endif
=====================================
default-sample.cfg
=====================================
@@ -61,6 +61,36 @@ maxprocesses=30
parallelprocesses=2
storagetype=file
+# hardcoded default : tempfile.gettempdir()
+; temp_path=/tmp
+
+processes_path=
+# list of allowed input paths (file url input) seperated by ':'
+allowedinputpaths=
+
+# hardcoded default : tempfile.gettempdir()
+; workdir=
+
+# If this flag is enabled it will set the HOME environment for each process to
+# its current workdir (a temp folder).
+sethomedir=false
+
+# If this flag is true PyWPS will remove the process temporary workdir after
+# process has finished.
+cleantempdir=true
+
+# File storage outputs can be copied, moved or linked from the workdir to the
+# output folder.
+# Allowed functions: "copy", "move", "link" (hardcoded default "copy")
+storage_copy_function=copy
+
+# Handles the default mimetype for requests.
+# valid options: "text/xml", "application/json"
+default_mimetype=text/xml
+
+# Default indentation used for json data responses.
+json_indent=2
+
# hardcoded default : tempfile.gettempdir()
#temp_path=/tmp
@@ -96,6 +126,12 @@ json_indent=2
[processing]
mode=default
+# hardcoded default: os.path.dirname(os.path.realpath(sys.argv[0]))
+; path=
+
+# https://github.com/natefoo/slurm-drmaa
+drmaa_native_specification=
+
# hardcoded default: os.path.dirname(os.path.realpath(sys.argv[0]))
#path=
=====================================
environment.yml
=====================================
@@ -0,0 +1,23 @@
+name: pywps
+channels:
+ - conda-forge
+dependencies:
+ - python >=3.10,<3.14
+ - pip >=25.0
+ - owslib >=0.35.0
+ - requests >=2.32.5
+ - werkzeug >=3.1.4
+ - sqlalchemy >=2.0.44
+ - lxml >=6.0.2
+ - urllib3 >=2.5.0
+ - markupsafe >=3.0.3
+ - numpy >=1.22.2
+ - zarr <3
+ - fiona
+ - geotiff
+ # tests
+ - pytest
+ - ruff >=0.5.7
+ # docs
+ - sphinx >=7.0.0
+
=====================================
pyproject.toml
=====================================
@@ -1,3 +1,11 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
+
+[tool.ruff]
+lint.select = ["E", "W", "F", "C90"] # Flake8-equivalent rule families
+lint.ignore = ["F401", "E402", "C901"]
+
+line-length = 120
+exclude = ["tests"]
+
=====================================
pywps/__init__.py
=====================================
@@ -8,7 +8,7 @@ import os
from lxml.builder import ElementMaker
-__version__ = "4.6.0"
+__version__ = "4.7.0"
LOGGER = logging.getLogger('PYWPS')
LOGGER.debug('setting core variables')
=====================================
pywps/configuration.py
=====================================
@@ -175,7 +175,7 @@ def load_configuration(cfgfiles=None):
:param cfgfiles: list of configuration files
"""
- global CONFIG
+ global CONFIG # noqa
load_hardcoded_configuration()
@@ -200,7 +200,7 @@ def load_configuration(cfgfiles=None):
def _check_config():
"""Check some configuration values
"""
- global CONFIG
+ global CONFIG # noqa
def checkdir(confid):
=====================================
pywps/inout/literaltypes.py
=====================================
@@ -32,7 +32,7 @@ def register_convert_type(name):
"""
def _register_convert_type(function):
- global LITERAL_DATA_TYPES
+ global LITERAL_DATA_TYPES # noqa
LITERAL_DATA_TYPES[name] = function
return function
=====================================
pywps/templates/1.0.0/execute/main.xml
=====================================
@@ -10,7 +10,7 @@
{% if wsdl %}
<wps:WSDL xlink:href="{{ process.wsdl }}"/>
{% endif %}
- </wps:Process>
+ </wps:Process>
<wps:Status creationTime="{{ status.time }}">
{% if status.status == "accepted" %}
<wps:ProcessAccepted percentCompleted="{{ status.percent_done }}">{{ status.message }}</wps:ProcessAccepted>
@@ -29,39 +29,39 @@
</wps:ExceptionReport>
</wps:ProcessFailed>
{% endif %}
- </wps:Status>
+ </wps:Status>
{% if lineage %}
{% if input_definitions %}
- <wps:DataInputs>
+ <wps:DataInputs>
{% for input in input_definitions %}
- <wps:Input>
+ <wps:Input>
<ows:Identifier>{{ input.identifier }}</ows:Identifier>
<ows:Title>{{ get_translation(input, "title", language) }}</ows:Title>
<ows:Abstract>{{ get_translation(input, "abstract", language) }}</ows:Abstract>
{% if input.type == "complex" %}
- <wps:Data>
+ <wps:Data>
<wps:ComplexData mimeType="{{ input.mimetype }}" encoding="{{ input.encoding }}" schema="{{ input.schema }}">{{ input.data | safe }}</wps:ComplexData>
- </wps:Data>
+ </wps:Data>
{% elif input.type == "literal" %}
- <wps:Data>
+ <wps:Data>
<wps:LiteralData {% if input.uom %}uom="{{ input.uom.reference }}"{% endif %}>{{ input.data }}</wps:LiteralData>
- </wps:Data>
+ </wps:Data>
{% elif input.type == "bbox" %}
- <wps:Data>
+ <wps:Data>
<wps:BoundingBoxData crs="{{ input.crs }}" dimensions="{{ input.dimensions }}">
<ows:LowerCorner>{% for c in input.ll %} {{ c }} {% endfor %}</ows:LowerCorner>
<ows:UpperCorner>{% for c in input.ur %} {{ c }} {% endfor %}</ows:UpperCorner>
</wps:BoundingBoxData>
- </wps:Data>
+ </wps:Data>
{% elif input.type == "reference" %}
<wps:Reference xlink:href="{{ input.href }}" method="{{ input.method }}" mimeType="{{ input.mimetype }}" encoding="{{ input.encoding }}" schema="{{ input.schema }}"/>
{% endif %}
- </wps:Input>
+ </wps:Input>
{% endfor %}
- </wps:DataInputs>
+ </wps:DataInputs>
{% endif %}
{% if output_definitions %}
- <wps:OutputDefinitions>
+ <wps:OutputDefinitions>
{% for output in output_definitions %}
{% if output.type in ["complex", "reference"] %}
<wps:Output mimeType="{{ output.mimetype }}" encoding="{{ output.encoding }}" schema="{{ output.schema }}" asReference="{{ output.asreference }}">
@@ -71,38 +71,38 @@
<ows:Identifier>{{ output.identifier }}</ows:Identifier>
<ows:Title>{{ get_translation(output, "title", language) }}</ows:Title>
<ows:Abstract>{{ get_translation(output, "abstract", language) }}</ows:Abstract>
- </wps:Output>
+ </wps:Output>
{% endfor %}
- </wps:OutputDefinitions>
+ </wps:OutputDefinitions>
{% endif %}
{% endif %}
{% if outputs %}
- <wps:ProcessOutputs>
+ <wps:ProcessOutputs>
{% for output in outputs %}
- <wps:Output>
+ <wps:Output>
<ows:Identifier>{{ output.identifier }}</ows:Identifier>
<ows:Title>{{ get_translation(output, "title", language) }}</ows:Title>
<ows:Abstract>{{ get_translation(output, "abstract", language) }}</ows:Abstract>
{% if output.type == "reference" %}
<wps:Reference href="{{ output.href }}" mimeType="{{ output.mimetype }}" encoding="{{ output.encoding }}" schema="{{ output.schema }}"/>
{% elif output.type == "complex" %}
- <wps:Data>
+ <wps:Data>
<wps:ComplexData mimeType="{{ output.mimetype }}" encoding="{{ output.encoding }}" schema="{{ output.schema }}">{{ output.data | safe }}</wps:ComplexData>
- </wps:Data>
+ </wps:Data>
{% elif output.type == "literal" %}
- <wps:Data>
+ <wps:Data>
<wps:LiteralData {% if output.uom %}uom="{{ output.uom.reference }}"{% endif %} dataType="{{ output.data_type }}">{{ output.data }}</wps:LiteralData>
- </wps:Data>
+ </wps:Data>
{% elif output.type == "bbox" %}
- <wps:Data>
+ <wps:Data>
<wps:BoundingBoxData crs="{{ output.crs }}" dimensions="{{ output.dimensions }}">
<ows:LowerCorner>{% for c in output.ll %} {{ c }} {% endfor %}</ows:LowerCorner>
<ows:UpperCorner>{% for c in output.ur %} {{ c }} {% endfor %}</ows:UpperCorner>
</wps:BoundingBoxData>
- </wps:Data>
+ </wps:Data>
{% endif %}
- </wps:Output>
+ </wps:Output>
{% endfor %}
- </wps:ProcessOutputs>
+ </wps:ProcessOutputs>
{% endif %}
</wps:ExecuteResponse>
=====================================
pywps/templates/2.0.0/capabilities/main.xml
=====================================
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- PyWPS {{ pywps_version }} -->
<wps:Capabilities xmlns:ows="http://www.opengis.net/ows/2.0" xmlns:wps="http://www.opengis.net/wps/2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/2.0 ../wps.xsd" service="WPS" version="2.0.0">
- <ows:ServiceIdentification>
+ <ows:ServiceIdentification>
<ows:Title>{{ title }}</ows:Title>
<ows:Abstract>{{ abstract }}</ows:Abstract>
<ows:Keywords>{% for keyword in keywords %}
<ows:Keyword>{{ keyword }}</ows:Keyword>{% endfor %}
- </ows:Keywords>
- <ows:ServiceType>WPS</ows:ServiceType>
- <ows:ServiceTypeVersion>2.0.0</ows:ServiceTypeVersion>
+ </ows:Keywords>
+ <ows:ServiceType>WPS</ows:ServiceType>
+ <ows:ServiceTypeVersion>2.0.0</ows:ServiceTypeVersion>
<ows:Fees>{{ fees }}</ows:Fees>
<ows:AccessConstraints>{% for ac in accessconstraints %}{{ ac }} {% endfor %}</ows:AccessConstraints>
- </ows:ServiceIdentification>
- <ows:ServiceProvider>
+ </ows:ServiceIdentification>
+ <ows:ServiceProvider>
<ows:ProviderName>{{ provider.name }}</ows:ProviderName>
<ows:ProviderSite xlink:href="{{ provider.site }}"/>
- <ows:ServiceContact>
+ <ows:ServiceContact>
<ows:individualname>{{ provider.individual }}</ows:individualname>
<ows:positionname>{{ provider.position }}</ows:positionname>
- <ows:ContactInfo>
+ <ows:ContactInfo>
<ows:Phone>
<ows:Voice>{{ provider.voice }}</ows:Voice>
<ows:Facsimile>{{ provider.fascimile }}</ows:Facsimile>
@@ -31,76 +31,76 @@
<ows:Country>{{ provider.address.country }}</ows:Country>
<ows:ElectronicMailAddress>{{ provider.address.email }}</ows:ElectronicMailAddress>
</ows:Address>
- </ows:ContactInfo>
- </ows:ServiceContact>
- </ows:ServiceProvider>
- <ows:OperationsMetadata>
- <ows:Operation name="GetCapabilities">
- <ows:DCP>
- <ows:HTTP>
+ </ows:ContactInfo>
+ </ows:ServiceContact>
+ </ows:ServiceProvider>
+ <ows:OperationsMetadata>
+ <ows:Operation name="GetCapabilities">
+ <ows:DCP>
+ <ows:HTTP>
<ows:Get xlink:href="{{ serviceurl }}"/>
<ows:Post xlink:href="{{ serviceurl }}"/>
- </ows:HTTP>
- </ows:DCP>
- </ows:Operation>
- <ows:Operation name="DescribeProcess">
- <ows:DCP>
- <ows:HTTP>
+ </ows:HTTP>
+ </ows:DCP>
+ </ows:Operation>
+ <ows:Operation name="DescribeProcess">
+ <ows:DCP>
+ <ows:HTTP>
<ows:Get xlink:href="{{ serviceurl }}"/>
<ows:Post xlink:href="{{ serviceurl }}"/>
- </ows:HTTP>
- </ows:DCP>
- </ows:Operation>
- <ows:Operation name="Execute">
- <ows:DCP>
- <ows:HTTP>
+ </ows:HTTP>
+ </ows:DCP>
+ </ows:Operation>
+ <ows:Operation name="Execute">
+ <ows:DCP>
+ <ows:HTTP>
<ows:Post xlink:href="{{ serviceurl }}"/>
- </ows:HTTP>
- </ows:DCP>
- </ows:Operation>
- <ows:Operation name="GetStatus">
- <ows:DCP>
- <ows:HTTP>
+ </ows:HTTP>
+ </ows:DCP>
+ </ows:Operation>
+ <ows:Operation name="GetStatus">
+ <ows:DCP>
+ <ows:HTTP>
<ows:Get xlink:href="{{ serviceurl }}"/>
<ows:Post xlink:href="{{ serviceurl }}"/>
- </ows:HTTP>
- </ows:DCP>
- </ows:Operation>
- <ows:Operation name="GetResult">
- <ows:DCP>
- <ows:HTTP>
+ </ows:HTTP>
+ </ows:DCP>
+ </ows:Operation>
+ <ows:Operation name="GetResult">
+ <ows:DCP>
+ <ows:HTTP>
<ows:Get xlink:href="{{ serviceurl }}"/>
<ows:Post xlink:href="{{ serviceurl }}"/>
- </ows:HTTP>
- </ows:DCP>
- </ows:Operation>
- <ows:Operation name="Dismiss">
- <ows:DCP>
- <ows:HTTP>
+ </ows:HTTP>
+ </ows:DCP>
+ </ows:Operation>
+ <ows:Operation name="Dismiss">
+ <ows:DCP>
+ <ows:HTTP>
<ows:Get xlink:href="{{ serviceurl }}"/>
<ows:Post xlink:href="{{ serviceurl }}"/>
- </ows:HTTP>
- </ows:DCP>
- </ows:Operation>
- </ows:OperationsMetadata>
+ </ows:HTTP>
+ </ows:DCP>
+ </ows:Operation>
+ </ows:OperationsMetadata>
<wps:Contents>{% for process in processes %}
<wps:ProcessSummary jobControlOptions="{% for option in process.control_options %}{{ option }} {% endfor %}" wps:processVersion="{{ process.version }}">
- <ows:Title>process.title</ows:Title>
- <ows:Identifier>process.identifier</ows:Identifier>
+ <ows:Title>process.title</ows:Title>
+ <ows:Identifier>process.identifier</ows:Identifier>
<ows:Abstract>{{ process.abstract }}</ows:Abstract>{% for metadata in process.metadata %}
<ows:Metadata xlink:title="{{ metadata.title }}" xlink:type="{{ metadata.type }}"
- {% if metadata.href != None %}
- xlink:href="{{ metadata.href }}"
- {% endif %}
- {% if metadata.role != None %}
- xlink:role="{{ metadata.role }}"
- {% endif %}
- />
- {% endfor %}
+ {% if metadata.href != None %}
+ xlink:href="{{ metadata.href }}"
+ {% endif %}
+ {% if metadata.role != None %}
+ xlink:role="{{ metadata.role }}"
+ {% endif %}
+ />
+ {% endfor %}
<ows:Keywords>{% for keyword in process.keywords %}
<ows:Keyword>{{ keyword }}</ows:Keyword>{% endfor %}
</ows:Keywords>
</wps:ProcessSummary>{% endfor %}
- </wps:Contents>
+ </wps:Contents>
</wps:Capabilities>
=====================================
pywps/validator/complexvalidator.py
=====================================
@@ -223,7 +223,7 @@ def validategeojson(data_input, mode):
>>> from io import StringIO
>>> class FakeInput(object):
... json = open('point.geojson','w')
- ... json.write('''{"type":"Feature", "properties":{}, "geometry":{"type":"Point", "coordinates":[8.5781228542328, 22.87500500679]}, "crs":{"type":"name", "properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}''') # noqa
+ ... json.write('''{"type":"Feature", "properties":{}, "geometry":{"type":"Point", "coordinates":[8.5781228542328, 22.87500500679]}, "crs":{"type":"name", "properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}''')
... json.close()
... file = 'point.geojson'
>>> class FakeDataFormat(object):
@@ -232,7 +232,7 @@ def validategeojson(data_input, mode):
>>> fake_input.data_format = FakeDataFormat()
>>> validategeojson(fake_input, MODE.SIMPLE)
True
- """
+ """ # noqa
LOGGER.info('validating GeoJSON; Mode: {}'.format(mode))
passed = False
=====================================
requirements-dev.txt
=====================================
@@ -2,7 +2,7 @@ bump2version
coverage
coveralls
docutils
-flake8
+ruff
pylint
pytest
pytest-cov
=====================================
requirements.txt
=====================================
@@ -2,6 +2,8 @@ markupsafe
sqlalchemy
fiona
geotiff
+tifffile <=2025.5.10
+zarr <3
humanize
jinja2
jsonschema
@@ -10,3 +12,5 @@ owslib
python-dateutil
requests
werkzeug
+urllib3>=2.5.0 # not directly required, pinned by Snyk to avoid a vulnerability
+numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability
=====================================
setup.cfg
=====================================
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 4.6.0
+current_version = 4.7.0
commit = False
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+).(?P<patch>\d+)
@@ -16,12 +16,3 @@ replace = {new_version}
[coverage:run]
relative_files = True
-
-[flake8]
-ignore =
- F401
- E402
- W606
-max-line-length = 120
-exclude = tests
-
=====================================
setup.py
=====================================
@@ -49,17 +49,17 @@ CONFIG = {
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.8",
- "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
"Topic :: Scientific/Engineering :: GIS",
],
"install_requires": INSTALL_REQUIRES,
"extras_require": dict(
dev=DEV_REQUIRES,
),
- "python_requires": ">=3.8,<4",
+ "python_requires": ">=3.10,<4",
"packages": find_packages(exclude=["docs", "tests.*", "tests"]),
"include_package_data": True,
"scripts": [],
=====================================
tests/test_assync.py
=====================================
@@ -27,6 +27,7 @@ class ExecuteTest(TestBase):
# Running processes using the MultiProcessing scheduler and a file-based database
configuration.CONFIG.set('processing', 'mode', 'distributed')
+ @pytest.mark.xfail(reason="async fails")
def test_async(self):
client = client_for(Service(processes=[Sleep()]))
wps = WPSExecution()
=====================================
tests/validator/test_complexvalidators.py
=====================================
@@ -76,6 +76,14 @@ class ValidateTest(TestBase):
self.assertTrue(validategml(gml_input, MODE.NONE), 'NONE validation')
self.assertTrue(validategml(gml_input, MODE.SIMPLE), 'SIMPLE validation')
self.assertTrue(validategml(gml_input, MODE.STRICT), 'STRICT validation')
+ # self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
+ gml_input.stream.close()
+
+ @pytest.mark.xfail(reason="gml verystrict validation fails")
+ def test_gml_validator_verystrict(self):
+ """Test GML validator
+ """
+ gml_input = self.get_input('gml/point.gml', 'point.xsd', FORMATS.GML.mime_type)
self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
gml_input.stream.close()
=====================================
tox.ini
=====================================
@@ -1,9 +1,19 @@
[tox]
min_version = 4.0
-envlist = py{37,38,39,310,311}{-extra,}
-requires = pip >= 20.0
+envlist =
+ py{310,311,312,313}{-extra,},
+ lint
+requires = pip >=25.2
opts = --verbose
+[testenv:lint]
+skip_install = true
+extras =
+deps =
+ ruff
+commands =
+ ruff check pywps
+
[testenv]
setenv =
PYTEST_ADDOPTS = "--color=yes"
View it on GitLab: https://salsa.debian.org/debian-gis-team/pywps/-/compare/ba9375579387045397abd1325fe9174874ffdc4f...d1f636918c2342381d5838f788abd692e49504ed
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/pywps/-/compare/ba9375579387045397abd1325fe9174874ffdc4f...d1f636918c2342381d5838f788abd692e49504ed
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20251215/9927be1c/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list