Passed
Push — master ( 26a5bf...afdbaf )
by Daniel
03:37
created

BasicNeeds.fn_numbers_with_leading_zero()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
"""
2
BasicNeeds - useful functions library
3
4
This library has functions useful to keep main logic short and simple
5
"""
6
# package to handle date and times
7
from datetime import date, datetime, timedelta
8
# package to use for checksum calculations (in this file)
9
import hashlib
10
# package to handle json files
11
import json
12
# package to handle files/folders and related metadata/operations
13
import os.path
14
# package regular expressions
15
import re
16
17
18
class BasicNeeds:
19
    cfg_dtls = {}
20
21
    def fn_check_inputs(self, input_parameters, input_script):
22
        # checking log folder first as there's all further messages will be stored
23
        self.fn_validate_single_value(os.path.dirname(input_parameters.output_log_file),
24
                                      'folder', 'log file')
25
        self.fn_check_inputs_script_specific(input_parameters, input_script)
26
27
    def fn_check_inputs_script_specific(self, input_parameters, input_script):
28
        # checking input file as the main point of whole logic revolves around it
29
        self.fn_validate_single_value(input_parameters.input_file,
30
                                      'file', 'input file')
31
        # checking script specific inputs
32
        if input_script == 'converter':
33
            self.fn_validate_single_value(os.path.dirname(input_parameters.output_file),
34
                                          'folder', 'output file')
35
        elif input_script == 'publish_data_source':
36
            self.fn_validate_single_value(input_parameters.input_credentials_file,
37
                                          'file', 'credentials file')
38
            self.fn_validate_single_value(input_parameters.tableau_server,
39
                                          'url', 'Tableau Server URL')
40
41
    def fn_final_message(self, local_logger, log_file_name, performance_in_seconds):
42
        total_time_string = str(timedelta(seconds=performance_in_seconds))
43
        if log_file_name == 'None':
44
            self.fn_timestamped_print('Application finished, whole script took '
45
                                      + total_time_string)
46
        else:
47
            local_logger.info(f'Total execution time was ' + total_time_string)
48
            self.fn_timestamped_print('Application finished, '
49
                                      + 'for complete logged details please check '
50
                                      + log_file_name)
51
52
    def fn_get_file_content(self, in_file_handler, in_content_type):
53
        if in_content_type == 'json':
54
            try:
55
                json_interpreted_details = json.load(in_file_handler)
56
                self.fn_timestamped_print('I have interpreted JSON structure from given file')
57
                return json_interpreted_details
58
            except Exception as e:
59
                self.fn_timestamped_print('Error encountered when trying to interpret JSON')
60
                print(e)
61
        elif in_content_type == 'raw':
62
            raw_interpreted_file = in_file_handler.read()
63
            self.fn_timestamped_print('I have read file entire content')
64
            return raw_interpreted_file
65
        else:
66
            self.fn_timestamped_print('Unknown content type provided, '
67
                                      + 'expected either "json" or "raw" but got '
68
                                      + in_content_type)
69
70
    @staticmethod
71
    def fn_get_file_statistics(file_to_evaluate):
72
        try:
73
            file_sha512 = hashlib.sha512(open(file=file_to_evaluate, mode='r', encoding='utf-8')\
74
                                         .read().encode()).hexdigest()
75
        except UnicodeDecodeError:
76
            file_sha512 = hashlib.sha512(open(file=file_to_evaluate, mode='r', encoding='mbcs')\
77
                                         .read().encode()).hexdigest()
78
        file_dates = {
79
            'created': os.path.getctime(file_to_evaluate),
80
            'modified': os.path.getctime(file_to_evaluate),
81
        }
82
        file_info = {
83
            'date when created': date.strftime(datetime.fromtimestamp(file_dates['created']),
84
                                               '%Y-%m-%d %H:%M:%S.%f'),
85
            'date when last modified': date.strftime(datetime.fromtimestamp(file_dates['modified']),
86
                                                     '%Y-%m-%d %H:%M:%S.%f'),
87
            'size [bytes]': os.path.getsize(file_to_evaluate),
88
            'SHA512-Checksum': file_sha512,
89
        }
90
        return file_info
91
92
    def fn_load_configuration(self):
93
        relevant_file = os.path.join(os.path.dirname(__file__), 'config.json')
94
        self.cfg_dtls = self.fn_open_file_and_get_content(relevant_file)
95
96
    @staticmethod
97
    def fn_multi_line_string_to_single_line(input_string):
98
        string_to_return = input_string.replace('\n', ' ').replace('\r', ' ')
99
        return re.sub(r'\s{2,100}', ' ', string_to_return).replace(' , ', ', ').strip()
100
101
    @staticmethod
102
    def fn_numbers_with_leading_zero(input_number_as_string, digits):
103
        final_number = input_number_as_string
104
        if len(input_number_as_string) < digits:
105
            final_number = '0' * (digits - len(input_number_as_string)) + input_number_as_string
106
        return final_number
107
108
    def fn_open_file_and_get_content(self, input_file, content_type='json'):
109
        if os.path.isfile(input_file):
110
            with open(input_file, 'r') as file_handler:
111
                self.fn_timestamped_print('I have opened file: ' + input_file)
112
                return self.fn_get_file_content(file_handler, content_type)
113
        else:
114
            self.fn_timestamped_print('Given file ' + input_file
115
                                      + ' does not exist, please check your inputs!')
116
117
    def fn_optional_print(self, boolean_variable, string_to_print):
118
        if boolean_variable:
119
            self.fn_timestamped_print(string_to_print)
120
121
    def fn_store_file_statistics(self, local_logger, timmer, file_name, file_meaning):
122
        timmer.start()
123
        local_logger.info(file_meaning + ' file "' + file_name
124
                          + '" has the following characteristics: '
125
                          + str(self.fn_get_file_statistics(file_name)))
126
        timmer.stop()
127
128
    @staticmethod
129
    def fn_timestamped_print(string_to_print):
130
        print(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f %Z")
131
              + ' - ' + string_to_print)
132
133
    @staticmethod
134
    def fn_validate_one_value(value_to_validate, validation_type, name_meaning):
135
        is_fatal_error = False
136
        message = ''
137
        if validation_type == 'file':
138
            is_fatal_error = (not os.path.isfile(value_to_validate))
139
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
140
                      + '" does not exist, please check your inputs!'
141
        elif validation_type == 'folder':
142
            is_fatal_error = (not os.path.isdir(value_to_validate))
143
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
144
                      + '" does not exist, please check your inputs!'
145
        elif validation_type == 'url':
146
            url_reg_expression = 'https?://(?:www)?(?:[\\w-]{2,255}(?:\\.\\w{2,66}){1,2})'
147
            is_fatal_error = (not re.match(url_reg_expression, value_to_validate))
148
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
149
                      + '" does not seem a valid one, please check your inputs!'
150
        return {
151
            'is_fatal_error': is_fatal_error,
152
            'message': message,
153
        }
154
155
    def fn_validate_single_value(self, value_to_validate, validation_type, name_meaning):
156
        validation_details = self.fn_validate_one_value(value_to_validate, validation_type,
157
                                                        name_meaning)
158
        if validation_details['is_fatal_error']:
159
            self.fn_timestamped_print(validation_details['message'])
160
            exit(1)
161