Skip to content

Commit

Permalink
Merge pull request #74 from crim-ca/wps-execute-accept-language
Browse files Browse the repository at this point in the history
Wps execute accept language
  • Loading branch information
David Caron committed Feb 10, 2020
2 parents b3ca9ff + 7886744 commit e876b75
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 2 deletions.
32 changes: 32 additions & 0 deletions tests/wps_restapi/test_processes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import unittest
from copy import deepcopy
import mock

import pyramid.testing
import pytest
Expand Down Expand Up @@ -32,6 +33,7 @@
from weaver.utils import fully_qualified_name, ows_context_href
from weaver.visibility import VISIBILITY_PRIVATE, VISIBILITY_PUBLIC
from weaver.wps import get_wps_url
from weaver.wps_restapi.processes.processes import set_wps_language

# simulated remote server with remote processes (mocked with `responses` package)
TEST_REMOTE_SERVER_URL = "https://remote-server.com"
Expand Down Expand Up @@ -486,6 +488,36 @@ def test_execute_process_success(self):
assert job.id == resp.json["jobID"]
assert job.task_id == STATUS_ACCEPTED # temporary value until processed by celery

def test_execute_process_language(self):
uri = "/processes/{}/jobs".format(self.process_public.identifier)
data = self.get_process_execute_template()
task = "job-{}".format(fully_qualified_name(self))
mock_execute = mocked_process_job_runner(task)

with contextlib.ExitStack() as stack:
for exe in mock_execute:
stack.enter_context(exe)
headers = self.json_headers.copy()
headers["Accept-Language"] = "fr-CA"
resp = self.app.post_json(uri, params=data, headers=headers)
assert resp.status_code == 201
try:
job = self.job_store.fetch_by_id(resp.json["jobID"])
except JobNotFound:
self.fail("Job should have been created and be retrievable.")
assert job.id == resp.json["jobID"]
assert job.accept_language == "fr-CA"

def test_set_wps_language(self):
wps = mock.Mock()
languages = mock.Mock()
wps.languages = languages
languages.default = 'en-US'
languages.supported = ['en-US', 'fr-CA']

set_wps_language(wps, 'ru, fr;q=0.5')
assert wps.language == 'fr-CA'

def test_execute_process_no_json_body(self):
uri = "/processes/{}/jobs".format(self.process_public.identifier)
resp = self.app.post_json(uri, headers=self.json_headers, expect_errors=True)
Expand Down
13 changes: 13 additions & 0 deletions weaver/datatype.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,18 @@ def notification_email(self, email):
raise TypeError("Type 'str' is required for '{}.notification_email'".format(type(self)))
self["notification_email"] = email

@property
def accept_language(self):
# type: () -> Optional[AnyStr]
return self.get("accept_language")

@accept_language.setter
def accept_language(self, language):
# type: (Optional[Union[AnyStr]]) -> None
if not isinstance(language, six.string_types):
raise TypeError("Type 'str' is required for '{}.accept_language'".format(type(self)))
self["accept_language"] = language

@property
def execute_async(self):
# type: () -> bool
Expand Down Expand Up @@ -555,6 +567,7 @@ def params(self):
"request": self.request,
"response": self.response,
"notification_email": self.notification_email,
"accept_language": self.accept_language,
}


Expand Down
2 changes: 2 additions & 0 deletions weaver/store/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ def save_job(self,
custom_tags=None, # type: Optional[List[AnyStr]]
access=None, # type: Optional[AnyStr]
notification_email=None, # type: Optional[AnyStr]
accept_language=None, # type: Optional[AnyStr]
): # type: (...) -> Job
"""
Stores a job in mongodb.
Expand Down Expand Up @@ -412,6 +413,7 @@ def save_job(self,
"tags": list(set(tags)),
"access": access,
"notification_email": notification_email,
"accept_language": accept_language,
})
self.collection.insert_one(new_job.params())
job = self.fetch_by_id(job_id=new_job.id)
Expand Down
32 changes: 31 additions & 1 deletion weaver/wps_restapi/processes/processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def execute_process(self, job_id, url, headers=None, notification_email=None):
try:
LOGGER.debug("Execute process WPS request for [%s]", job.process)
wps = WebProcessingService(url=url, headers=get_cookie_headers(headers), verify=ssl_verify)
set_wps_language(wps, job.accept_language)
# noinspection PyProtectedMember
raise_on_xml_exception(wps._capabilities)
except Exception as ex:
Expand Down Expand Up @@ -201,6 +202,35 @@ def execute_process(self, job_id, url, headers=None, notification_email=None):
return job.status


def set_wps_language(wps, accept_language):
# type: (WebProcessingService, str) -> None
"""Set the :attr:`language` property on the :class:`WebProcessingService` object.
Given the `Accept-Language` header value, match the best language
to the supported languages.
By default, and if no match is found, the :attr:`WebProcessingService.language`
property is set to None.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
(q-factor weighting is ignored, only order is considered)
:param str accept_language: the value of the Accept-Language header
"""
if not hasattr(wps, "languages"):
# owslib version doesn't support setting a language
return

accepted_languages = [lang.strip().split(';')[0] for lang in accept_language.lower().split(",")]

for accept in accepted_languages:
for language in wps.languages.supported:
# Accept-Language header could be only 'fr' instead of 'fr-CA'
if language.lower().startswith(accept):
wps.language = language
return


def validate_supported_submit_job_handler_parameters(json_body):
"""
Tests supported parameters not automatically validated by colander deserialize.
Expand Down Expand Up @@ -248,7 +278,7 @@ def submit_job_handler(request, service_url, is_workflow=False, visibility=None)
job = store.save_job(task_id=STATUS_ACCEPTED, process=process_id, service=provider_id,
inputs=json_body.get("inputs"), is_workflow=is_workflow, access=visibility,
user_id=request.authenticated_userid, execute_async=is_execute_async, custom_tags=tags,
notification_email=encrypted_email)
notification_email=encrypted_email, accept_language=str(request.accept_language))
result = execute_process.delay(
job_id=job.id,
url=clean_ows_url(service_url),
Expand Down
7 changes: 6 additions & 1 deletion weaver/wps_restapi/swagger_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ class AcceptHeader(MappingSchema):
]))


class AcceptLanguageHeader(AcceptHeader):
AcceptLanguage = SchemaNode(String(), missing=drop)
AcceptLanguage.name = "Accept-Language"


class KeywordList(SequenceSchema):
keyword = SchemaNode(String())

Expand Down Expand Up @@ -1172,7 +1177,7 @@ class PostProcessesEndpoint(MappingSchema):


class PostProcessJobsEndpoint(ProcessPath):
header = AcceptHeader()
header = AcceptLanguageHeader()
body = Execute()


Expand Down

0 comments on commit e876b75

Please sign in to comment.