[Git][debian-gis-team/pywps][upstream] New upstream version 4.7.0
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Mon Dec 15 13:37:28 GMT 2025
Bas Couwenberg pushed to branch upstream at Debian GIS Project / pywps
Commits:
35a8a6bd by Bas Couwenberg at 2025-12-15T13:00:30+01:00
New upstream version 4.7.0
- - - - -
23 changed files:
- .github/workflows/main.yml
- + .readthedocs.yml
- − INSTALL.md
- + Makefile
- README.md
- VERSION.txt
- debian/changelog
- 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,3 +1,16 @@
+pywps (4.7.0) trusty; urgency=medium
+
+ * Skipped support for Python 3.8 and 3.9.
+ * Added support for Python 3.12 and 3.13.
+ * Security upgrade of numpy (#695) and urllib (#693).
+ * Added conda support (#696).
+ * Fixed linting (#694).
+ * Reconfigure CI and documentation (#692).
+ * Improve the content of default-config.cfg (#691).
+ * Uniform tab/spaces in WPS templates (#690).
+
+ -- Carsten Ehbrecht <ehbrecht at dkrz.de> Mon, 15 Dec 2025 18:00:00 +0000
+
pywps (4.6.0) trusty; urgency=medium
* Skip support for Python 3.7
=====================================
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/-/commit/35a8a6bdd49dfad42cab02f973fcc0c535158d14
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/pywps/-/commit/35a8a6bdd49dfad42cab02f973fcc0c535158d14
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/b71d5604/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list