Passed
Push — master ( b5da8a...26a5bf )
by Daniel
01:41
created

BasicNeeds.fn_final_message()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nop 4
dl 0
loc 10
rs 9.95
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), 'folder',
24
                                      'log file')
25
        # checking input file as the main point of whole logic revolves around it
26
        self.fn_validate_single_value(input_parameters.input_file, 'file', 'input file')
27
        # checking script specific inputs
28
        if input_script == 'converter':
29
            self.fn_validate_single_value(os.path.dirname(input_parameters.output_file), 'folder',
30
                                          'output file')
31
        elif input_script == 'publish_data_source':
32
            self.fn_validate_single_value(input_parameters.input_credentials_file, 'file',
33
                                          'credentials file')
34
            self.fn_validate_single_value(input_parameters.tableau_server, 'url',
35
                                          'Tableau Server URL')
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
        # adding a special case data type
91
        self.cfg_dtls['data_types']['str'] = ''
92
93
    def fn_open_file_and_get_content(self, input_file, content_type='json'):
94
        if os.path.isfile(input_file):
95
            with open(input_file, 'r') as file_handler:
96
                self.fn_timestamped_print('I have opened file: ' + input_file)
97
                return self.fn_get_file_content(file_handler, content_type)
98
        else:
99
            self.fn_timestamped_print('Given file ' + input_file
100
                                      + ' does not exist, please check your inputs!')
101
102
    def fn_optional_print(self, boolean_variable, string_to_print):
103
        if boolean_variable:
104
            self.fn_timestamped_print(string_to_print)
105
106
    def fn_store_file_statistics(self, local_logger, timmer, file_name, file_meaning):
107
        timmer.start()
108
        local_logger.info(file_meaning + ' file "' + file_name
109
                          + '" has the following characteristics: '
110
                          + str(self.fn_get_file_statistics(file_name)))
111
        timmer.stop()
112
113
    @staticmethod
114
    def fn_timestamped_print(string_to_print):
115
        print(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S.%f %Z")
116
              + ' - ' + string_to_print)
117
118
    @staticmethod
119
    def fn_validate_one_value(value_to_validate, validation_type, name_meaning):
120
        is_fatal_error = False
121
        message = ''
122
        if validation_type == 'file':
123
            is_fatal_error = (not os.path.isfile(value_to_validate))
124
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
125
                      + '" does not exist, please check your inputs!'
126
        elif validation_type == 'folder':
127
            is_fatal_error = (not os.path.isdir(value_to_validate))
128
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
129
                      + '" does not exist, please check your inputs!'
130
        elif validation_type == 'url':
131
            url_reg_expression = 'https?://(?:www)?(?:[\\w-]{2,255}(?:\\.\\w{2,66}){1,2})'
132
            is_fatal_error = (not re.match(url_reg_expression, value_to_validate))
133
            message = 'Given ' + name_meaning + ' "' + value_to_validate \
134
                      + '" does not seem a valid one, please check your inputs!'
135
        return {
136
            'is_fatal_error': is_fatal_error,
137
            'message': message,
138
        }
139
140
    def fn_validate_single_value(self, value_to_validate, validation_type, name_meaning):
141
        validation_details = self.fn_validate_one_value(value_to_validate, validation_type,
142
                                                        name_meaning)
143
        if validation_details['is_fatal_error']:
144
            self.fn_timestamped_print(validation_details['message'])
145
            exit(1)
146