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

search_pack_index()   F

Complexity

Conditions 11

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 11
c 5
b 0
f 0
dl 0
loc 31
rs 3.1764

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.models.api.pack import PackAPI
23
from st2common.persistence.pack import Pack
24
25
__all__ = [
26
    'get_pack_by_ref',
27
    'fetch_pack_index',
28
    'get_pack_from_index',
29
    'search_pack_index'
30
]
31
32
EXCLUDE_FIELDS = [
33
    "repo_url",
34
    "email"
35
]
36
37
SEARCH_PRIORITY = [
38
    "name",
39
    "keywords"
40
]
41
42
43
def get_pack_by_ref(pack_ref):
44
    """
45
    Retrieve PackDB by the provided reference.
46
    """
47
    pack_db = Pack.get_by_ref(pack_ref)
48
    return pack_db
49
50
51
def fetch_pack_index(index_url=None):
52
    """
53
    Fetch the pack indexes (either from the config or provided as an argument)
54
    and return the object.
55
    """
56
    if not index_url:
57
        index_urls = cfg.CONF.content.index_url
58
    elif isinstance(index_url, str):
59
        index_urls = [index_url]
60
    elif hasattr(index_url, '__iter__'):
61
        index_urls = index_url
62
    else:
63
        raise TypeError('"index_url" should either be a string or an iterable object.')
64
65
    result = {}
66
    for index_url in index_urls:
67
        try:
68
            result.update(requests.get(index_url).json())
69
        except ValueError:
70
            raise ValueError("Malformed index: %s does not contain valid JSON." % index_url)
71
    return result
72
73
74
def get_pack_from_index(pack):
75
    """
76
    Search index by pack name.
77
    Returns a pack.
78
    """
79
    if not pack:
80
        raise ValueError("Pack name must be specified.")
81
82
    index = fetch_pack_index()
83
84
    return PackAPI(**index.get(pack))
85
86
87
def search_pack_index(query, exclude=None, priority=None):
88
    """
89
    Search the pack index by query.
90
    Returns a list of matches for a query.
91
    """
92
    if not query:
93
        raise ValueError("Query must be specified.")
94
95
    if not exclude:
96
        exclude = EXCLUDE_FIELDS
97
    if not priority:
98
        priority = SEARCH_PRIORITY
99
100
    index = fetch_pack_index()
101
102
    matches = [[] for _ in range(len(priority) + 1)]
103
    for pack_dict in six.itervalues(index):
104
        pack = PackAPI(**pack_dict)
105
106
        for key, value in six.iteritems(vars(pack)):
107
            if not hasattr(value, '__contains__'):
108
                value = str(value)
109
110
            if key not in exclude and query in value:
111
                if key in priority:
112
                    matches[priority.index(key)].append(pack)
113
                else:
114
                    matches[-1].append(pack)
115
                break
116
117
    return list(itertools.chain.from_iterable(matches))
118