Completed
Pull Request — master (#2842)
by Edward
05:24
created

search_pack_index()   F

Complexity

Conditions 16

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 16
c 4
b 0
f 0
dl 0
loc 34
rs 2.7326

How to fix   Complexity   

Complexity

Complex classes like search_pack_index() 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
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import itertools
17
18
import requests
19
import six
20
from oslo_config import cfg
21
22
from st2common.persistence.pack import Pack
23
24
__all__ = [
25
    'get_pack_by_ref',
26
    'fetch_pack_index',
27
    'search_pack_index'
28
]
29
30
EXCLUDE_FIELDS = [
31
    "repo_url",
32
    "email"
33
]
34
35
SEARCH_PRIORITY = [
36
    "name",
37
    "keywords"
38
]
39
40
41
def get_pack_by_ref(pack_ref):
42
    """
43
    Retrieve PackDB by the provided reference.
44
    """
45
    pack_db = Pack.get_by_ref(pack_ref)
46
    return pack_db
47
48
49
def fetch_pack_index(index_url=None):
50
    """
51
    Fetch the pack indexes (either from the config or provided as an argument)
52
    and return the object.
53
    """
54
    if not index_url:
55
        index_urls = cfg.CONF.content.index_url
56
    elif isinstance(index_url, str):
57
        index_urls = [index_url]
58
    elif hasattr(index_url, '__iter__'):
59
        index_urls = index_url
60
    else:
61
        raise TypeError('"index_url" should either be a string or an iterable object.')
62
63
    result = {}
64
    for index_url in index_urls:
65
        try:
66
            result.update(requests.get(index_url).json())
67
        except ValueError:
68
            raise ValueError("Malformed index: %s does not contain valid JSON." % index_url)
69
    return result
70
71
72
def search_pack_index(query=None, pack=None, exclude=None, priority=None):
73
    """
74
    Search the pack index either by pack name or by query.
75
    Returns a pack object if the pack name is specified, otherwise returns
76
    a list of matches for a query.
77
    """
78
    if (not query and not pack) or (query and pack):
79
        raise ValueError("Either a query or a pack name must be specified.")
80
    if not exclude:
81
        exclude = EXCLUDE_FIELDS
82
    if not priority:
83
        priority = SEARCH_PRIORITY
84
85
    index = fetch_pack_index()
86
87
    if pack:
88
        return index.get(pack, None)
89
90
    matches = [[] for _ in xrange(len(priority) + 1)]
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'xrange'
Loading history...
91
    for pack in six.itervalues(index):
92
        for key, value in six.iteritems(pack):
93
            if not hasattr(value, '__contains__'):
94
                try:
95
                    value = str(value)
96
                except:
97
                    continue
98
            if key not in exclude and query in value:
99
                if key in priority:
100
                    matches[priority.index(key)].append(pack)
101
                else:
102
                    matches[-1].append(pack)
103
                break
104
105
    return list(itertools.chain.from_iterable(matches))
106