• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geopython / pywps / 6720056456

01 Nov 2023 01:06PM UTC coverage: 84.061% (+2.7%) from 81.332%
6720056456

push

github

web-flow
fix tests (#687)



* skip py37

5374 of 6393 relevant lines covered (84.06%)

0.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.15
/tests/test_execute.py
1
##################################################################
2
# Copyright 2018 Open Source Geospatial Foundation and others    #
3
# licensed under MIT, Please consult LICENSE.txt for details     #
4
##################################################################
5

6
from basic import TestBase
1✔
7
import pytest
1✔
8
from pywps import xml_util as etree
1✔
9
import json
1✔
10

11
import os.path
1✔
12
from pywps import Service, Process, LiteralOutput, LiteralInput,\
1✔
13
    BoundingBoxOutput, BoundingBoxInput, Format, ComplexInput, ComplexOutput, FORMATS
14
from pywps.validator.base import emptyvalidator
1✔
15
from pywps.validator.complexvalidator import validategml
1✔
16
from pywps.exceptions import InvalidParameterValue
1✔
17
from pywps import get_inputs_from_xml
1✔
18
from pywps import E, get_ElementMakerForVersion
1✔
19
from pywps.app.basic import get_xpath_ns
1✔
20
from pywps.tests import client_for, assert_response_success, assert_response_success_json
1✔
21
from pywps import configuration
1✔
22

23
from io import StringIO
1✔
24

25
try:
1✔
26
    import netCDF4
1✔
27
except ImportError:
×
28
    WITH_NC4 = False
×
29
else:
30
    WITH_NC4 = True
1✔
31

32
DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data')
1✔
33

34
VERSION = "1.0.0"
1✔
35

36
WPS, OWS = get_ElementMakerForVersion(VERSION)
1✔
37

38
xpath_ns = get_xpath_ns(VERSION)
1✔
39

40

41
def create_ultimate_question():
1✔
42
    def handler(request, response):
1✔
43
        response.outputs['outvalue'].data = '42'
1✔
44
        return response
1✔
45

46
    return Process(handler=handler,
1✔
47
                   identifier='ultimate_question',
48
                   title='Ultimate Question',
49
                   outputs=[LiteralOutput('outvalue', 'Output Value', data_type='string')])
50

51

52
def create_greeter():
1✔
53
    def greeter(request, response):
1✔
54
        name = request.inputs['name'][0].data
1✔
55
        assert isinstance(name, str)
1✔
56
        response.outputs['message'].data = "Hello {}!".format(name)
1✔
57
        return response
1✔
58

59
    return Process(handler=greeter,
1✔
60
                   identifier='greeter',
61
                   title='Greeter',
62
                   inputs=[LiteralInput('name', 'Input name', data_type='string')],
63
                   outputs=[LiteralOutput('message', 'Output message', data_type='string')])
64

65

66
def create_translated_greeter():
1✔
67
    def greeter(request, response):
1✔
68
        name = request.inputs['name'][0].data
1✔
69
        response.outputs['message'].data = "Hello {}!".format(name)
1✔
70
        return response
1✔
71

72
    return Process(
1✔
73
        handler=greeter,
74
        identifier='greeter',
75
        title='Greeter',
76
        abstract='Say hello',
77
        inputs=[
78
            LiteralInput(
79
                'name',
80
                'Input name',
81
                data_type='string',
82
                abstract='Input description',
83
                translations={"fr-CA": {"title": "Nom", "abstract": "Description"}},
84
            )
85
        ],
86
        outputs=[
87
            LiteralOutput(
88
                'message',
89
                'Output message',
90
                data_type='string',
91
                abstract='Output description',
92
                translations={"fr-CA": {"title": "Message de retour", "abstract": "Description"}},
93
            )
94
        ],
95
        translations={"fr-CA": {"title": "Salutations", "abstract": "Dire allô"}},
96
    )
97

98

99
def create_bbox_process():
1✔
100
    def bbox_process(request, response):
1✔
101
        coords = request.inputs['mybbox'][0].data
1✔
102
        assert isinstance(coords, list)
1✔
103
        assert len(coords) == 4
1✔
104
        assert coords[0] == 15.0
1✔
105
        response.outputs['outbbox'].data = coords
1✔
106
        return response
1✔
107

108
    return Process(handler=bbox_process,
1✔
109
                   identifier='my_bbox_process',
110
                   title='Bbox process',
111
                   inputs=[BoundingBoxInput('mybbox', 'Input name', ["EPSG:4326"])],
112
                   outputs=[BoundingBoxOutput('outbbox', 'Output message', ["EPSG:4326"])])
113

114

115
def create_complex_proces(mime_type: str = 'gml'):
1✔
116
    def complex_proces(request, response):
1✔
117
        response.outputs['complex'].data = request.inputs['complex'][0].data_as_json()
1✔
118
        return response
1✔
119

120
    if mime_type == 'gml':
1✔
121
        frmt = Format(mime_type='application/gml', extension=".gml")  # this is unknown mimetype
1✔
122
    elif mime_type == 'geojson':
1✔
123
        frmt = FORMATS.GEOJSON
1✔
124
    else:
125
        raise Exception(f'Unknown mime type {mime_type}')
×
126

127
    return Process(handler=complex_proces,
1✔
128
                   identifier='my_complex_process',
129
                   title='Complex process',
130
                   inputs=[
131
                       ComplexInput(
132
                           'complex',
133
                           'Complex input',
134
                           min_occurs=0,
135
                           default="DEFAULT COMPLEX DATA",
136
                           supported_formats=[frmt])
137
                   ],
138
                   outputs=[
139
                       ComplexOutput(
140
                           'complex',
141
                           'Complex output',
142
                           supported_formats=[frmt])
143
                   ])
144

145

146
def create_complex_nc_process():
1✔
147
    def complex_proces(request, response):
1✔
148
        from pywps.dependencies import netCDF4 as nc
1✔
149
        url = request.inputs['dods'][0].url
1✔
150
        with nc.Dataset(url) as D:
1✔
151
            response.outputs['conventions'].data = D.Conventions
1✔
152

153
        response.outputs['outdods'].url = url
1✔
154
        response.outputs['ncraw'].file = os.path.join(DATA_DIR, 'netcdf', 'time.nc')
1✔
155
        response.outputs['ncraw'].data_format = FORMATS.NETCDF
1✔
156
        return response
1✔
157

158
    return Process(handler=complex_proces,
1✔
159
                   identifier='my_opendap_process',
160
                   title='Opendap process',
161
                   inputs=[
162
                       ComplexInput(
163
                           'dods',
164
                           'Opendap input',
165
                           supported_formats=[Format('DODS'), Format('NETCDF')],
166
                           #   mode=MODE.STRICT
167
                       )
168
                   ],
169
                   outputs=[
170
                       LiteralOutput(
171
                           'conventions',
172
                           'NetCDF convention',
173
                       ),
174
                       ComplexOutput('outdods', 'Opendap output',
175
                                     supported_formats=[FORMATS.DODS, ],
176
                                     as_reference=True),
177
                       ComplexOutput('ncraw', 'NetCDF raw data output',
178
                                     supported_formats=[FORMATS.NETCDF, ],
179
                                     as_reference=False)
180
                   ])
181

182

183
def create_mimetype_process():
1✔
184
    def _handler(request, response):
1✔
185
        response.outputs['mimetype'].data = response.outputs['mimetype'].data_format.mime_type
1✔
186
        return response
1✔
187

188
    frmt_txt = Format(mime_type='text/plain')
1✔
189
    frmt_txt2 = Format(mime_type='text/plain+test')
1✔
190

191
    return Process(handler=_handler,
1✔
192
                   identifier='get_mimetype_process',
193
                   title='Get mimeType process',
194
                   inputs=[],
195
                   outputs=[
196
                       ComplexOutput(
197
                           'mimetype',
198
                           'mimetype of requested output',
199
                           supported_formats=[frmt_txt, frmt_txt2])
200
                   ])
201

202

203
def create_metalink_process():
1✔
204
    from processes.metalinkprocess import MultipleOutputs
1✔
205
    return MultipleOutputs()
1✔
206

207

208
def get_output(doc):
1✔
209
    """Return the content of LiteralData, Reference or ComplexData."""
210

211
    output = {}
1✔
212
    for output_el in xpath_ns(doc, '/wps:ExecuteResponse'
1✔
213
                                   '/wps:ProcessOutputs/wps:Output'):
214
        [identifier_el] = xpath_ns(output_el, './ows:Identifier')
1✔
215

216
        lit_el = xpath_ns(output_el, './wps:Data/wps:LiteralData')
1✔
217
        if lit_el != []:
1✔
218
            output[identifier_el.text] = lit_el[0].text
1✔
219

220
        ref_el = xpath_ns(output_el, './wps:Reference')
1✔
221
        if ref_el != []:
1✔
222
            output[identifier_el.text] = ref_el[0].attrib['href']
×
223

224
        data_el = xpath_ns(output_el, './wps:Data/wps:ComplexData')
1✔
225
        if data_el != []:
1✔
226
            if data_el[0].text:
×
227
                output[identifier_el.text] = data_el[0].text
×
228
            else:  # XML children
229
                ch = list(data_el[0])[0]
×
230
                output[identifier_el.text] = etree.tostring(ch)
×
231

232
    return output
1✔
233

234

235
class ExecuteTest(TestBase):
1✔
236
    """Test for Exeucte request KVP request"""
237

238
    @pytest.mark.xfail(reason="test.opendap.org is offline")
1✔
239
    def test_dods(self):
1✔
240
        if not WITH_NC4:
1✔
241
            self.skipTest('netCDF4 not installed')
×
242
        my_process = create_complex_nc_process()
1✔
243
        service = Service(processes=[my_process])
1✔
244

245
        href = "http://test.opendap.org:80/opendap/netcdf/examples/sresa1b_ncar_ccsm3_0_run1_200001.nc"
1✔
246

247
        """ # Is this how the request should be written ?
×
248
        request_doc = WPS.Execute(
249
            OWS.Identifier('my_opendap_process'),
250
            WPS.DataInputs(
251
                WPS.Input(
252
                    OWS.Identifier('dods'),
253
                    WPS.Reference(
254
                        WPS.Body('request body'),
255
                        {'{http://www.w3.org/1999/xlink}href': href},
256
                        method='POST'
257
                    )
258
                    #WPS.Data(WPS.ComplexData(href=href, mime_type='application/x-ogc-dods'))
259
                    # This form is not supported yet. Should it be ?
260
                )
261
            ),
262
            version='1.0.0'
263
        )
264
        resp = client.post_xml(doc=request_doc)
265
        assert_response_success(resp)
266
        """
267

268
        class FakeRequest():
1✔
269
            identifier = 'my_opendap_process'
1✔
270
            service = 'wps'
1✔
271
            operation = 'execute'
1✔
272
            version = '1.0.0'
1✔
273
            raw = True,
1✔
274
            inputs = {'dods': [{
1✔
275
                'identifier': 'dods',
276
                'href': href,
277
            }]}
278
            store_execute = False
1✔
279
            lineage = False
1✔
280
            outputs = ['conventions']
1✔
281
            language = "en-US"
1✔
282

283
        request = FakeRequest()
1✔
284

285
        resp = service.execute('my_opendap_process', request, 'fakeuuid')
1✔
286
        self.assertEqual(resp.outputs['conventions'].data, 'CF-1.0')
1✔
287
        self.assertEqual(resp.outputs['outdods'].url, href)
1✔
288
        self.assertTrue(resp.outputs['outdods'].as_reference)
1✔
289
        self.assertFalse(resp.outputs['ncraw'].as_reference)
1✔
290
        with open(os.path.join(DATA_DIR, 'netcdf', 'time.nc'), 'rb') as f:
1✔
291
            data = f.read()
1✔
292
        self.assertEqual(resp.outputs['ncraw'].data, data)
1✔
293

294
    def test_input_parser(self):
1✔
295
        """Test input parsing
296
        """
297
        my_process = create_complex_proces()
1✔
298
        service = Service(processes=[my_process])
1✔
299
        self.assertEqual(len(service.processes), 1)
1✔
300
        self.assertTrue(service.processes['my_complex_process'])
1✔
301

302
        class FakeRequest():
1✔
303
            identifier = 'complex_process'
1✔
304
            service = 'wps'
1✔
305
            operation = 'execute'
1✔
306
            version = '1.0.0'
1✔
307
            inputs = {'complex': [{
1✔
308
                'identifier': 'complex',
309
                'mimeType': 'text/gml',
310
                'data': 'the data'
311
            }]}
312
            language = "en-US"
1✔
313

314
        request = FakeRequest()
1✔
315

316
        try:
1✔
317
            service.execute('my_complex_process', request, 'fakeuuid')
1✔
318
        except InvalidParameterValue as e:
1✔
319
            self.assertEqual(e.locator, 'mimeType')
1✔
320

321
        request.inputs['complex'][0]['mimeType'] = 'application/gml'
1✔
322
        parsed_inputs = service.create_complex_inputs(my_process.inputs[0],
1✔
323
                                                      request.inputs['complex'])
324

325
        # TODO parse outputs and their validators too
326

327
        self.assertEqual(parsed_inputs[0].data_format.validate, emptyvalidator)
1✔
328

329
        request.inputs['complex'][0]['mimeType'] = 'application/xml+gml'
1✔
330
        try:
1✔
331
            parsed_inputs = service.create_complex_inputs(my_process.inputs[0],
1✔
332
                                                          request.inputs['complex'])
333
        except InvalidParameterValue as e:
1✔
334
            self.assertEqual(e.locator, 'mimeType')
1✔
335

336
        try:
1✔
337
            my_process.inputs[0].data_format = Format(mime_type='application/xml+gml')
1✔
338
        except InvalidParameterValue as e:
1✔
339
            self.assertEqual(e.locator, 'mimeType')
1✔
340

341
        frmt = Format(mime_type='application/xml+gml', validate=validategml)
1✔
342
        self.assertEqual(frmt.validate, validategml)
1✔
343

344
        my_process.inputs[0].supported_formats = [frmt]
1✔
345
        my_process.inputs[0].data_format = Format(mime_type='application/xml+gml')
1✔
346
        parsed_inputs = service.create_complex_inputs(my_process.inputs[0],
1✔
347
                                                      request.inputs['complex'])
348

349
        self.assertEqual(parsed_inputs[0].data_format.validate, validategml)
1✔
350

351
    def test_input_default(self):
1✔
352
        """Test input parsing
353
        """
354
        my_process = create_complex_proces()
1✔
355
        service = Service(processes=[my_process])
1✔
356
        self.assertEqual(len(service.processes), 1)
1✔
357
        self.assertTrue(service.processes['my_complex_process'])
1✔
358

359
        class FakeRequest():
1✔
360
            identifier = 'complex_process'
1✔
361
            service = 'wps'
1✔
362
            operation = 'execute'
1✔
363
            version = '1.0.0'
1✔
364
            inputs = {}
1✔
365
            raw = False
1✔
366
            outputs = {}
1✔
367
            store_execute = False
1✔
368
            lineage = False
1✔
369
            language = "en-US"
1✔
370

371
        request = FakeRequest()
1✔
372
        response = service.execute('my_complex_process', request, 'fakeuuid')
1✔
373
        self.assertEqual(response.outputs['complex'].data, 'DEFAULT COMPLEX DATA')
1✔
374

375
    def test_output_mimetype(self):
1✔
376
        """Test input parsing
377
        """
378
        my_process = create_mimetype_process()
1✔
379
        service = Service(processes=[my_process])
1✔
380
        self.assertEqual(len(service.processes), 1)
1✔
381
        self.assertTrue(service.processes['get_mimetype_process'])
1✔
382

383
        class FakeRequest():
1✔
384
            def __init__(self, mimetype):
1✔
385
                self.outputs = {'mimetype': {
1✔
386
                    'identifier': 'mimetype',
387
                    'mimetype': mimetype,
388
                    'data': 'the data'
389
                }}
390

391
            identifier = 'get_mimetype_process'
1✔
392
            service = 'wps'
1✔
393
            operation = 'execute'
1✔
394
            version = '1.0.0'
1✔
395
            inputs = {}
1✔
396
            raw = False
1✔
397
            store_execute = False
1✔
398
            lineage = False
1✔
399
            language = "en-US"
1✔
400

401
        # valid mimetype
402
        request = FakeRequest('text/plain+test')
1✔
403
        response = service.execute('get_mimetype_process', request, 'fakeuuid')
1✔
404
        self.assertEqual(response.outputs['mimetype'].data, 'text/plain+test')
1✔
405

406
        # non valid mimetype
407
        request = FakeRequest('text/xml')
1✔
408
        with self.assertRaises(InvalidParameterValue):
1✔
409
            response = service.execute('get_mimetype_process', request, 'fakeuuid')
1✔
410

411
    def test_metalink(self):
1✔
412
        client = client_for(Service(processes=[create_metalink_process()]))
1✔
413
        resp = client.get('?Request=Execute&identifier=multiple-outputs')
1✔
414
        assert resp.status_code == 400
1✔
415

416
    def test_missing_process_error(self):
1✔
417
        client = client_for(Service(processes=[create_ultimate_question()]))
1✔
418
        resp = client.get('?Request=Execute&identifier=foo')
1✔
419
        assert resp.status_code == 400
1✔
420

421
    def test_get_with_no_inputs(self):
1✔
422
        client = client_for(Service(processes=[create_ultimate_question()]))
1✔
423
        resp = client.get('?service=wps&version=1.0.0&Request=Execute&identifier=ultimate_question')
1✔
424
        assert_response_success(resp)
1✔
425

426
        assert get_output(resp.xml) == {'outvalue': '42'}
1✔
427

428
    def test_post_with_no_inputs(self):
1✔
429
        request = {
1✔
430
            'identifier': 'ultimate_question',
431
            'version': '1.0.0'
432
        }
433
        result = {'outvalue': '42'}
1✔
434

435
        client = client_for(Service(processes=[create_ultimate_question()]))
1✔
436
        request_doc = WPS.Execute(
1✔
437
            OWS.Identifier(request['identifier']),
438
            version=request['version']
439
        )
440

441
        resp = client.post_xml(doc=request_doc)
1✔
442
        assert_response_success(resp)
1✔
443
        assert get_output(resp.xml) == result
1✔
444

445
        resp = client.post_json(doc=request)
1✔
446
        assert_response_success_json(resp, result)
1✔
447

448
    def test_post_with_string_input(self):
1✔
449
        request = {
1✔
450
            'identifier': 'greeter',
451
            'version': '1.0.0',
452
            'inputs': {
453
                'name': 'foo'
454
            },
455
        }
456
        result = {'message': "Hello foo!"}
1✔
457

458
        client = client_for(Service(processes=[create_greeter()]))
1✔
459
        request_doc = WPS.Execute(
1✔
460
            OWS.Identifier(request['identifier']),
461
            WPS.DataInputs(
462
                WPS.Input(
463
                    OWS.Identifier('name'),
464
                    WPS.Data(WPS.LiteralData(request['inputs']['name']))
465
                )
466
            ),
467
            version=request['version']
468
        )
469
        resp = client.post_xml(doc=request_doc)
1✔
470
        assert_response_success(resp)
1✔
471
        assert get_output(resp.xml) == result
1✔
472

473
        resp = client.post_json(doc=request)
1✔
474
        assert_response_success_json(resp, result)
1✔
475

476
    def test_bbox(self):
1✔
477
        client = client_for(Service(processes=[create_bbox_process()]))
1✔
478
        request_doc = WPS.Execute(
1✔
479
            OWS.Identifier('my_bbox_process'),
480
            WPS.DataInputs(
481
                WPS.Input(
482
                    OWS.Identifier('mybbox'),
483
                    WPS.Data(WPS.BoundingBoxData(
484
                        OWS.LowerCorner('15.0 50.0'),
485
                        OWS.UpperCorner('16.0 51.0'),
486
                    ))
487
                )
488
            ),
489
            version='1.0.0'
490
        )
491
        resp = client.post_xml(doc=request_doc)
1✔
492
        assert_response_success(resp)
1✔
493

494
        [output] = xpath_ns(resp.xml, '/wps:ExecuteResponse'
1✔
495
                                      '/wps:ProcessOutputs/wps:Output')
496
        self.assertEqual('outbbox', xpath_ns(
1✔
497
            output,
498
            './ows:Identifier')[0].text)
499

500
        lower_corner = xpath_ns(output, './wps:Data/wps:BoundingBoxData/ows:LowerCorner')[0].text
1✔
501
        lower_corner = lower_corner.strip().replace('  ', ' ')
1✔
502
        self.assertEqual('15.0 50.0', lower_corner)
1✔
503

504
        upper_corner = xpath_ns(output, './wps:Data/wps:BoundingBoxData/ows:UpperCorner')[0].text
1✔
505
        upper_corner = upper_corner.strip().replace('  ', ' ')
1✔
506
        self.assertEqual('16.0 51.0', upper_corner)
1✔
507

508
    def test_bbox_rest(self):
1✔
509
        client = client_for(Service(processes=[create_bbox_process()]))
1✔
510
        bbox = [15.0, 50.0, 16.0, 51.0]
1✔
511
        request = dict(
1✔
512
            identifier='my_bbox_process',
513
            version='1.0.0',
514
            inputs={
515
                'mybbox': {
516
                    "type": "bbox",
517
                    'bbox': bbox,
518
                }
519
            },
520
        )
521
        result = {'outbbox': bbox}
1✔
522

523
        resp = client.post_json(doc=request)
1✔
524
        assert_response_success_json(resp, result)
1✔
525

526
    def test_geojson_input_rest(self):
1✔
527
        geojson = os.path.join(DATA_DIR, 'json', 'point.geojson')
1✔
528
        with open(geojson) as f:
1✔
529
            p = json.load(f)
1✔
530

531
        my_process = create_complex_proces('geojson')
1✔
532
        client = client_for(Service(processes=[my_process]))
1✔
533

534
        request = dict(
1✔
535
            identifier='my_complex_process',
536
            version='1.0.0',
537
            inputs={
538
                'complex': {
539
                    "type": "complex",
540
                    'data': p
541
                }
542
            },
543
        )
544
        result = {'complex': p}
1✔
545

546
        resp = client.post_json(doc=request)
1✔
547
        assert_response_success_json(resp, result)
1✔
548

549
    def test_output_response_dataType(self):
1✔
550
        client = client_for(Service(processes=[create_greeter()]))
1✔
551
        request_doc = WPS.Execute(
1✔
552
            OWS.Identifier('greeter'),
553
            WPS.DataInputs(
554
                WPS.Input(
555
                    OWS.Identifier('name'),
556
                    WPS.Data(WPS.LiteralData('foo'))
557
                )
558
            ),
559
            version='1.0.0'
560
        )
561
        resp = client.post_xml(doc=request_doc)
1✔
562
        el = next(resp.xml.iter('{http://www.opengis.net/wps/1.0.0}LiteralData'))
1✔
563
        assert el.attrib['dataType'] == 'string'
1✔
564

565

566
class AllowedInputReferenceExecuteTest(TestBase):
1✔
567

568
    def setUp(self):
1✔
569
        super().setUp()
1✔
570
        self.allowedinputpaths = configuration.get_config_value('server', 'allowedinputpaths')
1✔
571
        configuration.CONFIG.set('server', 'allowedinputpaths', DATA_DIR)
1✔
572

573
    def test_geojson_input_reference_rest(self):
1✔
574
        geojson = os.path.join(DATA_DIR, 'json', 'point.geojson')
1✔
575
        with open(geojson) as f:
1✔
576
            p = json.load(f)
1✔
577

578
        my_process = create_complex_proces('geojson')
1✔
579
        client = client_for(Service(processes=[my_process]))
1✔
580

581
        request = dict(
1✔
582
            identifier='my_complex_process',
583
            version='1.0.0',
584
            inputs={
585
                'complex': {
586
                    "type": "reference",
587
                    "href": f"file:{geojson}"
588
                }
589
            },
590
        )
591
        result = {'complex': p}
1✔
592

593
        resp = client.post_json(doc=request)
1✔
594
        assert_response_success_json(resp, result)
1✔
595

596

597
class ExecuteTranslationsTest(TestBase):
1✔
598

599
    def setUp(self):
1✔
600
        super().setUp()
1✔
601
        configuration.get_config_value('server', 'language')
1✔
602
        configuration.CONFIG.set('server', 'language', 'en-US,fr-CA')
1✔
603

604
    def test_translations(self):
1✔
605
        client = client_for(Service(processes=[create_translated_greeter()]))
1✔
606

607
        request_doc = WPS.Execute(
1✔
608
            OWS.Identifier('greeter'),
609
            WPS.DataInputs(
610
                WPS.Input(
611
                    OWS.Identifier('name'),
612
                    WPS.Data(WPS.LiteralData('foo'))
613
                )
614
            ),
615
            WPS.ResponseForm(
616
                WPS.ResponseDocument(
617
                    lineage='true',
618
                )
619
            ),
620
            version='1.0.0',
621
            language='fr-CA',
622
        )
623
        resp = client.post_xml(doc=request_doc)
1✔
624

625
        assert resp.xpath('/wps:ExecuteResponse/@xml:lang')[0] == "fr-CA"
1✔
626

627
        process_title = [e.text for e in resp.xpath('//wps:Process/ows:Title')]
1✔
628
        assert process_title == ["Salutations"]
1✔
629
        process_abstract = [e.text for e in resp.xpath('//wps:Process/ows:Abstract')]
1✔
630
        assert process_abstract == ["Dire allô"]
1✔
631

632
        input_titles = [e.text for e in resp.xpath('//wps:Input/ows:Title')]
1✔
633
        assert input_titles == ["Nom"]
1✔
634
        input_abstract = [e.text for e in resp.xpath('//wps:Input/ows:Abstract')]
1✔
635
        assert input_abstract == ["Description"]
1✔
636

637
        output_titles = [e.text for e in resp.xpath('//wps:OutputDefinitions/wps:Output/ows:Title')]
1✔
638
        assert output_titles == ["Message de retour"]
1✔
639
        output_abstract = [e.text for e in resp.xpath('//wps:OutputDefinitions/wps:Output/ows:Abstract')]
1✔
640
        assert output_abstract == ["Description"]
1✔
641

642
        output_titles = [e.text for e in resp.xpath('//wps:ProcessOutputs/wps:Output/ows:Title')]
1✔
643
        assert output_titles == ["Message de retour"]
1✔
644
        output_abstract = [e.text for e in resp.xpath('//wps:ProcessOutputs/wps:Output/ows:Abstract')]
1✔
645
        assert output_abstract == ["Description"]
1✔
646

647

648
class ExecuteXmlParserTest(TestBase):
1✔
649
    """Tests for Execute request XML Parser
650
    """
651

652
    def test_empty(self):
1✔
653
        request_doc = WPS.Execute(OWS.Identifier('foo'))
1✔
654
        assert get_inputs_from_xml(request_doc) == {}
1✔
655

656
    def test_one_string(self):
1✔
657
        request_doc = WPS.Execute(
1✔
658
            OWS.Identifier('foo'),
659
            WPS.DataInputs(
660
                WPS.Input(
661
                    OWS.Identifier('name'),
662
                    WPS.Data(WPS.LiteralData('foo'))),
663
                WPS.Input(
664
                    OWS.Identifier('name'),
665
                    WPS.Data(WPS.LiteralData('bar')))
666
            ))
667
        rv = get_inputs_from_xml(request_doc)
1✔
668
        self.assertTrue('name' in rv)
1✔
669
        self.assertEqual(len(rv['name']), 2)
1✔
670
        self.assertEqual(rv['name'][0]['data'], 'foo')
1✔
671
        self.assertEqual(rv['name'][1]['data'], 'bar')
1✔
672

673
    def test_two_strings(self):
1✔
674
        request_doc = WPS.Execute(
1✔
675
            OWS.Identifier('foo'),
676
            WPS.DataInputs(
677
                WPS.Input(
678
                    OWS.Identifier('name1'),
679
                    WPS.Data(WPS.LiteralData('foo'))),
680
                WPS.Input(
681
                    OWS.Identifier('name2'),
682
                    WPS.Data(WPS.LiteralData('bar')))))
683
        rv = get_inputs_from_xml(request_doc)
1✔
684
        self.assertEqual(rv['name1'][0]['data'], 'foo')
1✔
685
        self.assertEqual(rv['name2'][0]['data'], 'bar')
1✔
686

687
    def test_complex_input(self):
1✔
688
        the_data = E.TheData("hello world")
1✔
689
        request_doc = WPS.Execute(
1✔
690
            OWS.Identifier('foo'),
691
            WPS.DataInputs(
692
                WPS.Input(
693
                    OWS.Identifier('name'),
694
                    WPS.Data(
695
                        WPS.ComplexData(the_data, mimeType='text/foobar')))))
696
        rv = get_inputs_from_xml(request_doc)
1✔
697
        self.assertEqual(rv['name'][0]['mimeType'], 'text/foobar')
1✔
698
        rv_doc = etree.parse(StringIO(rv['name'][0]['data'])).getroot()
1✔
699
        self.assertEqual(rv_doc.tag, 'TheData')
1✔
700
        self.assertEqual(rv_doc.text, 'hello world')
1✔
701

702
    def test_complex_input_raw_value(self):
1✔
703
        the_data = '{ "plot":{ "Version" : "0.1" } }'
1✔
704

705
        request_doc = WPS.Execute(
1✔
706
            OWS.Identifier('foo'),
707
            WPS.DataInputs(
708
                WPS.Input(
709
                    OWS.Identifier('json'),
710
                    WPS.Data(
711
                        WPS.ComplexData(the_data, mimeType='application/json')))))
712
        rv = get_inputs_from_xml(request_doc)
1✔
713
        self.assertEqual(rv['json'][0]['mimeType'], 'application/json')
1✔
714
        json_data = json.loads(rv['json'][0]['data'])
1✔
715
        self.assertEqual(json_data['plot']['Version'], '0.1')
1✔
716

717
    def test_complex_input_base64_value(self):
1✔
718
        the_data = 'eyAicGxvdCI6eyAiVmVyc2lvbiIgOiAiMC4xIiB9IH0='
1✔
719

720
        request_doc = WPS.Execute(
1✔
721
            OWS.Identifier('foo'),
722
            WPS.DataInputs(
723
                WPS.Input(
724
                    OWS.Identifier('json'),
725
                    WPS.Data(
726
                        WPS.ComplexData(the_data,
727
                                        encoding='base64',
728
                                        mimeType='application/json')))))
729
        rv = get_inputs_from_xml(request_doc)
1✔
730
        self.assertEqual(rv['json'][0]['mimeType'], 'application/json')
1✔
731
        json_data = json.loads(rv['json'][0]['data'].decode())
1✔
732
        self.assertEqual(json_data['plot']['Version'], '0.1')
1✔
733

734
    def test_bbox_input(self):
1✔
735
        request_doc = WPS.Execute(
1✔
736
            OWS.Identifier('request'),
737
            WPS.DataInputs(
738
                WPS.Input(
739
                    OWS.Identifier('bbox'),
740
                    WPS.Data(
741
                        WPS.BoundingBoxData(
742
                            OWS.LowerCorner('40 50'),
743
                            OWS.UpperCorner('60 70'))))))
744
        rv = get_inputs_from_xml(request_doc)
1✔
745
        bbox = rv['bbox'][0]
1✔
746
        # assert isinstance(bbox, BoundingBox)
747
        assert bbox['data'] == ['40', '50', '60', '70']
1✔
748
        # assert bbox.minx == '40'
749
        # assert bbox.miny == '50'
750
        # assert bbox.maxx == '60'
751
        # assert bbox.maxy == '70'
752

753
    def test_reference_post_input(self):
1✔
754
        request_doc = WPS.Execute(
1✔
755
            OWS.Identifier('foo'),
756
            WPS.DataInputs(
757
                WPS.Input(
758
                    OWS.Identifier('name'),
759
                    WPS.Reference(
760
                        WPS.Body('request body'),
761
                        {'{http://www.w3.org/1999/xlink}href': 'http://foo/bar/service'},
762
                        method='POST'
763
                    )
764
                )
765
            )
766
        )
767
        rv = get_inputs_from_xml(request_doc)
1✔
768
        self.assertEqual(rv['name'][0]['href'], 'http://foo/bar/service')
1✔
769
        self.assertEqual(rv['name'][0]['method'], 'POST')
1✔
770
        self.assertEqual(rv['name'][0]['body'], 'request body')
1✔
771

772
    def test_reference_post_bodyreference_input(self):
1✔
773
        request_doc = WPS.Execute(
1✔
774
            OWS.Identifier('foo'),
775
            WPS.DataInputs(
776
                WPS.Input(
777
                    OWS.Identifier('name'),
778
                    WPS.Reference(
779
                        WPS.BodyReference(
780
                            {'{http://www.w3.org/1999/xlink}href': 'http://foo/bar/reference'}),
781
                        {'{http://www.w3.org/1999/xlink}href': 'http://foo/bar/service'},
782
                        method='POST'
783
                    )
784
                )
785
            )
786
        )
787
        rv = get_inputs_from_xml(request_doc)
1✔
788
        self.assertEqual(rv['name'][0]['href'], 'http://foo/bar/service')
1✔
789
        self.assertEqual(rv['name'][0]['bodyreference'], 'http://foo/bar/reference')
1✔
790

791
    def test_build_input_file_name(self):
1✔
792
        from pywps.inout.basic import ComplexInput
1✔
793

794
        h = ComplexInput('ci')
1✔
795
        h.workdir = workdir = configuration.get_config_value('server', 'workdir')
1✔
796

797
        self.assertEqual(
1✔
798
            h._build_file_name('http://path/to/test.txt'),
799
            os.path.join(workdir, 'test.txt'))
800
        self.assertEqual(
1✔
801
            h._build_file_name('http://path/to/test'),
802
            os.path.join(workdir, 'test'))
803
        self.assertEqual(
1✔
804
            h._build_file_name('file://path/to/.config'),
805
            os.path.join(workdir, '.config'))
806
        self.assertEqual(
1✔
807
            h._build_file_name('https://path/to/test.txt?token=abc&expires_at=1234567'),
808
            os.path.join(workdir, 'test.txt'))
809

810
        h.supported_formats = [FORMATS.TEXT, ]
1✔
811
        h.data_format = FORMATS.TEXT
1✔
812
        self.assertEqual(
1✔
813
            h._build_file_name('http://path/to/test'),
814
            os.path.join(workdir, 'test.txt'))
815

816
        open(os.path.join(workdir, 'duplicate.html'), 'a').close()
1✔
817
        inpt_filename = h._build_file_name('http://path/to/duplicate.html')
1✔
818
        self.assertTrue(inpt_filename.startswith(os.path.join(workdir, 'duplicate_')))
1✔
819
        self.assertTrue(inpt_filename.endswith('.html'))
1✔
820

821

822
def load_tests(loader=None, tests=None, pattern=None):
1✔
823
    import unittest
×
824

825
    if not loader:
×
826
        loader = unittest.TestLoader()
×
827
    suite_list = [
×
828
        loader.loadTestsFromTestCase(ExecuteTest),
829
        loader.loadTestsFromTestCase(ExecuteTranslationsTest),
830
        loader.loadTestsFromTestCase(ExecuteXmlParserTest),
831
    ]
832
    return unittest.TestSuite(suite_list)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc