diff --git a/.readthedocs.yml b/.readthedocs.yml
index 317d25e57..efc2f6e88 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -10,7 +10,7 @@ formats:
- epub
build:
- os: ubuntu-22.04
+ os: "ubuntu-24.04"
tools:
python: "3.11" # Use standard CPython version; `mambaforge-22.9` is not valid here
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index be0c2d9b5..83e275616 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -150,7 +150,7 @@ for stable releases and managed exclusively by the PyWPS team.
# clone the repository locally
$ git clone git@github.com:USERNAME/pywps.git
$ cd pywps
- $ pip install -e . && pip install -r requirements.txt
+ $ pip install -e .
# add the main PyWPS development branch to keep up to date with upstream changes
$ git remote add upstream https://github.com/geopython/pywps.git
diff --git a/README.md b/README.md
index a035da75e..41df0b028 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ As of PyWPS 4.0.0, PyWPS is released under an
## Dependencies
-See [requirements.txt](requirements.txt) file
+See [pyproject.toml](pyproject.toml) file
## Install
@@ -34,11 +34,11 @@ $ pip install .
## Run tests
```bash
-pip install -r requirements-dev.txt
+pip install ".[dev]"
# run unit tests
python -m pytest tests
# run code coverage
-python -m coverage run --source=pywps -m unittest tests
+python -m coverage run --source=pywps -m pytest
python -m coverage report -m
```
diff --git a/docs/conf.py b/docs/conf.py
index a4becd261..59668a73e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -81,9 +81,6 @@ def __getattr__(cls, name):
MOCK_MODULES = ['lxml', 'lxml.etree', 'lxml.builder']
-# with open('../requirements.txt') as f:
-# MOCK_MODULES = f.read().splitlines()
-
for mod_name in MOCK_MODULES:
sys.modules[mod_name] = Mock()
diff --git a/docs/extensions.rst b/docs/extensions.rst
index 84446726f..d96fab2a0 100644
--- a/docs/extensions.rst
+++ b/docs/extensions.rst
@@ -40,7 +40,7 @@ The scheduler extension uses the `DRMAA`_
library to talk to the different scheduler systems. Install the additional
Python dependencies using pip::
- $ pip install -r requirements-processing.txt # drmaa
+ $ pip install ".[processing]" # drmaa
If you are using the `conda `_ package manager you can
install the dependencies with::
@@ -95,7 +95,6 @@ Slurm.
Docker Container Extension
---------------------------
-
.. todo:: This extension is on our wish list. In can be used to encapsulate
and control the execution of a process. It enhances also the use case of
Web Processing Services in a cloud computing infrastructure.
diff --git a/docs/install.rst b/docs/install.rst
index 421e2d660..b51c7cb6a 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -12,7 +12,7 @@ Installation
Dependencies and requirements
-----------------------------
-PyWPS runs on Python 3.7 or higher. PyWPS is currently tested and developed on Linux (mostly Ubuntu).
+PyWPS runs on Python 3.10 or higher. PyWPS is currently tested and developed on Linux (mostly Ubuntu).
In the documentation we take this distribution as reference.
Prior to installing PyWPS, Git and the Python bindings for GDAL must be
@@ -61,15 +61,9 @@ Manual installation
$ tar zxf pywps-x.y.z.tar.gz
$ cd pywps-x.y.z/
- Then install the package dependencies using pip::
+ To install PyWPS system-wide with all dependencies run::
- $ pip install -r requirements.txt
- $ pip install -r requirements-gdal.txt # for GDAL Python bindings (if python-gdal is not already installed by `apt-get`)
- $ pip install -r requirements-dev.txt # for developer tasks
-
- To install PyWPS system-wide run::
-
- $ sudo pip install .
+ $ sudo pip install ".[dev,extra] # for developer tasks and GDAL Python bindings (if python-gdal is not already installed by `apt-get`)
For Developers
Installation of the source code using Git and Python's virtualenv tool::
diff --git a/pyproject.toml b/pyproject.toml
index 69c40b3e8..cf96b962b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,11 +1,124 @@
[build-system]
-requires = ["setuptools"]
+requires = ["setuptools>=80", "wheel"]
build-backend = "setuptools.build_meta"
+[project]
+name = "pywps"
+description = "PyWPS is an implementation of the Web Processing Service standard from the Open Geospatial Consortium. PyWPS is written in Python."
+readme = { file = "README.md", content-type = "text/markdown" }
+license = { text = "MIT" }
+authors = [
+ { name = "Jachym Cepicky", email = "jachym.cepicky@gmail.com" }
+]
+maintainers = [
+ { name = "Jachym Cepicky", email = "jachym.cepicky@gmail.com" }
+]
+keywords = ["PyWPS", "WPS", "OGC", "processing"]
+requires-python = ">=3.10"
+dynamic = ["version"]
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "Intended Audience :: Science/Research",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Topic :: Scientific/Engineering :: GIS",
+]
+urls = {Homepage = "https://pywps.org", Repository = "https://github.com/geopython/pywps"}
+dependencies = [
+ "humanize >=4.5.0",
+ "jinja2 >=3.1.0",
+ "jsonschema >=4.20.0",
+ "lxml >=6.0.2",
+ "markupsafe >=3.0.3",
+ "numpy >=1.22.2", # not directly required, pinned by Snyk to avoid a vulnerability
+ "owslib >=0.35.0",
+ "python-dateutil",
+ "requests >=2.32.5",
+ "sqlalchemy >=2.0.44",
+ "urllib3 >=2.5.0", # not directly required, pinned by Snyk to avoid a vulnerability
+ "werkzeug >=3.1.4",
+]
+
+[project.optional-dependencies]
+dev = [
+ "bump-my-version",
+ "coverage",
+ "docutils",
+ "pylint",
+ "pytest",
+ "pytest-cov",
+ "ruff >=0.14.0",
+ "sphinx",
+ "tox >=4.30.3",
+ "twine",
+ "wheel"
+]
+extra = [
+ "fiona",
+ "geotiff",
+ "netCDF4",
+ "tifffile <=2025.5.10",
+ "zarr <3.0"]
+processing = ["drmaa"]
+s3 = ["boto3"]
+
+[project.scripts]
+joblauncher = "pywps.processing.job:launcher"
+
+[tool.bumpversion]
+current_version = "4.7.0"
+commit = false
+tag = false
+parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)"
+serialize = ["{major}.{minor}.{patch}"]
+
+[[tool.bumpversion.files]]
+filename = "pywps/__init__.py"
+search = '__version__ = "{current_version}"'
+replace = '__version__ = "{new_version}"'
+
+[[tool.bumpversion.files]]
+filename = "VERSION.txt"
+search = "{current_version}"
+replace = "{new_version}"
+
+[tool.coverage.run]
+relative_files = true
+
+[tool.pytest.ini_options]
+addopts = [
+ "--import-mode=importlib",
+]
+xfail_strict = true
+pythonpath = ["tests"]
+testpaths = ["tests"]
+markers = [
+ "online: marks tests requiring network",
+ "requires_fiona: marks tests requiring fiona module",
+ "requires_geotiff: marks tests requiring geotiff module",
+ "requires_netcdf4: marks tests requiring netcdf4 module",
+]
+
+[tool.setuptools]
+include-package-data = true
+
+[tool.setuptools.packages.find]
+exclude = ["docs", "tests", "tests.*"]
+
+[tool.setuptools.dynamic]
+version = { file = ["VERSION.txt"] }
+
[tool.ruff]
lint.select = ["E", "W", "F", "C90"] # Flake8-equivalent rule families
lint.ignore = ["F401", "E402", "C901"]
-
line-length = 120
exclude = ["tests"]
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index 17d18719a..000000000
--- a/pytest.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[pytest]
-addopts =
- --import-mode=importlib
-xfail_strict = true
-pythonpath = tests
-testpaths = tests
-markers =
- online: marks tests requiring network
- requires_fiona: marks tests requiring fiona module
- requires_geotiff: marks tests requiring geotiff module
- requires_netcdf4: marks tests requiring netcdf4 module
diff --git a/requirements-dev.txt b/requirements-dev.txt
deleted file mode 100644
index f317af4ca..000000000
--- a/requirements-dev.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-bump2version
-coverage
-docutils
-pylint
-pytest
-pytest-cov
-ruff>=0.14.0
-sphinx
-tox>=4.30.3
-twine
-wheel
diff --git a/requirements-extra.txt b/requirements-extra.txt
deleted file mode 100644
index 354c54ea4..000000000
--- a/requirements-extra.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-fiona
-geotiff
-netCDF4
-tifffile<=2025.5.10
-zarr<3.0
diff --git a/requirements-processing.txt b/requirements-processing.txt
deleted file mode 100644
index 91ffcad8d..000000000
--- a/requirements-processing.txt
+++ /dev/null
@@ -1 +0,0 @@
-drmaa
diff --git a/requirements-s3.txt b/requirements-s3.txt
deleted file mode 100644
index 1db657b6b..000000000
--- a/requirements-s3.txt
+++ /dev/null
@@ -1 +0,0 @@
-boto3
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 0044eb055..000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-humanize>=4.5.0
-jinja2>=3.1.0
-jsonschema>=4.20.0
-lxml>=6.0.2
-markupsafe>=3.0.3
-numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability
-owslib>=0.35.0
-python-dateutil
-requests>=2.32.5
-sqlalchemy>=2.0.44
-urllib3>=2.5.0 # not directly required, pinned by Snyk to avoid a vulnerability
-werkzeug>=3.1.4
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 96b6f1ed8..000000000
--- a/setup.cfg
+++ /dev/null
@@ -1,18 +0,0 @@
-[bumpversion]
-current_version = 4.7.0
-commit = False
-tag = False
-parse = (?P\d+)\.(?P\d+).(?P\d+)
-serialize =
- {major}.{minor}.{patch}
-
-[bumpversion:file:pywps/__init__.py]
-search = __version__ = "{current_version}"
-replace = __version__ = "{new_version}"
-
-[bumpversion:file:VERSION.txt]
-search = {current_version}
-replace = {new_version}
-
-[coverage:run]
-relative_files = True
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 7a2535b00..000000000
--- a/setup.py
+++ /dev/null
@@ -1,85 +0,0 @@
-##################################################################
-# Copyright 2018 Open Source Geospatial Foundation and others #
-# licensed under MIT, Please consult LICENSE.txt for details #
-##################################################################
-
-from setuptools import find_packages, setup
-
-with open("VERSION.txt") as ff:
- VERSION = ff.read().strip()
-
-DESCRIPTION = (
- "PyWPS is an implementation of the Web Processing Service "
- "standard from the Open Geospatial Consortium. PyWPS is "
- "written in Python."
-)
-
-with open("README.md") as ff:
- LONG_DESCRIPTION = ff.read()
-
-KEYWORDS = "PyWPS WPS OGC processing"
-
-with open("requirements.txt") as fr:
- INSTALL_REQUIRES = fr.read().splitlines()
-
-with open("requirements-dev.txt") as frd:
- DEV_REQUIRES = frd.read().splitlines()
-
-with open("requirements-extra.txt") as frd:
- EXTRA_REQUIRES = frd.read().splitlines()
-
-with open("requirements-processing.txt") as frd:
- PROCESSING_REQUIRES = frd.read().splitlines()
-
-with open("requirements-s3.txt") as frd:
- S3_REQUIRES = frd.read().splitlines()
-
-CONFIG = {
- "name": "pywps",
- "version": VERSION,
- "description": DESCRIPTION,
- "long_description": LONG_DESCRIPTION,
- "long_description_content_type": "text/markdown",
- "keywords": KEYWORDS,
- "license": "MIT",
- "platforms": "all",
- "author": "Jachym Cepicky",
- "author_email": "jachym.cepicky@gmail.com",
- "maintainer": "Jachym Cepicky",
- "maintainer_email": "jachym.cepicky@gmail.com",
- "url": "https://pywps.org",
- "download_url": "https://github.com/geopython/pywps",
- "classifiers": [
- "Development Status :: 5 - Production/Stable",
- "Environment :: Web Environment",
- "Intended Audience :: Developers",
- "Intended Audience :: Science/Research",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- "Programming Language :: Python",
- "Programming Language :: Python :: 3",
- "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,
- extra=EXTRA_REQUIRES,
- processing=PROCESSING_REQUIRES,
- s3=S3_REQUIRES
- ),
- "python_requires": ">=3.10,<4",
- "packages": find_packages(exclude=["docs", "tests.*", "tests"]),
- "include_package_data": True,
- "scripts": [],
- "entry_points": {
- "console_scripts": [
- "joblauncher=pywps.processing.job:launcher",
- ]
- },
-}
-
-setup(**CONFIG)