Passed
Pull Request — develop (#812)
by
unknown
01:18
created

atramhasis.utils.db_provider_to_skosprovider()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nop 1
dl 0
loc 15
rs 9.9
c 0
b 0
f 0
1
"""
2
Module containing utility functions used by Atramhasis.
3
"""
4
import copy
5
from collections import deque
6
7
from pyramid.httpexceptions import HTTPMethodNotAllowed
8
from skosprovider.skos import Collection
9
from skosprovider.skos import Concept
10
from skosprovider.skos import ConceptScheme
11
from skosprovider.skos import Label
12
from skosprovider.skos import Note
13
from skosprovider.skos import Source
14
from skosprovider.uri import UriPatternGenerator
15
from skosprovider_sqlalchemy.providers import SQLAlchemyProvider
16
from sqlalchemy import orm
17
from sqlalchemy.orm import Session
18
19
from atramhasis.data.models import IDGenerationStrategy
20
from atramhasis.data.models import Provider
21
22
23
def from_thing(thing):
24
    """
25
        Map a :class:`skosprovider_sqlalchemy.models.Thing` to a
26
        :class:`skosprovider.skos.Concept` or
27
        a :class:`skosprovider.skos.Collection`, depending on the type.
28
29
        :param skosprovider_sqlalchemy.models.Thing thing: Thing to map.
30
        :rtype: :class:`~skosprovider.skos.Concept` or
31
            :class:`~skosprovider.skos.Collection`.
32
        """
33
    if thing.type and thing.type == 'collection':
34
        return Collection(
35
            id=thing.concept_id,
36
            uri=thing.uri,
37
            concept_scheme=ConceptScheme(thing.conceptscheme.uri),
38
            labels=[
39
                Label(label.label, label.labeltype_id, label.language_id)
40
                for label in thing.labels
41
            ],
42
            notes=[
43
                Note(n.note, n.notetype_id, n.language_id)
44
                for n in thing.notes
45
            ],
46
            sources=[
47
                Source(s.citation)
48
                for s in thing.sources
49
            ],
50
            members=[member.concept_id for member in thing.members] if hasattr(thing, 'members') else [],
51
            member_of=[c.concept_id for c in thing.member_of],
52
            superordinates=[broader_concept.concept_id for broader_concept in thing.broader_concepts],
53
            infer_concept_relations=thing.infer_concept_relations
54
        )
55
    else:
56
        matches = {}
57
        for m in thing.matches:
58
            key = m.matchtype.name[:m.matchtype.name.find('Match')]
59
            if key not in matches:
60
                matches[key] = []
61
            matches[key].append(m.uri)
62
        return Concept(
63
            id=thing.concept_id,
64
            uri=thing.uri,
65
            concept_scheme=ConceptScheme(thing.conceptscheme.uri),
66
            labels=[
67
                Label(label.label, label.labeltype_id, label.language_id)
68
                for label in thing.labels
69
            ],
70
            notes=[
71
                Note(n.note, n.notetype_id, n.language_id)
72
                for n in thing.notes
73
            ],
74
            sources=[
75
                Source(s.citation)
76
                for s in thing.sources
77
            ],
78
            broader=[c.concept_id for c in thing.broader_concepts],
79
            narrower=[c.concept_id for c in thing.narrower_concepts],
80
            related=[c.concept_id for c in thing.related_concepts],
81
            member_of=[c.concept_id for c in thing.member_of],
82
            subordinate_arrays=[narrower_collection.concept_id for narrower_collection in thing.narrower_collections],
83
            matches=matches,
84
        )
85
86
87
def internal_providers_only(fn):
88
    """
89
    aspect oriented way to check if provider is internal when calling the decorated function
90
91
    :param fn: the decorated function
92
    :return: around advice
93
    :raises pyramid.httpexceptions.HTTPMethodNotAllowed: when provider is not internal
94
    """
95
    def advice(parent_object, *args, **kw):
96
97
        if isinstance(parent_object.provider, SQLAlchemyProvider) and \
98
                'external' not in parent_object.provider.get_metadata()['subject']:
99
            return fn(parent_object, *args, **kw)
100
        else:
101
            raise HTTPMethodNotAllowed()
102
103
    return advice
104
105
106
def update_last_visited_concepts(request, concept_data):
107
    deque_last_visited = deque(maxlen=4)
108
    deque_last_visited.extend(request.session.get('last_visited', []))
109
    try:
110
        # Try to remove concept from the queue to prevent double entries
111
        deque_last_visited.remove(concept_data)
112
    except ValueError:
113
        # Concept is not in the queue
114
        pass
115
    # Add concept to the queue
116
    deque_last_visited.append(concept_data)
117
    request.session['last_visited'] = list(deque_last_visited)
118
119
120
def label_sort(concepts, language='any'):
121
    if not concepts:
122
        return []
123
    return sorted(
124
        concepts, key=lambda concept: concept._sortkey(key='sortlabel',
125
                                                       language=language)
126
    )
127
128
129
def db_provider_to_skosprovider(db_provider: Provider) -> SQLAlchemyProvider:
130
    """Create a SQLAlchemyProvider from a atramhasis.data.models.Provider.
131
132
    :param db_provider: The Provider to use as basis for the SQLAlchemyProvider.
133
    :return: An SQLAlchemyProvider with the data from the `db_provider`
134
    """
135
    metadata = copy.deepcopy(db_provider.meta)
136
    metadata["conceptscheme_id"] = db_provider.conceptscheme_id
137
    metadata['atramhasis.id_generation_strategy'] = db_provider.id_generation_strategy
138
    metadata["id"] = db_provider.id
139
    return SQLAlchemyProvider(
140
        metadata=metadata,
141
        session=orm.object_session(db_provider),
142
        expand_strategy=db_provider.expand_strategy.value,
143
        uri_generator=UriPatternGenerator(db_provider.uri_pattern),
144
    )
145