Skip to content

Commit

Permalink
[mw] Add CLI interface for search operation on IFI CLAIMS
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Jun 3, 2022
1 parent 91278c8 commit 0f48979
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ jobs:
env:
OPS_API_CONSUMER_KEY: ${{ secrets.OPS_API_CONSUMER_KEY }}
OPS_API_CONSUMER_SECRET: ${{ secrets.OPS_API_CONSUMER_SECRET }}
IFICLAIMS_API_URI: ${{ secrets.IFICLAIMS_API_URI }}
IFICLAIMS_API_USERNAME: ${{ secrets.IFICLAIMS_API_USERNAME }}
IFICLAIMS_API_PASSWORD: ${{ secrets.IFICLAIMS_API_PASSWORD }}

name: Python ${{ matrix.python-version }} on OS ${{ matrix.os }}
steps:
Expand Down
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Development
- [mw] Improve "minimal" application framework bootstrapping
- [mw] Add CLI interface for basic operations on EPO/OPS
- [mw] Fix access to DPMAregister due to upstream changes
- [mw] Add CLI interface for search operation on IFI CLAIMS


2019-11-01 0.169.3
Expand Down
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ Examples using EPO/OPS::
# Acquire first drawing of patent document in PDF format.
patzilla ops image --document EP0666666B1 --page 1 --kind FullDocumentDrawing > EP0666666B1-drawing1.pdf

Example using IFI CLAIMS::

patzilla ificlaims search "text:(wind or solar) and energy"


*****
Demos
Expand Down
2 changes: 1 addition & 1 deletion docs/running/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ essential options configuring access to data sources on the command line::
export IFICLAIMS_API_URI=https://cdws21.ificlaims.com
export IFICLAIMS_API_USERNAME=acme
export IFICLAIMS_API_PASSWORD=10f8GmWTz
patzilla ificlaims lalala
patzilla ificlaims search "text:(wind or solar) and energy"

# For accessing "depa.tech".
export DEPATECH_API_URI=https://api.depa.tech
Expand Down
1 change: 1 addition & 0 deletions patzilla/access/ificlaims/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ def search_real(self, query, options=None):
else:
raise self.search_failed(
user_info=message,
message=message,
response=response)

# Mogrify search response
Expand Down
58 changes: 53 additions & 5 deletions patzilla/access/ificlaims/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,77 @@
export IFICLAIMS_API_URI=https://cdws21.ificlaims.com
export IFICLAIMS_API_USERNAME=acme
export IFICLAIMS_API_PASSWORD=10f8GmWTz
python -m patzilla.access.ificlaims.commands
patzilla ificlaims search "text:(wind or solar) and energy"
Use configuration file::
python -m patzilla.access.ificlaims.commands patzilla/config/development-local.ini
python -m patzilla.access.ificlaims.commands patzilla/config/development-local.ini | jq .
python -m patzilla.access.ificlaims.commands patzilla/config/development-local.ini | xmllint --format -
export PATZILLA_CONFIG=patzilla/config/development-local.ini
patzilla ificlaims search "text:(wind or solar) and energy"
Todo
====
- Pass output type (JSON/XML) via parameter
"""
import json
import logging

import click

from patzilla.access.ificlaims import get_ificlaims_client
from patzilla.boot.cache import configure_cache_backend
from patzilla.boot.config import BootConfiguration
from patzilla.util.config import get_configfile_from_commandline
from patzilla.util.data.container import SmartBunch
from patzilla.util.data.container import SmartBunch, jd
from patzilla.boot.framework import pyramid_setup


logger = logging.getLogger(__name__)


@click.group(name="ificlaims")
@click.pass_context
def ificlaims_cli(ctx):
"""
Access the IFI CLAIMS data source adapter.
"""

# Create a Pyramid runtime environment.
env = pyramid_setup(
configfile=get_configfile_from_commandline(),
bootconfiguration=BootConfiguration(datasources=["ificlaims"]),
)

# Propagate reference to the environment to the Click context.
ctx.meta["pyramid_env"] = env


@click.command(name="search")
@click.argument("expression", type=str, required=True)
@click.option('--json', "request_json", is_flag=True, type=bool, default=False, required=False,
help="Request/return data as JSON, otherwise use XML")
@click.pass_context
def search(ctx, expression, request_json):
"""
Access the IFICLAIMS bibliographic- and fulltext-search API.
The `expression` argument accepts the search expression in Solr search syntax.
TODO: Currently, only the first 100 hits will be displayed. Extend range by implementing "crawling".
"""

# Get hold of data source client utility.
client = get_ificlaims_client()

# Invoke API and output result.
logger.warning("Only the first 100 hits will be displayed. The CLI currently does not employ paging.")
results = client.search(SmartBunch({'expression': expression}), SmartBunch({'offset': 0, 'limit': 100}))
print(jd(results))


ificlaims_cli.add_command(cmd=search)


def make_request(client):

#results = client.search('*:*')
Expand Down
2 changes: 2 additions & 0 deletions patzilla/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from docopt import docopt

from patzilla.access.epo.ops.commands import ops_cli
from patzilla.access.ificlaims.commands import ificlaims_cli
from patzilla.boot.cache import configure_cache_backend
from patzilla.config import get_configuration
from patzilla.util.config import read_list, normalize_docopt_options
Expand Down Expand Up @@ -71,6 +72,7 @@ def make_config(ctx, kind, flavor):

cli.add_command(cmd=make_config)
cli.add_command(cmd=ops_cli)
cli.add_command(cmd=ificlaims_cli)


def usercmd():
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def app_environment():
"""
Provide and configure a Pyramid environment at runtime, a minimal application flavor.
"""
return pyramid_setup(bootconfiguration=BootConfiguration(flavor="minimal", datasources=["ops"]))
return pyramid_setup(bootconfiguration=BootConfiguration(flavor="minimal", datasources=["ops", "ificlaims"]))


@pytest.fixture(scope="function")
Expand All @@ -48,7 +48,7 @@ def web_environment():
"""
Provide and configure a Pyramid environment at runtime, this time the full web application flavor.
"""
return pyramid_setup(bootconfiguration=BootConfiguration(flavor="web", datasources=["ops"]))
return pyramid_setup(bootconfiguration=BootConfiguration(flavor="web", datasources=["ops", "ificlaims"]))


@pytest.fixture(scope='session', autouse=True)
Expand Down
30 changes: 30 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pytest
from pyramid.httpexceptions import HTTPNotFound

from patzilla.access.generic.exceptions import SearchException
from patzilla.commands import cli


Expand Down Expand Up @@ -133,3 +134,32 @@ def test_command_ops_image_failure():
with pytest.raises(HTTPNotFound) as ex:
runner.invoke(cli, "ops image --document=EP123A2 --page=1", catch_exceptions=False)
ex.match("No image information for document=EP123A2")


def test_command_ificlaims_search_success():
"""
Proof that `patzilla ificlaims search` works as intended.
"""
runner = CliRunner()

result = runner.invoke(cli, "--verbose ificlaims search pn:EP0666666", catch_exceptions=False)
assert result.exit_code == 0

data = json.loads(result.stdout)
assert data["meta"]["navigator"]["count_total"] == 3
assert data["meta"]["upstream"]["status"] == "success"
assert data["meta"]["upstream"]["params"]["q"] == "pn:EP0666666"
assert data["numbers"] == ["EP0666666B1", "EP0666666A3", "EP0666666A2"]
assert len(data["details"]) == 3


def test_command_ificlaims_search_failure():
"""
Proof that bad input to `patzilla ificlaims search` croaks as intended.
"""
runner = CliRunner()

with pytest.raises(SearchException) as ex:
runner.invoke(cli, "ificlaims search foo:bar", catch_exceptions=False)
ex.match("Response status code: 400")
ex.match("undefined field foo")

0 comments on commit 0f48979

Please sign in to comment.