Skip to content

Commit

Permalink
Merge pull request #105 from OnroerendErfgoed/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
goessebr authored Feb 9, 2021
2 parents 4078cd3 + 60cb072 commit 9a38932
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 169 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
language: python
python:
- 2.7
- 3.6
- 3.7
- 3.8
Expand Down
7 changes: 7 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
0.4.0 (2021-02-09)
------------------
- Upgrade libraries, fe dogpile.cache (#95)
- Drop support for python 2 (#96)
- Only build property concept_scheme once (#97)
- Lazy access concept_scheme.uri (#98)

0.3.1 (2020-02-19)
------------------

Expand Down
6 changes: 2 additions & 4 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
--requirement requirements.txt

# Documentation
Sphinx==1.8.5 ; python_version < '3.5'
Sphinx==2.4.2 ; python_version >= '3.5'
Sphinx==3.4.3

# Unit testing
tox==3.14.5
pytest==4.6.9 ; python_version < '3.0'
pytest==5.3.5 ; python_version >= '3.0'
pytest==5.3.5
responses==0.10.9
pytest-cov==2.8.1
coveralls==1.11.1
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
requests==2.23.0
skosprovider==0.7.0
requests==2.25.1
skosprovider==0.7.1
# -e git+https://github.com/koenedaele/skosprovider.git@DEV_0.7.0#egg=skosprovider
dogpile.cache==0.9.0
dogpile.cache==1.1.2
13 changes: 5 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import os

try:
from setuptools import setup, find_packages
except ImportError:
from distutils.core import setup
from setuptools import setup

here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.rst')).read()
Expand All @@ -13,12 +10,13 @@
]

requires = [
'skosprovider>=0.7.0',
'requests'
'skosprovider>=0.7.1',
'requests',
'dogpile.cache>=1.1.0',
]
setup(
name='skosprovider_atramhasis',
version='0.3.1',
version='0.4.0',
description='Skosprovider implementation of Atramhasis Vocabularies',
long_description=README,
long_description_content_type='text/x-rst',
Expand All @@ -32,7 +30,6 @@
'Natural Language :: English',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
Expand Down
13 changes: 5 additions & 8 deletions skosprovider_atramhasis/cache_utils.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
# -*- coding: utf-8 -*-
'''
"""
Utility functions for chaching in :mod:`skosprovider_atramhasis`.
'''
"""

import functools
import json

from dogpile.util import compat


def _atramhasis_key_generator(namespace, fn, to_str=compat.string_type):
def _atramhasis_key_generator(namespace, fn, to_str=str):
"""
This is mostly a copy of dogpile.cache.util.function_key_generator.
Expand All @@ -18,9 +15,9 @@ def _atramhasis_key_generator(namespace, fn, to_str=compat.string_type):
don't use each other's caches. As well as we try and handle kwargs.
"""
if namespace is None:
namespace = '%s:%s' % (fn.__module__, fn.__name__)
namespace = f'{fn.__module__}:{fn.__name__}'
else:
namespace = '%s:%s|%s' % (fn.__module__, fn.__name__, namespace)
namespace = f'{fn.__module__}:{fn.__name__}|{namespace}'

def generate_key(*args, **kwargs):
provider = args[0]
Expand Down
125 changes: 69 additions & 56 deletions skosprovider_atramhasis/providers.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
# -*- coding: utf-8 -*-
'''
"""
This module implements a :class:`skosprovider.providers.VocabularyProvider`
for Atramhasis
'''
"""
import logging

import requests
from requests.exceptions import ConnectionError, Timeout
from dogpile.cache import make_region
from requests.exceptions import ConnectionError
from requests.exceptions import Timeout
from skosprovider.exceptions import ProviderUnavailableException
from skosprovider.providers import VocabularyProvider
from skosprovider.skos import ConceptScheme
from skosprovider.skos import Label
from skosprovider.skos import Note
from skosprovider.skos import dict_to_source

from skosprovider_atramhasis.cache_utils import _atramhasis_key_generator
from skosprovider_atramhasis.cache_utils import _cache_on_arguments
from skosprovider_atramhasis.utils import dict_to_thing
from skosprovider.exceptions import ProviderUnavailableException
from skosprovider.providers import VocabularyProvider
from skosprovider.skos import ConceptScheme, Label, Note, dict_to_source

log = logging.getLogger(__name__)


class AtramhasisProvider(VocabularyProvider):
"""A provider that can work with the Atramhasis REST services (based on pyramid_skosprovider)
"""
"""A provider that can work with the Atramhasis REST services"""

base_url = None
'''Base URL of an Atramhasis instance.'''
Expand All @@ -34,6 +35,8 @@ class AtramhasisProvider(VocabularyProvider):
The :class:`requests.Session` being used to make HTTP requests.
'''

# noinspection PyMissingConstructor
# intentionally does not call super.
def __init__(self, metadata, **kwargs):
"""Create a new AtramhasisProvider
Expand All @@ -45,10 +48,12 @@ def __init__(self, metadata, **kwargs):
* `cache_config` is an optional dict. Only keys starting with
"cache." are relevant.
"""

if not 'subject' in metadata:
if 'subject' not in metadata:
metadata['subject'] = []
if 'uri' not in metadata:
metadata['uri'] = f'{self.base_url}/conceptschemes/{self.scheme_id}'
self.metadata = metadata
self._conceptscheme = None
self.allowed_instance_scopes = kwargs.get(
'allowed_instance_scopes',
['single', 'threaded_thread']
Expand Down Expand Up @@ -81,11 +86,13 @@ def __init__(self, metadata, **kwargs):

@property
def concept_scheme(self):
return self._get_concept_scheme()
if self._conceptscheme is None:
self._conceptscheme = self._get_concept_scheme()
return self._conceptscheme

def _get_concept_scheme(self):
request = self.base_url + '/conceptschemes/' + self.scheme_id
response = self._request(request, {'Accept': 'application/json'}, dict())
request = f'{self.base_url}/conceptschemes/{self.scheme_id}'
response = self._request(request, {'Accept': 'application/json'})
if response.status_code == 404:
raise ProviderUnavailableException(
"Conceptscheme %s not found. Check your configuration." % request
Expand All @@ -94,27 +101,27 @@ def _get_concept_scheme(self):
return ConceptScheme(
cs['uri'],
labels=[
Label(l['label'] if 'label' in l.keys() else '<no label>',
l['type'] if 'type' in l.keys() else 'prefLabel',
l['language'] if 'language' in l.keys() else 'und')
for l in cs['labels']
Label(
label.get('label', '<no label>'),
label.get('type', 'prefLabel'),
label.get('language', 'und'),
) for label in cs['labels']
],
notes=[
Note(n['note'] if 'note' in n.keys() else '<no note>',
n['type'] if 'type' in n.keys() else 'note',
n['language'] if 'language' in n.keys() else 'und',
n['markup'] if 'markup' in n.keys() else None)
for n in cs['notes']
],
sources=[
dict_to_source(s) for s in cs['sources']
Note(
note.get('note', '<no note>'),
note.get('type', 'note'),
note.get('language', 'und'),
note.get('markup'),
) for note in cs['notes']
],
sources=[dict_to_source(s) for s in cs['sources']],
languages=cs['languages']
)

@_cache_on_arguments(cache_name='cache')
def get_by_id(self, id):
request = self.base_url + '/conceptschemes/' + self.scheme_id + "/c/" + str(id)
def get_by_id(self, id_):
request = f'{self.base_url}/conceptschemes/{self.scheme_id}/c/{id_}'
response = self._request(request, {'Accept': 'application/json'})
if response.status_code == 404:
return False
Expand All @@ -123,7 +130,7 @@ def get_by_id(self, id):

@_cache_on_arguments(cache_name='cache')
def get_by_uri(self, uri):
request = self.base_url + "/uris"
request = f'{self.base_url}/uris'
params = {'uri': uri}
response = self._request(request, {'Accept': 'application/json'}, params)
if response.status_code == 404:
Expand All @@ -136,8 +143,7 @@ def get_by_uri(self, uri):
def find(self, query, **kwargs):
# interprete and validate query parameters

params = {}
params['language'] = self._get_language(**kwargs)
params = {'language': self._get_language(**kwargs)}
params.update(self._get_sort_params(**kwargs))

# Label
Expand All @@ -151,11 +157,15 @@ def find(self, query, **kwargs):
# Collection to search in (optional)
if 'collection' in query:
collection = query['collection']
if not 'id' in collection:
raise ValueError("collection: 'id' is required key if a collection-dictionary is given")
if 'id' not in collection:
raise ValueError(
"collection: 'id' is required key if a collection-dictionary is given"
)
params['collection'] = collection['id']
if 'depth' in collection and collection['depth'] != 'all':
raise ValueError("collection - 'depth': only 'all' is supported by Atramhasis")
raise ValueError(
"collection - 'depth': only 'all' is supported by Atramhasis"
)

# Match
if 'matches' in query:
Expand All @@ -168,17 +178,16 @@ def find(self, query, **kwargs):
if match_type:
params['match_type'] = match_type

search_url = self.base_url + '/conceptschemes/' + self.scheme_id + "/c/"
search_url = f'{self.base_url}/conceptschemes/{self.scheme_id}/c/'
response = self._request(search_url, {'Accept': 'application/json'}, params)
if response.status_code == 404:
return False
return response.json()

@_cache_on_arguments(cache_name='cache')
def get_all(self, **kwargs):
request = self.base_url + '/conceptschemes/' + self.scheme_id + "/c/"
params = dict()
params['language'] = self._get_language(**kwargs)
request = f'{self.base_url}/conceptschemes/{self.scheme_id}/c/'
params = {'language': self._get_language(**kwargs)}
params.update(self._get_sort_params(**kwargs))
response = self._request(request, {'Accept': 'application/json'}, params)
if response.status_code == 404:
Expand All @@ -187,9 +196,8 @@ def get_all(self, **kwargs):

@_cache_on_arguments(cache_name='cache')
def get_top_concepts(self, **kwargs):
request = self.base_url + '/conceptschemes/' + self.scheme_id + "/topconcepts"
params = dict()
params['language'] = self._get_language(**kwargs)
request = f'{self.base_url}/conceptschemes/{self.scheme_id}/topconcepts'
params = {'language': self._get_language(**kwargs)}
params.update(self._get_sort_params(**kwargs))
response = self._request(request, {'Accept': 'application/json'}, params)
if response.status_code == 404:
Expand All @@ -198,18 +206,19 @@ def get_top_concepts(self, **kwargs):

@_cache_on_arguments(cache_name='cache')
def get_top_display(self, **kwargs):
request = self.base_url + '/conceptschemes/' + self.scheme_id + "/displaytop"
params = dict()
params['language'] = self._get_language(**kwargs)
request = f'{self.base_url}/conceptschemes/{self.scheme_id}/displaytop'
params = {'language': self._get_language(**kwargs)}
params.update(self._get_sort_params(**kwargs))
response = self._request(request, {'Accept': 'application/json'}, params)
if response.status_code == 404:
return False
return response.json()

@_cache_on_arguments(cache_name='cache')
def get_children_display(self, id, **kwargs):
request = self.base_url + '/conceptschemes/' + self.scheme_id + "/c/" + str(id) + "/displaychildren"
def get_children_display(self, id_, **kwargs):
request = (
f'{self.base_url}/conceptschemes/{self.scheme_id}/c/{id_}/displaychildren'
)
params = dict()
params['language'] = self._get_language(**kwargs)
params.update(self._get_sort_params(**kwargs))
Expand All @@ -219,8 +228,8 @@ def get_children_display(self, id, **kwargs):
return response.json()

@_cache_on_arguments(cache_name='cache')
def expand(self, id):
request = self.base_url + '/conceptschemes/' + self.scheme_id + "/c/" + str(id) + "/expand"
def expand(self, id_):
request = f'{self.base_url}/conceptschemes/{self.scheme_id}/c/{id_}/expand'
response = self._request(request, {'Accept': 'application/json'})
if response.status_code != 200:
return False
Expand All @@ -238,14 +247,18 @@ def _request(self, request, headers=None, params=None):
try:
res = self.session.get(request, headers=headers, params=params)
except ConnectionError:
raise ProviderUnavailableException("Request could not be executed \
due to connection issues- Request: %s" % (request,))
except Timeout: # pragma: no cover
raise ProviderUnavailableException("Request could not be executed \
due to timeout - Request: %s" % (request,))
raise ProviderUnavailableException(
f"Request could not be executed due to connection issues - "
f"Request: {request}"
)
except Timeout: # pragma: no cover
raise ProviderUnavailableException(
f"Request could not be executed due to timeout - Request: {request}"
)
if res.status_code >= 500:
raise ProviderUnavailableException("Request could not be executed \
due to server issues - Request: %s" % (request,))
raise ProviderUnavailableException(
f"Request could not be executed due to server issues - Request: {request}"
)
if not res.encoding:
res.encoding = 'utf-8'
return res
Loading

0 comments on commit 9a38932

Please sign in to comment.