Passed
Push — master ( 4176a8...f1bc36 )
by torrua
01:46 queued 13s
created

app.api.views.get_statement()   A

Complexity

Conditions 5

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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