Passed
Pull Request — main (#846)
by Osma
06:37 queued 03:27
created

annif.vocab.rules.kwargs_to_exclude_uris()   D

Complexity

Conditions 12

Size

Total Lines 45
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 34
nop 2
dl 0
loc 45
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
import annif
7
from annif.exception import ConfigurationException
8
9
from .vocab import AnnifVocabulary
10
11
logger = annif.logger
12
13
14
def uris_by_type(graph: Graph, type: str, action: str) -> list[str]:
15
    uris = [str(uri) for uri in graph.subjects(RDF.type, URIRef(type))]
16
    if not uris:
17
        logger.warning(f"{action}: no concepts found with type {type}")
18
    return uris
19
20
21
def uris_by_scheme(graph: Graph, scheme: str, action: str) -> list[str]:
22
    uris = [str(uri) for uri in graph.subjects(SKOS.inScheme, URIRef(scheme))]
23
    if not uris:
24
        logger.warning(f"{action}: no concepts found in scheme {scheme}")
25
    return uris
26
27
28
def uris_by_collection(graph: Graph, collection: str, action: str) -> list[str]:
29
    uris = [str(uri) for uri in graph.objects(URIRef(collection), SKOS.member)]
30
    if not uris:
31
        logger.warning(f"{action}: no concepts found in collection {collection}")
32
    return uris
33
34
35
def add_uris(
36
    graph: Graph, uris_func: callable, uris_set: set[str], vals: list[str], action: str
37
) -> None:
38
    for val in vals:
39
        uris_set.update(uris_func(graph, val, action))
40
41
42
def remove_uris(
43
    graph: Graph, uris_func: callable, uris_set: set[str], vals: list[str], action: str
44
) -> None:
45
    for val in vals:
46
        for uri in uris_func(graph, val, action):
47
            uris_set.discard(uri)
48
49
50
def kwargs_to_exclude_uris(vocab: AnnifVocabulary, kwargs: dict[str, str]) -> set[str]:
51
    exclude_uris = set()
52
    actions = {
53
        "exclude": lambda vals: exclude_uris.update(
54
            vals
55
            if "*" not in vals
56
            else uris_by_type(vocab.as_graph(), SKOS.Concept, "exclude")
57
        ),
58
        "exclude_type": lambda vals: add_uris(
59
            vocab.as_graph(), uris_by_type, exclude_uris, vals, "exclude_type"
60
        ),
61
        "exclude_scheme": lambda vals: add_uris(
62
            vocab.as_graph(), uris_by_scheme, exclude_uris, vals, "exclude_scheme"
63
        ),
64
        "exclude_collection": lambda vals: add_uris(
65
            vocab.as_graph(),
66
            uris_by_collection,
67
            exclude_uris,
68
            vals,
69
            "exclude_collection",
70
        ),
71
        "include": lambda vals: exclude_uris.difference_update(vals),
72
        "include_type": lambda vals: remove_uris(
73
            vocab.as_graph(), uris_by_type, exclude_uris, vals, "include_type"
74
        ),
75
        "include_scheme": lambda vals: remove_uris(
76
            vocab.as_graph(), uris_by_scheme, exclude_uris, vals, "include_scheme"
77
        ),
78
        "include_collection": lambda vals: remove_uris(
79
            vocab.as_graph(),
80
            uris_by_collection,
81
            exclude_uris,
82
            vals,
83
            "include_collection",
84
        ),
85
    }
86
87
    for key, value in kwargs.items():
88
        vals = value.split("|")
89
        if key in actions:
90
            actions[key](vals)
91
        else:
92
            raise ConfigurationException(f"unknown vocab keyword argument {key}")
93
94
    return exclude_uris
95