Passed
Pull Request — main (#846)
by Osma
07:09 queued 03:50
created

annif.vocab.rules.kwargs_to_exclude_uris()   D

Complexity

Conditions 12

Size

Total Lines 35
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 24
nop 2
dl 0
loc 35
rs 4.8
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like annif.vocab.rules.kwargs_to_exclude_uris() 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
"""Support for exclude/include rules for subject vocabularies"""
2
3
from rdflib import RDF, Graph, URIRef
4
from rdflib.namespace import SKOS
5
6
from annif.exception import ConfigurationException
7
8
from .vocab import AnnifVocabulary
9
10
11
def uris_by_type(graph: Graph, type: str) -> list[str]:
12
    return [str(uri) for uri in graph.subjects(RDF.type, URIRef(type))]
13
14
15
def uris_by_scheme(graph: Graph, type: str) -> list[str]:
16
    return [str(uri) for uri in graph.subjects(SKOS.inScheme, URIRef(type))]
17
18
19
def uris_by_collection(graph: Graph, type: str) -> list[str]:
20
    return [str(uri) for uri in graph.objects(URIRef(type), SKOS.member)]
21
22
23
def add_uris(
24
    graph: Graph, uris_func: callable, uris_set: set[str], vals: list[str]
25
) -> None:
26
    for val in vals:
27
        uris_set.update(uris_func(graph, val))
28
29
30
def remove_uris(
31
    graph: Graph, uris_func: callable, uris_set: set[str], vals: list[str]
32
) -> None:
33
    for val in vals:
34
        for uri in uris_func(graph, val):
35
            uris_set.discard(uri)
36
37
38
def kwargs_to_exclude_uris(vocab: AnnifVocabulary, kwargs: dict[str, str]) -> set[str]:
39
    exclude_uris = set()
40
    actions = {
41
        "exclude": lambda vals: exclude_uris.update(
42
            vals if "*" not in vals else uris_by_type(vocab.as_graph(), SKOS.Concept)
43
        ),
44
        "exclude_type": lambda vals: add_uris(
45
            vocab.as_graph(), uris_by_type, exclude_uris, vals
46
        ),
47
        "exclude_scheme": lambda vals: add_uris(
48
            vocab.as_graph(), uris_by_scheme, exclude_uris, vals
49
        ),
50
        "exclude_collection": lambda vals: add_uris(
51
            vocab.as_graph(), uris_by_collection, exclude_uris, vals
52
        ),
53
        "include": lambda vals: exclude_uris.difference_update(vals),
54
        "include_type": lambda vals: remove_uris(
55
            vocab.as_graph(), uris_by_type, exclude_uris, vals
56
        ),
57
        "include_scheme": lambda vals: remove_uris(
58
            vocab.as_graph(), uris_by_scheme, exclude_uris, vals
59
        ),
60
        "include_collection": lambda vals: remove_uris(
61
            vocab.as_graph(), uris_by_collection, exclude_uris, vals
62
        ),
63
    }
64
65
    for key, value in kwargs.items():
66
        vals = value.split("|")
67
        if key in actions:
68
            actions[key](vals)
69
        else:
70
            raise ConfigurationException(f"unknown vocab keyword argument {key}")
71
72
    return exclude_uris
73