Skip to content

Commit

Permalink
Merge pull request #164 from f-PLT/add-multiple-lang-support
Browse files Browse the repository at this point in the history
Adding language support to Birdy
  • Loading branch information
huard authored Apr 21, 2020
2 parents 13badf6 + 2f0b071 commit b660066
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 43 deletions.
46 changes: 25 additions & 21 deletions birdy/cli/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,24 @@ def __init__(self, name=None, url=None, caps_xml=None, desc_xml=None, **attrs):
self.verify = get_ssl_verify()
self.caps_xml = caps_xml
self.desc_xml = desc_xml
self.wps = WebProcessingService(self.url, verify=self.verify, skip_caps=True)
self._wps = None
self.commands = OrderedDict()

@property
def wps(self):
if self._wps is None:
language = self.context_settings['obj'].get('language')
self._wps = WebProcessingService(self.url, verify=self.verify, skip_caps=True, language=language)
return self._wps

def _update_commands(self):
if not self.commands:
try:
self.wps.getcapabilities(xml=self.caps_xml)
except SSLError:
raise ConnectionError('SSL verfication of server certificate failed. Set WPS_SSL_VERIFY=false.')
except Exception:
raise ConnectionError("Web Processing Service not available.")
except Exception as e:
raise ConnectionError("Could not connect to Web Processing Service ({!r})".format(e))
for process in self.wps.processes:
self.commands[process.identifier] = dict(
name=process.identifier,
Expand All @@ -50,7 +57,6 @@ def _update_commands(self):
options=[])

def list_commands(self, ctx):
ctx.obj = True
self._update_commands()
return list(self.commands.keys())

Expand All @@ -65,23 +71,21 @@ def get_command(self, ctx, name):

def _get_command_info(self, name, ctx):
cmd = self.commands.get(name)
if ctx.obj is None or False:
pp = self.wps.describeprocess(name, xml=self.desc_xml)
for inp in pp.dataInputs:
help = inp.title or ''
default = BirdyCLI.get_param_default(inp)
if default:
help = "{}. Default: {}".format(help, default)
cmd['options'].append(dict(
name=inp.identifier,
# default=BirdyCLI.get_param_default(inp),
help=help,
type=BirdyCLI.get_param_type(inp),
multiple=inp.maxOccurs > 1))
outputs = []
for output in pp.processOutputs:
outputs.append((output.identifier, BirdyCLI.get_param_type(output) is COMPLEX))
ctx.obj = dict(outputs=outputs)
pp = self.wps.describeprocess(name, xml=self.desc_xml)
for inp in pp.dataInputs:
help = inp.title or ''
default = BirdyCLI.get_param_default(inp)
if default:
help = "{}. Default: {}".format(help, default)
cmd['options'].append(dict(
name=inp.identifier.replace(' ', '-'),
# default=BirdyCLI.get_param_default(inp),
help=help,
type=BirdyCLI.get_param_type(inp),
multiple=inp.maxOccurs > 1))
outputs = []
for output in pp.processOutputs:
outputs.append((output.identifier, BirdyCLI.get_param_type(output) is COMPLEX))
return cmd

@staticmethod
Expand Down
29 changes: 28 additions & 1 deletion birdy/cli/run.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import os

import click
from birdy.cli.base import BirdyCLI
from birdy.cli.misc import get_ssl_verify

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
from owslib.wps import WebProcessingService

CONTEXT_OBJ = dict(language=None)
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'], obj=CONTEXT_OBJ)
DEFAULT_URL = "http://localhost:5000/wps"


def _show_languages(ctx, param, value):
if not value or ctx.resilient_parsing:
return
url = os.environ.get('WPS_SERVICE') or DEFAULT_URL
wps = WebProcessingService(url, verify=get_ssl_verify())
click.echo(','.join(wps.languages.supported))
ctx.exit()


def _set_language(ctx, param, value):
if not value or ctx.resilient_parsing:
return
CONTEXT_OBJ['language'] = value


@click.command(cls=BirdyCLI, context_settings=CONTEXT_SETTINGS,
Expand All @@ -12,6 +33,12 @@
@click.option('--send', '-S', is_flag=True, help="Send client side certificate to WPS. Default: false")
@click.option("--sync", '-s', is_flag=True, help="Execute process in sync mode. Default: async mode.")
@click.option("--token", "-t", help="Token to access the WPS service.")
@click.option(
"--language", "-l", expose_value=False, is_eager=True, callback=_set_language,
help="Set the accepted language to send to the WPS service.")
@click.option(
"--show-languages", "-L", expose_value=False, is_flag=True, is_eager=True, callback=_show_languages,
help="Show a list of accepted languages for the WPS service.")
@click.pass_context
def cli(ctx, cert, send, sync, token):
"""
Expand Down
16 changes: 16 additions & 0 deletions birdy/client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def __init__(
version=WPS_DEFAULT_VERSION,
caps_xml=None,
desc_xml=None,
language=None,
):
"""
Args:
Expand All @@ -63,6 +64,8 @@ def __init__(
verbose (str): passed to :class:`owslib.wps.WebProcessingService`
progress (bool): If True, enable interactive user mode.
version (str): WPS version to use.
language (str): passed to :class:`owslib.wps.WebProcessingService`
ex: 'fr-CA', 'en_US'.
"""
self._converters = converters
self._interactive = progress
Expand Down Expand Up @@ -102,6 +105,7 @@ def __init__(
verify=verify,
cert=cert,
skip_caps=True,
language=language
)

try:
Expand All @@ -125,6 +129,18 @@ def __init__(

self.__doc__ = utils.build_wps_client_doc(self._wps, self._processes)

@property
def language(self):
return self._wps.language

@language.setter
def language(self, value):
self._wps.language = value

@property
def languages(self):
return self._wps.languages

def _get_process_description(self, processes=None, xml=None):
"""Return the description for each process.
Expand Down
3 changes: 2 additions & 1 deletion birdy/templates/cmd.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def cli(ctx, **options):
if send and cert:
with open(cert, 'r') as fh:
headers = {'X-Ssl-Client-Cert': quote(fh.read())}
wps = WebProcessingService('{{ url }}', skip_caps=True, verify=verify, cert=cert, headers=headers)
language = ctx.obj.get('language')
wps = WebProcessingService('{{ url }}', skip_caps=True, verify=verify, cert=cert, headers=headers, language=language)
inputs = []
for opt in options.keys():
if not options[opt]:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
click
jinja2
lxml
owslib>=0.18
owslib>=0.19.2
wrapt
funcsigs
boltons
Expand Down
3 changes: 2 additions & 1 deletion tests/resources/wps_emu_caps.xml
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@
<ows:Language>en-US</ows:Language>
</wps:Default>
<wps:Supported>
<ows:Language>lang</ows:Language>
<ows:Language>en-US</ows:Language>
<ows:Language>fr-CA</ows:Language>
</wps:Supported>
</wps:Languages>
</wps:Capabilities>
32 changes: 17 additions & 15 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
from click.testing import CliRunner
import pytest

import click
from click.testing import CliRunner
import birdy.cli.run

from birdy.cli.base import BirdyCLI
from .common import (
URL_EMU,
EMU_CAPS_XML,
# EMU_DESC_XML,
)
from .common import EMU_CAPS_XML, URL_EMU


@click.command(cls=BirdyCLI,
url=URL_EMU,
caps_xml=EMU_CAPS_XML,
# desc_xml=EMU_DESC_XML
)
def cli():
pass
cli = birdy.cli.run.cli
cli.url = URL_EMU
cli.caps_xml = EMU_CAPS_XML


@pytest.mark.online
def test_help():
runner = CliRunner()
result = runner.invoke(cli, ['--help'])
assert result.exit_code == 0
assert 'hello' in result.output
assert 'wordcount' in result.output
assert 'language' in result.output
assert 'show-languages' in result.output


@pytest.mark.online
def test_show_languages():
runner = CliRunner()
result = runner.invoke(cli, ['--show-languages'])
assert result.exit_code == 0
assert 'en-US' in result.output


@pytest.mark.online
Expand Down
18 changes: 15 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,21 @@ def process():
return owslib.wps.Process(xml)


def test_emu_offline():
wps = WPSClient(URL_EMU, caps_xml=EMU_CAPS_XML, desc_xml=EMU_DESC_XML)
assert 'Hello' in wps.hello.__doc__
def test_emu_offline(wps_offline):
assert 'Hello' in wps_offline.hello.__doc__


def test_wps_supported_languages(wps_offline):
assert wps_offline.languages.supported == ['en-US', 'fr-CA']


def test_wps_with_language_arg():
wps = WPSClient(URL_EMU, language='fr-CA')
assert wps.language == 'fr-CA'
p = wps._processes['translation']
assert p.title == "Processus traduit"
resp = wps.translation(10)
assert resp.processOutputs[0].title == "Sortie #1"


@pytest.mark.online
Expand Down

0 comments on commit b660066

Please sign in to comment.