atramhasis.utils.from_thing()   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 61
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 44
dl 0
loc 61
rs 7.8906
c 0
b 0
f 0
cc 6
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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