Test Failed
Push — master ( 47aaa2...5ffdf1 )
by Daniel
02:25
created

CommandLineArgumentsHandling.fn_command_line_argument_digest()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 9

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nop 2
dl 10
loc 10
rs 9.95
c 0
b 0
f 0
1
"""
2
CommandLineArgumentsHandling - a command line arguments handling library
3
4
This library allows handling pre-configured arguments to be received from command line and use them
5
to call the main package functions
6
7
Potential changes to implement:
8
    argparse = Alternative command line option and argument parsing library.
9
    https://www.programcreek.com/python/example/748/argparse.ArgumentParser
10
"""
11
# standard Python packages
12
import getopt
13
import json
14
import os.path
15
import sys
16
# additional Python packages available from PyPi
17
import pandas as pd
18
# Custom class specific to this package
19
from BasicNeeds import BasicNeeds as ClassBN
20
from TableauHyperApiExtraLogic import TableauHyperApiExtraLogic as ClassTHAEL
21
22
23 View Code Duplication
class CommandLineArgumentsHandling:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
24
    cfg_dtls = {}
25
26
    def fn_assess_option(self, current_option, str_meaning, given_default_value):
27
        if self.cfg_dtls['options'][current_option]['default_value'] == given_default_value:
28
            str_feedback_parts = {
29
                'prefix': 'Fatal Error',
30
                'verdict': 'Expected -' + current_option + '|--'
31
                           + self.cfg_dtls['options'][current_option]['option_long']
32
                           + ' <'
33
                           + self.cfg_dtls['options'][current_option]['option_sample_value']
34
                           + '> but nothing of that sort has been seen...',
35
                'suffix': ':-('
36
            }
37
            ln = len(str_feedback_parts['verdict']) - len(str_feedback_parts['prefix'])
38
            ClassBN.fn_timestamped_print(ClassBN, str_feedback_parts['prefix'] + '_'*ln)
39
            print(str_feedback_parts['verdict'] + ' ' + str_feedback_parts['suffix'])
40
            sys.exit(2)
41
        ClassBN.fn_timestamped_print(ClassBN, str_meaning + ' is "' + given_default_value + '"')
42
43
    def fn_build_combined_options(self):
44
        str_combined_opts = ''
45
        for option_index, crt_opt in enumerate(self.cfg_dtls['options']):
46
            if crt_opt is not None:
47
                str_option_crt = '-' + crt_opt + '|--'\
48
                                 + self.cfg_dtls['options'][crt_opt]['option_long']
49
                if 'option_sample_value' in self.cfg_dtls['options'][crt_opt]:
50
                    str_option_crt += ' <'\
51
                                      + self.cfg_dtls['options'][crt_opt]['option_sample_value']\
52
                                      + '>'
53
                if self.cfg_dtls['options'][crt_opt]['option_type'] == 'optional':
54
                    str_combined_opts += ' [' + str_option_crt\
55
                                         + '|if omitted, default value will be considered: '\
56
                                         + str(self.cfg_dtls['options'][crt_opt]['default_value'])\
57
                                         + ']'
58
                else:
59
                    str_combined_opts += ' ' + str_option_crt
60
        return str_combined_opts
61
62
    def fn_build_long_options(self):
63
        str_opts = []
64
        for option_index, crt_lng_opt in enumerate(self.cfg_dtls['options']):
65
            if crt_lng_opt is not None:
66
                str_opts.append(option_index)
67
                str_opts[option_index] = self.cfg_dtls['options'][crt_lng_opt]['option_long'] + '='
68
        return str_opts
69
70
    def fn_build_short_options(self):
71
        str_short_options = 'h'
72
        for crt_short_opt in self.cfg_dtls['options']:
73
            if crt_short_opt is not None:
74
                if self.cfg_dtls['options'][crt_short_opt]['option_type'] == 'mandatory':
75
                    str_short_options += crt_short_opt + ':'
76
                else:
77
                    str_short_options += crt_short_opt
78
        return str_short_options
79
80
    def fn_command_line_argument_digest(self, help_feedback):
81
        try:
82
            opts, args = getopt.getopt(sys.argv[1:],
83
                                       self.fn_build_short_options(self),
84
                                       self.fn_build_long_options(self)
85
                                       )
86
            return opts
87
        except getopt.GetoptError:
88
            print(help_feedback)
89
            sys.exit(2)
90
91
    def fn_command_line_argument_interpretation(self):
92
        print('#' * 120)
93
        input_file = ''
94
        csv_field_separator = ','
95
        output_file = ''
96
        verbose = False
97
        self.fn_load_configuration(self)
98
        help_feedback = __file__ + self.fn_build_combined_options(self)
99
        opts = self.fn_command_line_argument_digest(self, help_feedback)
100
        for opt, arg in opts:
101
            if opt in ("-h", "--help"):
102
                print(help_feedback)
103
                sys.exit()
104
            elif opt in ("-i", "--input-file"):
105
                input_file = arg
106
            elif opt in ("-s", "--csv-field-separator"):
107
                csv_field_separator = arg
108
            elif opt in ("-o", "--output-file"):
109
                output_file = arg
110
            elif opt in ("-v", "--verbose"):
111
                verbose = True
112
            else:
113
                assert False, "Unhandled Option: " + arg
114
        self.fn_assess_option(self, 'i', 'Input file', input_file)
115
        ClassBN.fn_timestamped_print(ClassBN, 'CSV field separator is "'
116
                                     + csv_field_separator + '"')
117
        self.fn_assess_option(self, 'o', 'Output file', output_file)
118
        print('#' * 120)
119
        csv_content_df = pd.read_csv(filepath_or_buffer=input_file,
120
                                     delimiter=csv_field_separator,
121
                                     cache_dates=True,
122
                                     index_col=None,
123
                                     memory_map=True,
124
                                     encoding='utf-8')
125
        ClassTHAEL.fn_run_hyper_creation(ClassTHAEL,
126
                                         csv_content_df,
127
                                         self.cfg_dtls['data_types'],
128
                                         output_file, verbose)
129
130
    def fn_load_configuration(self):
131
        with open(os.path.dirname(__file__) + "/config.json", 'r') as json_file:
132
            self.cfg_dtls = json.load(json_file)
133