get_database_configuration()   F
last analyzed

Complexity

Conditions 22

Size

Total Lines 94
Code Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 58
dl 0
loc 94
rs 0
c 0
b 0
f 0
cc 22
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like db_sync_tool.utility.parser.get_database_configuration() 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
#!/usr/bin/env python3
2
# -*- coding: future_fstrings -*-
3
4
"""
5
Parser script
6
"""
7
8
import sys
9
from db_sync_tool.utility import mode, system, output, helper
10
from db_sync_tool.remote import client as remote_client
11
12
13
class Framework:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
14
    TYPO3 = 'TYPO3'
15
    SYMFONY = 'Symfony'
16
    DRUPAL = 'Drupal'
17
    WORDPRESS = 'Wordpress'
18
    LARAVEL = 'Laravel'
19
    MANUAL = 'Manual'
20
21
22
mapping = {
23
    Framework.TYPO3: [
24
        'LocalConfiguration.php',
25
        'AdditionalConfiguration.php'
26
    ],
27
    Framework.SYMFONY: [
28
        '.env',
29
        'parameters.yml'
30
    ],
31
    Framework.DRUPAL: [
32
        'settings.php'
33
    ],
34
    Framework.WORDPRESS: [
35
        'wp-config.php'
36
    ],
37
    Framework.LARAVEL: [
38
        '.env'
39
    ]
40
}
41
42
43
def get_database_configuration(client):
44
    """
45
    Getting database configuration of given client and defined sync base (framework type)
46
    :param client: String
47
    :return:
48
    """
49
    system.config['db'] = {}
50
51
    # check framework type
52
    _base = ''
53
54
    automatic_type_detection()
55
56
    if 'type' in system.config and (
57
            'path' in system.config[mode.Client.ORIGIN] or
58
            'path' in system.config[mode.Client.TARGET]
59
    ):
60
        _type = system.config['type'].lower()
61
        if _type == 'typo3':
62
            # TYPO3 sync base
63
            _base = Framework.TYPO3
64
        elif _type == 'symfony':
65
            # Symfony sync base
66
            _base = Framework.SYMFONY
67
        elif _type == 'drupal':
68
            # Drupal sync base
69
            _base = Framework.DRUPAL
70
        elif _type == 'wordpress':
71
            # Wordpress sync base
72
            _base = Framework.WORDPRESS
73
        elif _type == 'laravel':
74
            # Laravel sync base
75
            _base = Framework.LARAVEL
76
        else:
77
            sys.exit(
78
                output.message(
79
                    output.Subject.ERROR,
80
                    f'Framework type not supported: {_type}',
81
                    False
82
                )
83
            )
84
    elif 'db' in system.config['origin'] or 'db' in system.config['target']:
85
        _base = Framework.MANUAL
86
    else:
87
        sys.exit(
88
            output.message(
89
                output.Subject.ERROR,
90
                f'Missing framework type or database credentials',
0 ignored issues
show
introduced by
Using an f-string that does not have any interpolated variables
Loading history...
91
                False
92
            )
93
        )
94
95
    sys.path.append('../recipes')
96
    if _base == Framework.TYPO3:
97
        # Import TYPO3 parser
98
        from ..recipes import typo3
0 ignored issues
show
introduced by
Import outside toplevel (recipes.typo3)
Loading history...
99
        _parser = typo3
100
101
    elif _base == Framework.SYMFONY:
102
        # Import Symfony parser
103
        from ..recipes import symfony
0 ignored issues
show
introduced by
Import outside toplevel (recipes.symfony)
Loading history...
104
        _parser = symfony
105
106
    elif _base == Framework.DRUPAL:
107
        # Import Symfony parser
108
        from ..recipes import drupal
0 ignored issues
show
introduced by
Import outside toplevel (recipes.drupal)
Loading history...
109
        _parser = drupal
110
111
    elif _base == Framework.WORDPRESS:
112
        # Import Symfony parser
113
        from ..recipes import wordpress
0 ignored issues
show
introduced by
Import outside toplevel (recipes.wordpress)
Loading history...
114
        _parser = wordpress
115
116
    elif _base == Framework.LARAVEL:
117
        # Import Symfony parser
118
        from ..recipes import laravel
0 ignored issues
show
introduced by
Import outside toplevel (recipes.laravel)
Loading history...
119
        _parser = laravel
120
121
    if client == mode.Client.ORIGIN:
122
        output.message(
123
            output.Subject.INFO,
124
            'Sync base: ' + _base,
125
            True
126
        )
127
128
    if _base != Framework.MANUAL:
129
        load_parser(client, _parser)
0 ignored issues
show
introduced by
The variable _parser does not seem to be defined for all execution paths.
Loading history...
130
    else:
131
        if client == mode.Client.ORIGIN and mode.is_origin_remote():
132
            remote_client.load_ssh_client_origin()
133
        elif client == mode.Client.TARGET and mode.is_target_remote():
134
            remote_client.load_ssh_client_target()
135
136
    validate_database_credentials(client)
137
138
139
def load_parser(client, parser):
140
    """
141
    Loading parser and checking database configuration
142
    :param client:
143
    :param parser:
144
    :return:
145
    """
146
    _path = system.config[client]['path']
147
148
    output.message(
149
        output.host_to_subject(client),
150
        f'Checking database configuration {output.CliFormat.BLACK}{_path}{output.CliFormat.ENDC}',
151
        True
152
    )
153
    if client == mode.Client.ORIGIN:
154
        if mode.is_origin_remote():
155
            remote_client.load_ssh_client_origin()
156
        else:
157
            helper.run_script(client, 'before')
158
    else:
159
        if mode.is_target_remote():
160
            remote_client.load_ssh_client_target()
161
        else:
162
            helper.run_script(client, 'before')
163
164
    # Check only if database configuration is a file
165
    if not helper.check_file_exists(client, _path) and _path[-1] != '/':
166
        sys.exit(
167
            output.message(
168
                output.Subject.ERROR,
169
                f'Database configuration for {client} not found: {_path}',
170
                False
171
            )
172
        )
173
    parser.check_configuration(client)
174
175
176
def validate_database_credentials(client):
177
    """
178
    Validate the parsed database credentials
179
    :param client: String
180
    :return:
181
    """
182
    output.message(
183
        output.host_to_subject(client),
184
        'Validating database credentials',
185
        True
186
    )
187
    _db_credential_keys = ['name', 'host', 'password', 'user']
188
189
    for _key in _db_credential_keys:
190
        if _key not in system.config[client]['db']:
191
            sys.exit(
192
                output.message(
193
                    output.Subject.ERROR,
194
                    f'Missing database credential "{_key}" for {client} client',
195
                    False
196
                )
197
            )
198
        if system.config[client]['db'][_key] is None or system.config[client]['db'][_key] == '':
199
            sys.exit(
200
                output.message(
201
                    output.Subject.ERROR,
202
                    f'Missing database credential "{_key}" for {client} client',
203
                    False
204
                )
205
            )
206
        else:
207
            output.message(
208
                output.host_to_subject(client),
209
                f'Database credential "{_key}" valid',
210
                verbose_only=True
211
            )
212
213
214
def automatic_type_detection():
215
    """
216
    Detects the framework type by the provided path using the default mapping
217
    """
218
    if 'type' in system.config or 'db' in system.config['origin'] or 'db' in system.config[
219
        'target']:
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
220
        return
221
222
    type = None
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in type.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
223
    file = None
224
225
    for _client in [mode.Client.ORIGIN, mode.Client.TARGET]:
226
        if 'path' in system.config[_client]:
227
            file = helper.get_file_from_path(system.config[_client]['path'])
228
            for _key, _files in mapping.items():
229
                if file in _files:
230
                    type = _key
231
232
    if type:
233
        output.message(
234
            output.Subject.LOCAL,
235
            f'Automatic framework type detection '
236
            f'{output.CliFormat.BLACK}{file}{output.CliFormat.ENDC}',
237
            verbose_only=True
238
        )
239
        system.config['type'] = type
240