Skip to content

Commit c9ed573

Browse files
committed
OAProc: derive jobControlOptions and outputTransmission from plugin (#2257)
1 parent 3764b1a commit c9ed573

4 files changed

Lines changed: 150 additions & 6 deletions

File tree

docs/source/plugins.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ Below is a sample process definition as a Python dictionary:
410410
'it back as output. Intended to demonstrate a simple '
411411
'process with a single literal input.',
412412
'jobControlOptions': ['sync-execute', 'async-execute'], # whether the process can be executed in sync or async mode
413+
'outputTransmission': ['value', 'reference'], # whether the process can return inline data or URL references
413414
'keywords': ['hello world', 'example', 'echo'], # keywords associated with the process
414415
'links': [{ # a list of 1..n # link objects relevant to the process
415416
'type': 'text/html',

pygeoapi/api/processes.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,15 @@ def describe_processes(api: API, request: APIRequest,
130130
p2.pop('outputs')
131131
p2.pop('example', None)
132132

133-
p2['jobControlOptions'] = ['sync-execute']
134-
if api.manager.is_async:
133+
jco = p.metadata.get('jobControlOptions', ['sync-execute'])
134+
p2['jobControlOptions'] = jco
135+
136+
if api.manager.is_async and 'async-execute' not in jco:
137+
LOGGER.debug('Adding async capability')
135138
p2['jobControlOptions'].append('async-execute')
136139

137-
p2['outputTransmission'] = ['value']
140+
p2['outputTransmission'] = p.metadata.get(
141+
'outputTransmission', ['value'])
138142

139143
p2['links'] = p2.get('links', [])
140144

tests/api/test_processes.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,28 @@
3737
import time
3838
from unittest import mock
3939

40+
import pytest
41+
42+
from pygeoapi.api import API
4043
from pygeoapi.api.processes import (
4144
describe_processes, execute_process, delete_job, get_job_result, get_jobs
4245
)
4346
from pygeoapi.formats import FORMAT_TYPES, F_HTML, F_JSON
47+
from pygeoapi.util import yaml_load
48+
49+
from tests.util import get_test_file_path, mock_api_request
50+
4451

45-
from tests.util import mock_api_request
52+
@pytest.fixture()
53+
def config_process_metadata() -> dict:
54+
""" Returns a pygeoapi configuration with process metadata."""
55+
with open(get_test_file_path('pygeoapi-test-config-process-metadata.yml')) as fh: # noqa
56+
return yaml_load(fh)
57+
58+
59+
@pytest.fixture()
60+
def api_process_metadata(config_process_metadata, openapi):
61+
return API(config_process_metadata, openapi)
4662

4763

4864
def test_describe_processes(config, api_):
@@ -143,15 +159,32 @@ def test_describe_processes(config, api_):
143159

144160
# Test describe doesn't crash if example is missing
145161
req = mock_api_request()
146-
processor = api_.manager.get_processor("hello-world")
147-
example = processor.metadata.pop("example")
162+
processor = api_.manager.get_processor('hello-world')
163+
example = processor.metadata.pop('example')
148164
rsp_headers, code, response = describe_processes(api_, req)
149165
processor.metadata['example'] = example
150166
data = json.loads(response)
151167
assert code == HTTPStatus.OK
152168
assert len(data['processes']) == 2
153169

154170

171+
def test_describe_processes_metadata(config_process_metadata,
172+
api_process_metadata):
173+
174+
req = mock_api_request({'limit': 1})
175+
# Test for description of single processes
176+
rsp_headers, code, response = describe_processes(
177+
api_process_metadata, req, 'echo')
178+
data = json.loads(response)
179+
assert code == HTTPStatus.OK
180+
assert len(data['jobControlOptions']) == 2
181+
assert 'sync-execute' in data['jobControlOptions']
182+
assert 'async-execute' in data['jobControlOptions']
183+
assert len(data['outputTransmission']) == 2
184+
assert 'value' in data['outputTransmission']
185+
assert 'reference' in data['outputTransmission']
186+
187+
155188
def test_execute_process(config, api_):
156189
req_body_0 = {
157190
'inputs': {
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# =================================================================
2+
#
3+
# Authors: Tom Kralidis <tomkralidis@gmail.com>
4+
#
5+
# Copyright (c) 2026 Tom Kralidis
6+
#
7+
# Permission is hereby granted, free of charge, to any person
8+
# obtaining a copy of this software and associated documentation
9+
# files (the "Software"), to deal in the Software without
10+
# restriction, including without limitation the rights to use,
11+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
# copies of the Software, and to permit persons to whom the
13+
# Software is furnished to do so, subject to the following
14+
# conditions:
15+
#
16+
# The above copyright notice and this permission notice shall be
17+
# included in all copies or substantial portions of the Software.
18+
#
19+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26+
# OTHER DEALINGS IN THE SOFTWARE.
27+
#
28+
# =================================================================
29+
30+
server:
31+
bind:
32+
host: 0.0.0.0
33+
port: 5000
34+
url: http://localhost:5000/
35+
mimetype: application/json; charset=UTF-8
36+
encoding: utf-8
37+
gzip: false
38+
languages:
39+
# First language is the default language
40+
- en-US
41+
- fr-CA
42+
cors: true
43+
pretty_print: true
44+
limits:
45+
default_items: 10
46+
max_items: 10
47+
# templates: /path/to/templates
48+
map:
49+
url: https://tile.openstreetmap.org/{z}/{x}/{y}.png
50+
attribution: '&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
51+
manager:
52+
name: TinyDB
53+
connection: /tmp/pygeoapi-test-process-manager.db
54+
output_dir: /tmp
55+
56+
logging:
57+
level: DEBUG
58+
#logfile: /tmp/pygeoapi.log
59+
60+
metadata:
61+
identification:
62+
title:
63+
en: pygeoapi default instance
64+
fr: instance par défaut de pygeoapi
65+
description:
66+
en: pygeoapi provides an API to geospatial data
67+
fr: pygeoapi fournit une API aux données géospatiales
68+
keywords:
69+
en:
70+
- geospatial
71+
- data
72+
- api
73+
fr:
74+
- géospatiale
75+
- données
76+
- api
77+
keywords_type: theme
78+
terms_of_service: https://creativecommons.org/licenses/by/4.0/
79+
url: http://example.org
80+
license:
81+
name: CC-BY 4.0 license
82+
url: https://creativecommons.org/licenses/by/4.0/
83+
provider:
84+
name: Organization Name
85+
url: https://pygeoapi.io
86+
contact:
87+
name: Lastname, Firstname
88+
position: Position Title
89+
address: Mailing Address
90+
city: City
91+
stateorprovince: Administrative Area
92+
postalcode: Zip or Postal Code
93+
country: Country
94+
phone: +xx-xxx-xxx-xxxx
95+
fax: +xx-xxx-xxx-xxxx
96+
email: you@example.org
97+
url: Contact URL
98+
hours: Hours of Service
99+
instructions: During hours of service. Off on weekends.
100+
role: pointOfContact
101+
102+
resources:
103+
echo:
104+
type: process
105+
processor:
106+
name: Echo

0 commit comments

Comments
 (0)