Passed
Push — master ( 8a736d...e50686 )
by torrua
01:19
created

app.api.views.separate_arguments()   A

Complexity

Conditions 3

Size

Total Lines 9
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 3
nop 2
1
import os
2
3
from flask import request, Blueprint, Response, json
4
from loglan_core.addons.key_selector import KeySelector
5
from loglan_core.addons.word_selector import WordSelector
6
from sqlalchemy import select
7
8
from app.api.schemas.author import blue_print_export as bp_author
9
from app.api.schemas.definition import blue_print_export as bp_definition
10
from app.api.schemas.event import blue_print_export as bp_event
11
from app.api.schemas.key import blue_print_export as bp_key
12
from app.api.schemas.setting import blue_print_export as bp_setting
13
from app.api.schemas.syllable import blue_print_export as bp_syllable
14
from app.api.schemas.type import blue_print_export as bp_type
15
from app.api.schemas.word import blue_print_export as bp_word
16
from app.engine import Session
17
18
API_PATH = os.getenv("API_PATH", "/api")
19
API_VERSION = os.getenv("API_VERSION", "/v1")
20
21
22
def universal_get(schema_full, schema_nested, model, many: bool = True):
23
    """
24
    Return entity from DB through GET request
25
    :param schema_full:
26
    :param schema_nested:
27
    :param model:
28
    :param many:
29
    :return:
30
    """
31
    args = {**request.args}
32
33
    detailed = True if str(args.pop("detailed", False)).lower() == "true" else False
34
    statement, skipped_args = get_statement(model, args)
35
36
    with Session() as app_session:
37
        result = app_session.execute(statement)
38
        model_entities = result.scalars().all() if many else [result.scalar()]
39
40
        count = len(model_entities)
41
        schema = schema_full if detailed else schema_nested
42
        data = schema.dump(model_entities, many=many)
43
44
    return Response(
45
        mimetype="application/json",
46
        response=json.dumps(
47
            {
48
                "result": True,
49
                "data": data,
50
                "count": count,
51
                "skipped_arguments": skipped_args,
52
            }
53
        ),
54
        status=200,
55
    )
56
57
58
def get_statement(model, args):
59
    event_id = args.pop("event_id", None)
60
    case_sensitive = True if str(args.pop("case_sensitive", False)).lower() == "true" else False
61
    model_args, skipped_args = separate_arguments(model, args)
62
    statement = filter_statement_by_event_id(model, event_id)
63
64
    if model_args:
65
        for attr, value in model_args.items():
66
            if str(value).isdigit():
67
                value = int(value)
68
                statement = statement.filter(getattr(model, attr) == value)
69
                continue
70
71
            value = value.replace("*", "%")
72
            name_attr = getattr(model, attr)
73
            name_filter = (
74
                name_attr.like(value) if case_sensitive else name_attr.ilike(value)
75
            )
76
77
            statement = statement.filter(name_filter)
78
79
    return statement, skipped_args
80
81
82
def filter_statement_by_event_id(model, event_id):
83
    api_section = request.path.strip("/").split("/")[-1]
84
    if event_id:
85
        if api_section == "words":
86
            return WordSelector().by_event(event_id=int(event_id))
87
        if api_section == "keys":
88
            return KeySelector().by_event(event_id=int(event_id))
89
    return select(model)
90
91
92
def separate_arguments(model, args):
93
    skipped_args = {}
94
    model_args = {}
95
    for parameter, value in args.items():
96
        if parameter in model.attributes_all():
97
            model_args[parameter] = value
98
        else:
99
            skipped_args[parameter] = value
100
    return model_args, skipped_args
101
102
103
def get_api_properties(entity):
104
    entity_name = entity.__tablename__.lower().removesuffix("s")
105
    section_name = f"/{entity_name}s"
106
    api_name = f"{entity_name}_api"
107
    blueprint = Blueprint(api_name, __name__)
108
    data = (blueprint, section_name)
109
    return blueprint, data
110
111
112
def create_blueprint_data(entity, schema_nested, schema_full):
113
    api_blueprint, api_data = get_api_properties(entity)
114
115
    @api_blueprint.route("/", methods=["GET"])
116
    def entity_get():
117
        """
118
        Get Entity by Entity's parameters Function
119
        """
120
        return universal_get(schema_full, schema_nested, entity)
121
122
    return api_data
123
124
125
dictionary_bp_data = [
126
    bp_author,
127
    bp_definition,
128
    bp_event,
129
    bp_key,
130
    bp_setting,
131
    bp_syllable,
132
    bp_type,
133
    bp_word,
134
]
135
136
dictionary_api_data = [create_blueprint_data(*data) for data in dictionary_bp_data]
137
138
blueprints = [
139
    {"blueprint": api[0], "url_prefix": f"{API_PATH}{API_VERSION}{api[1]}"}
140
    for api in dictionary_api_data
141
]
142