Passed
Push — master ( 5ef4cb...89c1da )
by Daniel
01:13
created

sources.db_extractor.BasicNeeds   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 122
dl 0
loc 156
rs 10
c 0
b 0
f 0
wmc 28

14 Methods

Rating   Name   Duplication   Size   Complexity  
A BasicNeeds.fn_optional_print() 0 3 2
A BasicNeeds.fn_validate_single_value() 0 6 2
A BasicNeeds.fn_validate_one_value() 0 20 4
A BasicNeeds.fn_final_message() 0 10 2
A BasicNeeds.fn_multi_line_string_to_single_line() 0 4 1
A BasicNeeds.fn_load_configuration() 0 3 1
A BasicNeeds.fn_timestamped_print() 0 4 1
A BasicNeeds.fn_check_inputs_script_specific() 0 9 2
A BasicNeeds.fn_get_file_content() 0 17 4
A BasicNeeds.fn_get_file_statistics() 0 20 2
A BasicNeeds.fn_open_file_and_get_content() 0 8 3
A BasicNeeds.fn_numbers_with_leading_zero() 0 6 2
A BasicNeeds.fn_store_file_statistics() 0 6 1
A BasicNeeds.fn_check_inputs() 0 5 1
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 script specific inputs
29
        if input_script == 'extractor':
30
            self.fn_validate_single_value(input_parameters.input_source_system_file,
31
                                          'file', 'source system file')
32
            self.fn_validate_single_value(input_parameters.input_credentials_file,
33
                                          'file', 'credentials file')
34
            self.fn_validate_single_value(input_parameters.input_extracting_sequence_file,
35
                                          'file', 'extracting sequence file')
36
37
    def fn_final_message(self, local_logger, log_file_name, performance_in_seconds):
38
        total_time_string = str(timedelta(seconds=performance_in_seconds))
39
        if log_file_name == 'None':
40
            self.fn_timestamped_print('Application finished, whole script took '
41
                                      + total_time_string)
42
        else:
43
            local_logger.info(f'Total execution time was ' + total_time_string)
44
            self.fn_timestamped_print('Application finished, '
45
                                      + 'for complete logged details please check '
46
                                      + log_file_name)
47
48
    def fn_get_file_content(self, in_file_handler, in_content_type):
49
        if in_content_type == 'json':
50
            try:
51
                json_interpreted_details = json.load(in_file_handler)
52
                self.fn_timestamped_print('I have interpreted JSON structure from given file')
53
                return json_interpreted_details
54
            except Exception as e:
55
                self.fn_timestamped_print('Error encountered when trying to interpret JSON')
56
                print(e)
57
        elif in_content_type == 'raw':
58
            raw_interpreted_file = in_file_handler.read()
59
            self.fn_timestamped_print('I have read file entire content')
60
            return raw_interpreted_file
61
        else:
62
            self.fn_timestamped_print('Unknown content type provided, '
63
                                      + 'expected either "json" or "raw" but got '
64
                                      + in_content_type)
65
66
    def fn_get_file_statistics(self, file_to_evaluate):
67
        try:
68
            file_sha512 = hashlib.sha512(open(file=file_to_evaluate, mode='r', encoding='utf-8')\
69
                                         .read().encode()).hexdigest()
70
        except UnicodeDecodeError:
71
            file_sha512 = hashlib.sha512(open(file=file_to_evaluate, mode='r', encoding='mbcs')\
72
                                         .read().encode()).hexdigest()
73
        file_dates = {
74
            'created': os.path.getctime(file_to_evaluate),
75
            'modified': os.path.getctime(file_to_evaluate),
76
        }
77
        file_info = {
78
            'date when created': date.strftime(datetime.fromtimestamp(file_dates['created']),
79
                                               '%Y-%m-%d %H:%M:%S.%f'),
80
            'date when last modified': date.strftime(datetime.fromtimestamp(file_dates['modified']),
81
                                                     '%Y-%m-%d %H:%M:%S.%f'),
82
            'size [bytes]': os.path.getsize(file_to_evaluate),
83
            'SHA512-Checksum': file_sha512,
84
        }
85
        return file_info
86
87
    def fn_load_configuration(self):
88
        relevant_file = os.path.join(os.path.dirname(__file__), 'config.json')
89
        self.cfg_dtls = self.fn_open_file_and_get_content(relevant_file)
90
91
    @staticmethod
92
    def fn_multi_line_string_to_single_line(input_string):
93
        return input_string.replace('\n', ' ').replace('\r', ' ')\
94
            .replace('  ', ' ', 5).replace('   ', ' ').strip()
95
96
    @staticmethod
97
    def fn_numbers_with_leading_zero(self, input_number_as_string, digits):
98
        final_number = input_number_as_string
99
        if len(input_number_as_string) < digits:
100
            final_number = '0' * (digits - len(input_number_as_string)) + input_number_as_string
101
        return final_number
102
103
    def fn_open_file_and_get_content(self, input_file, content_type='json'):
104
        if os.path.isfile(input_file):
105
            with open(input_file, 'r') as file_handler:
106
                self.fn_timestamped_print('I have opened file: ' + input_file)
107
                return self.fn_get_file_content(file_handler, content_type)
108
        else:
109
            self.fn_timestamped_print('Given file ' + input_file
110
                                      + ' does not exist, please check your inputs!')
111
112
    def fn_optional_print(self, boolean_variable, string_to_print):
113
        if boolean_variable:
114
            self.fn_timestamped_print(string_to_print)
115
116
    def fn_store_file_statistics(self, local_logger, timmer, file_name, file_meaning):
117
        timmer.start()
118
        local_logger.info(file_meaning + ' file "' + file_name
119
                          + '" has the following characteristics: '
120
                          + str(self.fn_get_file_statistics(file_name)))
121
        timmer.stop()
122
123
    @staticmethod
124
    def fn_timestamped_print(string_to_print):
125
        print(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f %Z")
126
              + ' - ' + string_to_print)
127
128
    @staticmethod
129
    def fn_validate_one_value(value_to_validate, validation_type, name_meaning):
130
        is_fatal_error = False
131
        message = ''
132
        if validation_type == 'file':
133
            is_fatal_error = (not os.path.isfile(value_to_validate))
134
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
135
                      + '" does not exist, please check your inputs!'
136
        elif validation_type == 'folder':
137
            is_fatal_error = (not os.path.isdir(value_to_validate))
138
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
139
                      + '" does not exist, please check your inputs!'
140
        elif validation_type == 'url':
141
            url_reg_expression = 'https?://(?:www)?(?:[\\w-]{2,255}(?:\\.\\w{2,66}){1,2})'
142
            is_fatal_error = (not re.match(url_reg_expression, value_to_validate))
143
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
144
                      + '" does not seem a valid one, please check your inputs!'
145
        return {
146
            'is_fatal_error': is_fatal_error,
147
            'message': message,
148
        }
149
150
    def fn_validate_single_value(self, value_to_validate, validation_type, name_meaning):
151
        validation_details = self.fn_validate_one_value(value_to_validate, validation_type,
152
                                                        name_meaning)
153
        if validation_details['is_fatal_error']:
154
            self.fn_timestamped_print(validation_details['message'])
155
            exit(1)
156