Completed
Push — master ( fb4288...061ec2 )
by Koen
11s
created

ProviderView   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 209
Duplicated Lines 28.71 %

Importance

Changes 24
Bugs 2 Features 3
Metric Value
c 24
b 2
f 3
dl 60
loc 209
rs 6
wmc 55

14 Methods

Rating   Name   Duplication   Size   Complexity  
B get_uri() 0 23 4
A get_conceptschemes() 0 10 4
A _build_providers() 0 15 3
A get_conceptscheme() 0 16 4
A get_conceptscheme_display_top() 0 8 2
A get_conceptscheme_top_concepts() 0 8 2
C _postprocess_wildcards() 0 9 11
A get_concept_display_children() 11 12 3
A _page_results() 0 18 4
A get_expand() 10 11 3
A get_conceptscheme_concepts() 19 19 4
A get_concept() 1 11 3
A get_concepts() 17 17 4
A _get_sort_params() 0 9 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ProviderView often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf8 -*-
2
'''
3
This module contains the pyramid views that expose services.
4
'''
5
6
from __future__ import unicode_literals
7
8
import itertools
9
10
from pyramid.view import view_config, view_defaults
11
12
from pyramid.compat import ascii_native_
13
14
from pyramid.httpexceptions import (
15
    HTTPNotFound,
16
    HTTPBadRequest
17
)
18
19
from pyramid_skosprovider.utils import (
20
    parse_range_header,
21
    QueryBuilder
22
)
23
24
import logging
25
log = logging.getLogger(__name__)
26
27
28
class RestView(object):
29
30
    def __init__(self, request):
31
        self.request = request
32
        self.skos_registry = self.request.skos_registry
33
34
35
@view_defaults(renderer='skosjson', accept='application/json')
36
class ProviderView(RestView):
37
    '''
38
    A set of views that expose information from a certain provider.
39
    '''
40
41
    @view_config(route_name='skosprovider.uri', request_method='GET')
42
    @view_config(route_name='skosprovider.uri.deprecated', request_method='GET')
43
    def get_uri(self):
44
        uri = self.request.params.get('uri', self.request.matchdict.get('uri', None))
45
        if not uri:
46
            return HTTPBadRequest()
47
        provider = self.skos_registry.get_provider(uri)
48
        if provider:
49
            return {
50
                'type': 'concept_scheme',
51
                'uri': provider.concept_scheme.uri,
52
                'id': provider.get_vocabulary_id()
53
            }
54
        c = self.skos_registry.get_by_uri(uri)
55
        if not c:
56
            return HTTPNotFound()
57
        return {
58
            'type': c.type,
59
            'uri': c.uri,
60
            'id': c.id,
61
            'concept_scheme': {
62
                'uri': c.concept_scheme.uri,
63
                'id': self.skos_registry.get_provider(c.concept_scheme.uri).get_vocabulary_id()
64
            }
65
        }
66
67
    @view_config(route_name='skosprovider.conceptschemes', request_method='GET')
68
    def get_conceptschemes(self):
69
        language = self.request.params.get('language', self.request.locale_name)
70
        return [
71
            {
72
                'id': p.get_vocabulary_id(),
73
                'uri': p.concept_scheme.uri,
74
                'label': p.concept_scheme.label(language).label if p.concept_scheme.label(language) else None,
75
                'subject': p.metadata['subject'] if p.metadata['subject'] else []
76
            } for p in self.skos_registry.get_providers()
77
        ]
78
79
    @view_config(route_name='skosprovider.conceptscheme', request_method='GET')
80
    def get_conceptscheme(self):
81
        scheme_id = self.request.matchdict['scheme_id']
82
        provider = self.skos_registry.get_provider(scheme_id)
83
        if not provider:
84
            return HTTPNotFound()
85
        language = self.request.params.get('language', self.request.locale_name)
86
        return {
87
            'id': provider.get_vocabulary_id(),
88
            'uri': provider.concept_scheme.uri,
89
            'label': provider.concept_scheme.label(language).label if provider.concept_scheme.label(language) else None,
90
            'subject': provider.metadata['subject'] if provider.metadata['subject'] else [],
91
            'labels': provider.concept_scheme.labels,
92
            'notes': provider.concept_scheme.notes,
93
            'sources': provider.concept_scheme.sources,
94
            'languages': provider.concept_scheme.languages
95
        }
96
97
    @view_config(route_name='skosprovider.conceptscheme.tc', request_method='GET')
98
    def get_conceptscheme_top_concepts(self):
99
        scheme_id = self.request.matchdict['scheme_id']
100
        provider = self.skos_registry.get_provider(scheme_id)
101
        if not provider:
102
            return HTTPNotFound()
103
        language = self.request.params.get('language', self.request.locale_name)
104
        return provider.get_top_concepts(language=language)
105
106
    @view_config(route_name='skosprovider.conceptscheme.display_top', request_method='GET')
107
    def get_conceptscheme_display_top(self):
108
        scheme_id = self.request.matchdict['scheme_id']
109
        provider = self.skos_registry.get_provider(scheme_id)
110
        if not provider:
111
            return HTTPNotFound()
112
        language = self.request.params.get('language', self.request.locale_name)
113
        return provider.get_top_display(language=language)
114
115
    def _build_providers(self, request):
116
        '''
117
        :param pyramid.request.Request request:
118
        :rtype: :class:`dict`
119
        '''
120
        # determine targets
121
        providers = {}
122
        ids = request.params.get('providers.ids', None)
123
        if ids:
124
            ids = ids.split(',')
125
            providers['ids'] = ids
126
        subject = self.request.params.get('providers.subject', None)
127
        if subject:
128
            providers['subject'] = subject
129
        return providers
130
131 View Code Duplication
    @view_config(route_name='skosprovider.cs', request_method='GET')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
132
    def get_concepts(self):
133
        qb = QueryBuilder(self.request)
134
        query = qb()
135
        kwargs = {"language": qb.language, "providers": self._build_providers(self.request)}
136
        kwargs.update(self._get_sort_params())
137
        if qb.no_result:
138
            concepts = []
139
        else:
140
            concepts = self.skos_registry.find(query, **kwargs)
141
            # Flatten it all
142
            concepts = list(itertools.chain.from_iterable([c['concepts'] for c in concepts]))
143
144
        if qb.postprocess:
145
            concepts = self._postprocess_wildcards(concepts, qb.label)
146
147
        return self._page_results(concepts)
148
149 View Code Duplication
    @view_config(route_name='skosprovider.conceptscheme.cs', request_method='GET')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
150
    def get_conceptscheme_concepts(self):
151
        scheme_id = self.request.matchdict['scheme_id']
152
        provider = self.skos_registry.get_provider(scheme_id)
153
        if not provider:
154
            return HTTPNotFound()
155
        qb = QueryBuilder(self.request)
156
        query = qb()
157
        kwargs = {"language": qb.language}
158
        kwargs.update(self._get_sort_params())
159
        if qb.no_result:
160
            concepts = []
161
        else:
162
            concepts = provider.find(query, **kwargs)
163
164
        if qb.postprocess:
165
            concepts = self._postprocess_wildcards(concepts, qb.label)
166
167
        return self._page_results(concepts)
168
169
    def _postprocess_wildcards(self, concepts, label):
170
        # We need to refine results further
171
        if label.startswith('*') and label.endswith('*'):
172
            concepts = [c for c in concepts if label[1:-1] in c['label']]
173
        elif label.endswith('*'):
174
            concepts = [c for c in concepts if c['label'].startswith(label[0:-1])]
175
        elif label.startswith('*'):
176
            concepts = [c for c in concepts if c['label'].endswith(label[1:])]
177
        return concepts
178
179
    def _get_sort_params(self):
180
        sort = self.request.params.get('sort', None)
181
        # Result sorting
182
        if sort:
183
            sort_order = 'desc' if sort[0:1] == '-' else 'asc'
184
            sort = sort[1:] if sort[0:1] in ['-', '+'] else sort
185
            sort = sort.strip().lower()  # dojo store does not encode '+'
186
            return {"sort": sort, "sort_order": sort_order}
187
        return {}
188
189
    def _page_results(self, concepts):
190
        # Result paging
191
        paging_data = False
192
        if 'Range' in self.request.headers:
193
            paging_data = parse_range_header(self.request.headers['Range'])
194
        count = len(concepts)
195
        if not paging_data:
196
            paging_data = {
197
                'start': 0,
198
                'finish': count - 1 if count > 0 else 0,
199
                'number': count
200
            }
201
        cslice = concepts[paging_data['start']:paging_data['finish']+1]
202
        self.request.response.headers[ascii_native_('Content-Range')] = \
203
            ascii_native_('items %d-%d/%d' % (
204
                paging_data['start'], paging_data['finish'], count
205
            ))
206
        return cslice
207
208
    @view_config(route_name='skosprovider.c', request_method='GET')
209
    def get_concept(self):
210
        scheme_id = self.request.matchdict['scheme_id']
211
        concept_id = self.request.matchdict['c_id']
212
        provider = self.skos_registry.get_provider(scheme_id)
213
        if not provider:
214
            return HTTPNotFound()
215
        concept = provider.get_by_id(concept_id)
216
        if not concept:
217
            return HTTPNotFound()
218 View Code Duplication
        return concept
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
219
220
    @view_config(route_name='skosprovider.c.display_children', request_method='GET')
221
    def get_concept_display_children(self):
222
        scheme_id = self.request.matchdict['scheme_id']
223
        concept_id = self.request.matchdict['c_id']
224
        provider = self.skos_registry.get_provider(scheme_id)
225
        if not provider:
226
            return HTTPNotFound()
227
        language = self.request.params.get('language', self.request.locale_name)
228
        children = provider.get_children_display(concept_id, language=language)
229
        if children is False:
230 View Code Duplication
            return HTTPNotFound()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
231
        return children
232
233
    @view_config(route_name='skosprovider.c.expand', request_method='GET')
234
    def get_expand(self):
235
        scheme_id = self.request.matchdict['scheme_id']
236
        concept_id = self.request.matchdict['c_id']
237
        provider = self.skos_registry.get_provider(scheme_id)
238
        if not provider:
239
            return HTTPNotFound()
240
        expanded = provider.expand(concept_id)
241
        if not expanded:
242
            return HTTPNotFound()
243
        return expanded
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
244