Passed
Push — master ( dd6867...c9baf7 )
by Konrad
01:30
created

file_sync_tool.__main__.build_config()   F

Complexity

Conditions 17

Size

Total Lines 59
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 39
nop 1
dl 0
loc 59
rs 1.8
c 0
b 0
f 0

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 file_sync_tool.__main__.build_config() 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
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
# -*- coding: future_fstrings -*-
3
4
import argparse, sys, os
0 ignored issues
show
introduced by
Multiple imports on one line (argparse, sys, os)
Loading history...
5
from collections import defaultdict
6
from db_sync_tool.utility import helper
7
# Workaround for ModuleNotFoundError
8
sys.path.append(os.getcwd())
9
from file_sync_tool import sync
0 ignored issues
show
introduced by
Import "from file_sync_tool import sync" should be placed at the top of the module
Loading history...
10
11
12
def main(args={}):
0 ignored issues
show
Bug Best Practice introduced by
The default value {} might cause unintended side-effects.

Objects as default values are only created once in Python and not on each invocation of the function. If the default object is modified, this modification is carried over to the next invocation of the method.

# Bad:
# If array_param is modified inside the function, the next invocation will
# receive the modified object.
def some_function(array_param=[]):
    # ...

# Better: Create an array on each invocation
def some_function(array_param=None):
    array_param = array_param or []
    # ...
Loading history...
13
    """
14
    Main entry point for the command line. Parse the arguments and call to the main process.
15
    :param args:
16
    :return:
17
    """
18
    args = get_arguments(args)
19
    config = build_config(args)
20
    sync.Sync(
21
        config_file=args.config_file,
22
        verbose=args.verbose,
23
        mute=args.mute,
24
        host_file=args.host_file,
25
        config=config
26
    )
27
28
29
def get_arguments(args):
30
    """
31
    Parses and returns script arguments
32
    :param args:
33
    :return:
34
    """
35
    parser = argparse.ArgumentParser(prog='file_sync_tool', description='A tool for automatic file synchronization from and to host systems.')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (142/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
36
    parser.add_argument('-f', '--config-file',
37
                        help='Path to configuration file',
38
                        required=False,
39
                        type=str)
40
    parser.add_argument('-v', '--verbose',
41
                        help='Enable extended console output',
42
                        required=False,
43
                        action='store_true')
44
    parser.add_argument('-m', '--mute',
45
                        help='Mute console output',
46
                        required=False,
47
                        action='store_true')
48
    parser.add_argument('-o', '--host-file',
49
                        help='Using an additional hosts file for merging hosts information with the configuration file',
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
50
                        required=False,
51
                        type=str)
52
    parser.add_argument('-th', '--target-host',
53
                        help='SSH host to target system',
54
                        required=False,
55
                        type=str)
56
    parser.add_argument('-tu', '--target-user',
57
                        help='SSH user for target system',
58
                        required=False,
59
                        type=str)
60
    parser.add_argument('-tpw', '--target-password',
61
                        help='SSH password for target system',
62
                        required=False,
63
                        type=str)
64
    parser.add_argument('-tk', '--target-key',
65
                        help='File path to SSH key for target system',
66
                        required=False,
67
                        type=str)
68
    parser.add_argument('-tpo', '--target-port',
69
                        help='SSH port for target system',
70
                        required=False,
71
                        type=int)
72
    parser.add_argument('-oh', '--origin-host',
73
                        help='SSH host to origin system',
74
                        required=False,
75
                        type=str)
76
    parser.add_argument('-ou', '--origin-user',
77
                        help='SSH user for origin system',
78
                        required=False,
79
                        type=str)
80
    parser.add_argument('-opw', '--origin-password',
81
                        help='SSH password for origin system',
82
                        required=False,
83
                        type=str)
84
    parser.add_argument('-ok', '--origin-key',
85
                        help='File path to SSH key for origin system',
86
                        required=False,
87
                        type=str)
88
    parser.add_argument('-opo', '--origin-port',
89
                        help='SSH port for origin system',
90
                        required=False,
91
                        type=int)
92
    parser.add_argument('-fo', '--files-origin',
93
                        help='File path for origin source of file sync',
94
                        required=False,
95
                        type=str)
96
    parser.add_argument('-ft', '--files-target',
97
                        help='File path for target destination of file sync',
98
                        required=False,
99
                        type=str)
100
    parser.add_argument('-fe', '--files-exclude',
101
                        help='Excludes for file sync',
102
                        required=False,
103
                        type=str)
104
    parser.add_argument('-fop', '--files-option',
105
                        help='Additional rsync options',
106
                        required=False,
107
                        type=str)
108
109
    return parser.parse_args(helper.dict_to_args(args))
110
111
112
def build_config(args):
113
    """
114
    Building an optional config
115
    :param args:
116
    :return:
117
    """
118
    config = defaultdict(dict)
119
    config['target'] = defaultdict(dict)
120
    config['origin'] = defaultdict(dict)
121
122
    if not args.target_host is None:
123
        config['target']['host'] = args.target_host
124
125
    if not args.target_user is None:
126
        config['target']['user'] = args.target_user
127
128
    if not args.target_password is None:
129
        config['target']['password'] = args.target_password
130
131
    if not args.target_key is None:
132
        config['target']['ssh_key'] = args.target_key
133
134
    if not args.target_port is None:
135
        config['target']['port'] = args.target_port
136
137
    if not args.origin_host is None:
138
        config['origin']['host'] = args.origin_host
139
140
    if not args.origin_user is None:
141
        config['origin']['user'] = args.origin_user
142
143
    if not args.origin_password is None:
144
        config['origin']['password'] = args.origin_password
145
146
    if not args.origin_key is None:
147
        config['origin']['ssh_key'] = args.origin_key
148
149
    if not args.origin_port is None:
150
        config['origin']['port'] = args.origin_port
151
152
    if not args.files_origin is None:
153
        if 'config' not in config['files']:
154
            config['files']['config'] = []
155
            config['files']['config'].append({})
156
        config['files']['config'][0]['origin'] = args.files_origin
157
158
    if not args.files_target is None:
159
        if 'config' not in config['files']:
160
            config['files']['config'] = []
161
            config['files']['config'].append({})
162
        config['files']['config'][0]['target'] = args.files_target
163
164
    if not args.files_exclude is None:
165
        config['files']['config'][0]['exclude'] = args.files_exclude.split(',')
166
167
    if not args.files_option is None:
168
        config['files']['option'] = args.files_option.split(',')
169
170
    return config
171
172
173
if __name__ == "__main__":
174
    main()
175