yfrake.openapi.generator._build_parameters()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nop 1
dl 0
loc 13
rs 9.95
c 0
b 0
f 0
1
# ================================================================================== #
2
#   generator.py - This file is part of the yfrake package.                          #
3
# ================================================================================== #
4
#                                                                                    #
5
#   MIT License                                                                      #
6
#                                                                                    #
7
#   Copyright (c) 2022 Mattias Aabmets                                               #
8
#                                                                                    #
9
#   Permission is hereby granted, free of charge, to any person obtaining a copy     #
10
#   of this software and associated documentation files (the "Software"), to deal    #
11
#   in the Software without restriction, including without limitation the rights     #
12
#   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell        #
13
#   copies of the Software, and to permit persons to whom the Software is            #
14
#   furnished to do so, subject to the following conditions:                         #
15
#                                                                                    #
16
#   The above copyright notice and this permission notice shall be included in all   #
17
#   copies or substantial portions of the Software.                                  #
18
#                                                                                    #
19
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR       #
20
#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,         #
21
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE      #
22
#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER           #
23
#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,    #
24
#   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE    #
25
#   SOFTWARE.                                                                        #
26
#                                                                                    #
27
# ================================================================================== #
28
from .components import components
29
from .modules import modules
30
from . import utils
31
import tomli
32
import yaml
33
import copy
34
35
36
yfrake_spec = {
37
    'openapi': '3.0.0',
38
    'info': {},
39
    'paths': {},
40
    'components': components
41
}
42
43
44
# ================================================================================== #
45
def generate_openapi_spec() -> None:
46
    """
47
    Poetry dependency manager uses this function to
48
    generate the 'yfrake_spec.yaml' file, before the
49
    package is published to the PyPI.
50
    """
51
    for module in modules:
52
        spec = {
53
            'summary': module.summary,
54
            'description': module.description,
55
            'parameters': _build_parameters(module),
56
            'responses': _build_responses()
57
        }
58
        endpoint = '/' + module.summary.lower().replace(' ', '_')
59
        yfrake_spec['paths'].update({endpoint: {'get': spec}})
60
        yfrake_spec['info'].update(_build_info())
61
62
    path = utils.get_spec_file_path()
63
    with open(path, 'w', encoding='utf-8') as file:
64
        file.write(yaml.dump(yfrake_spec))
65
66
    print('OpenAPI yaml file has been built.')
67
68
69
# ---------------------------------------------------------------------------------- #
70
def _build_parameters(module) -> list:
71
    """
72
    This function is responsible for building the
73
    parameters section of the documentation.
74
    """
75
    parameters = list()
76
    for param in module.parameters:
77
        param = copy.deepcopy(param)
78
        _type: object = param['schema']['type']
79
        _type: str = utils.get_openapi_datatype(_type)
80
        param['schema']['type'] = _type
81
        parameters.append(param)
82
    return parameters
83
84
85
# ---------------------------------------------------------------------------------- #
86
def _build_responses() -> dict:
87
    """
88
    This function is responsible for building the
89
    responses section of the documentation.
90
    """
91
    # Note: Currently, only the base response is being set for each endpoint,
92
    # because the recursive function required to build the response models
93
    # in the correct yaml format was taking too much time to design.
94
    # This deficiency is somewhat mitigated by the fact that the
95
    # swagger openapi server allows performing test queries, from
96
    # which the response model of each endpoint can be examined.
97
    return {
98
        '200': {
99
            'description': 'Successful Request',
100
            'content': {
101
                'application/json': {
102
                    'schema': {
103
                        '$ref': '#/components/schemas/BaseResponse'
104
                    }
105
                }
106
            }
107
        }
108
    }
109
110
111
# ---------------------------------------------------------------------------------- #
112
def _build_info() -> dict:
113
    """
114
    This function is responsible for building the
115
    information section of the documentation.
116
    """
117
    with open(utils.get_toml_file_path(), "rb") as file:
118
        data = tomli.load(file)
119
    data = data['tool']['poetry']
120
    contact = data['authors'][0].split()
121
    email = contact.pop().strip('<>')
122
    name = ' '.join(contact)
123
    url = data['urls']['Repository']
124
    return {
125
        'title': data['name'],
126
        'version': data['version'],
127
        'description': data['description'],
128
        'contact': {
129
            'name': name,
130
            'email': email,
131
            'url': url
132
        },
133
        'license': {
134
            'name': data['license'],
135
            'url': url + '/blob/main/LICENSE'
136
        }
137
    }
138