FileOperations.fn_get_file_dates_raw()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
"""
2
facilitates File Operations
3
"""
4
# package to handle date and times
5
from datetime import datetime
6
# package to add support for multi-language (i18n)
7
import gettext
8
# package to get ability to search file recursively
9
import glob
10
# package to use for checksum calculations (in this file)
11
import hashlib
12
# package to handle json files
13
import json
14
# package to facilitate operating system operations
15
import os
16
# package to facilitate os path manipulations
17
import pathlib
18
# package regular expressions
19
import re
20
21
22
class FileOperations:
23
    timestamp_format = '%Y-%m-%d %H:%M:%S.%f %Z'
24
    locale = None
25
26
    def __init__(self, in_language='en_US'):
27
        file_parts = os.path.normpath(os.path.abspath(__file__)).replace('\\', os.path.altsep)\
28
            .split(os.path.altsep)
29
        locale_domain = file_parts[(len(file_parts)-1)].replace('.py', '')
30
        locale_folder = os.path.normpath(os.path.join(
31
            os.path.join(os.path.altsep.join(file_parts[:-2]), 'project_locale'), locale_domain))
32
        self.locale = gettext.translation(locale_domain, localedir=locale_folder,
33
                                          languages=[in_language], fallback=True)
34
35
    def fn_build_file_list(self, local_logger, timer, given_input_file):
36
        timer.start()
37
        if re.search(r'(\*|\?)*', given_input_file):
38
            local_logger.debug(self.locale.gettext('File matching pattern identified'))
39
            parent_directory = os.path.dirname(given_input_file)
40
            # loading from a specific folder all files matching a given pattern into a file list
41
            relevant_files_list = self.fn_build_relevant_file_list(
42
                local_logger, parent_directory, given_input_file)
43
        else:
44
            local_logger.debug(self.locale.gettext('Specific file name provided'))
45
            relevant_files_list = [given_input_file]
46
        timer.stop()
47
        return relevant_files_list
48
49
    def fn_build_relevant_file_list(self, local_logger, in_folder, matching_pattern):
50
        folder_parts = pathlib.Path(matching_pattern).parts
51
        search_pattern = folder_parts[(len(folder_parts)-1)]
52
        local_logger.info(
53
            self.locale.gettext('Listing all files within {in_folder} folder '
54
                                + 'looking for {matching_pattern} as matching pattern')
55
                    .replace('{in_folder}', in_folder)
56
                    .replace('{matching_pattern}', search_pattern))
57
        list_files = []
58
        if os.path.isdir(in_folder):
59
            list_files = glob.glob(matching_pattern)
60
            file_counter = len(list_files)
61
            local_logger.info(self.locale.ngettext(
62
                '{files_counted} file from {in_folder} folder identified',
63
                '{files_counted} files from {in_folder} folder identified', file_counter)
64
                              .replace('{files_counted}', str(file_counter))
65
                              .replace('{in_folder}', in_folder))
66
        else:
67
            local_logger.error(self.locale.gettext('Folder {folder_name} does not exist')
68
                               .replace('{folder_name}', in_folder))
69
        return list_files
70
71
    def fn_get_file_content(self, in_file_handler, in_file_type):
72
        if in_file_type == 'json':
73
            try:
74
                json_interpreted_details = json.load(in_file_handler)
75
                print(datetime.utcnow().strftime(self.timestamp_format) + '- ' +
76
                      self.locale.gettext('JSON structure interpreted'))
77
                return json_interpreted_details
78
            except Exception as e:
79
                print(datetime.utcnow().strftime(self.timestamp_format) + '- ' +
80
                      self.locale.gettext('Error encountered when trying to interpret JSON'))
81
                print(e)
82
        elif in_file_type == 'raw':
83
            raw_interpreted_file = in_file_handler.read()
84
            print(datetime.utcnow().strftime(self.timestamp_format) + '- ' +
85
                  self.locale.gettext('Entire file content read'))
86
            return raw_interpreted_file
87
        else:
88
            print(datetime.utcnow().strftime(self.timestamp_format) + '- ' +
89
                  self.locale.gettext('Unknown file type provided, '
90
                                      + 'expected either "json" or "raw" but got {in_file_type}')
91
                  .replace('{in_file_type}', in_file_type))
92
93
    @staticmethod
94
    def fn_get_file_dates_raw(file_to_evaluate):
95
        return {
96
            'created': os.path.getctime(file_to_evaluate),
97
            'last modified': os.path.getmtime(file_to_evaluate),
98
        }
99
100
    @staticmethod
101
    def fn_get_file_dates(file_to_evaluate):
102
        return {
103
            'created': datetime.fromtimestamp(os.path.getctime(file_to_evaluate)),
104
            'last modified': datetime.fromtimestamp(os.path.getmtime(file_to_evaluate)),
105
        }
106
107
    def fn_get_file_simple_statistics(self, file_to_evaluate):
108
        file_date_time = self.fn_get_file_dates(file_to_evaluate)
109
        return {
110
            'date when created': datetime.strftime(file_date_time['created'],
111
                                                   self.timestamp_format).strip(),
112
            'date when last modified': datetime.strftime(file_date_time['last modified'],
113
                                                         self.timestamp_format).strip(),
114
            'size [bytes]': os.path.getsize(file_to_evaluate),
115
        }
116
117
    def fn_get_file_statistics(self, in_dict):
118
        file_statistics = self.fn_get_file_simple_statistics(in_dict['file name'])
119
        if 'checksum included' in in_dict and in_dict['checksum included'] == 'Yes':
120
            try:
121
                file_handler = open(file=in_dict['file name'], mode='r', encoding='mbcs')
122
            except UnicodeDecodeError:
123
                file_handler = open(file=in_dict['file name'], mode='r', encoding='utf-8')
124
            file_content = file_handler.read().encode('utf-8', 'xmlcharrefreplace')
125
            file_handler.close()
126
            file_statistics['MD5 Checksum'] = hashlib.md5(file_content).hexdigest()
127
            file_statistics['SHA1 Checksum'] = hashlib.sha1(file_content).hexdigest()
128
            file_statistics['SHA224 Checksum'] = hashlib.sha224(file_content).hexdigest()
129
            file_statistics['SHA256 Checksum'] = hashlib.sha256(file_content).hexdigest()
130
            file_statistics['SHA384 Checksum'] = hashlib.sha384(file_content).hexdigest()
131
            file_statistics['SHA512 Checksum'] = hashlib.sha512(file_content).hexdigest()
132
        return file_statistics
133
134
    def fn_get_file_datetime_verdict(self, local_logger, file_to_evaluate,
135
                                     created_or_modified, reference_datetime):
136
        implemented_choices = ['created', 'last modified']
137
        verdict = self.locale.gettext('unknown')
138
        file_date_time = self.fn_get_file_dates_raw(file_to_evaluate)
139
        if created_or_modified in implemented_choices:
140
            which_datetime = file_date_time.get(created_or_modified)
141
            verdict = self.locale.gettext('older')
142
            if which_datetime > reference_datetime:
143
                verdict = self.locale.gettext('newer')
144
            elif which_datetime == reference_datetime:
145
                verdict = self.locale.gettext('same')
146
            str_file_datetime = datetime.strftime(
147
                datetime.fromtimestamp(which_datetime), self.timestamp_format).strip()
148
            str_reference = datetime.strftime(
149
                datetime.fromtimestamp(reference_datetime), self.timestamp_format).strip()
150
            local_logger.debug(self.locale.gettext(
151
                    'File "{file_name}" which has the {created_or_modified} datetime '
152
                    + 'as "{file_datetime}" vs. "{reference_datetime}" '
153
                    + 'has a verdict = {verdict}')
154
                              .replace('{file_name}', str(file_to_evaluate))
155
                              .replace('{created_or_modified}',
156
                                       self.locale.gettext(created_or_modified))
157
                              .replace('{reference_datetime}', str_reference)
158
                              .replace('{file_datetime}', str_file_datetime)
159
                              .replace('{verdict}', verdict))
160
        else:
161
            local_logger.error(self.locale.gettext(
162
                    'Unknown file datetime choice, '
163
                    + 'expected is one of the following choices "{implemented_choices}" '
164
                    + 'but provided was "{created_or_modified}"...')
165
                               .replace('{implemented_choices}', '", "'.join(implemented_choices))
166
                               .replace('{created_or_modified}', created_or_modified))
167
        return verdict
168
169
    def fn_move_files(self, local_logger, timer, file_names, destination_folder):
170
        timer.start()
171
        resulted_files = []
172
        for current_file in file_names:
173
            source_folder = os.path.dirname(current_file)
174
            new_file_name = current_file.replace(source_folder, destination_folder)
175
            if os.path.isfile(new_file_name):
176
                local_logger.warning(self.locale.gettext('File {file_name} will be overwritten')
177
                                     .replace('{file_name}', current_file))
178
                os.replace(current_file, new_file_name)
179
                local_logger.info(self.locale.gettext(
180
                    'File {file_name} has just been been overwritten as {new_file_name}')
181
                                     .replace('{file_name}', current_file)
182
                                     .replace('{new_file_name}', current_file))
183
            else:
184
                local_logger.info(self.locale.gettext(
185
                    'File {file_name} will be renamed as {new_file_name}')
186
                                     .replace('{file_name}', current_file)
187
                                     .replace('{new_file_name}', current_file))
188
                os.rename(current_file, new_file_name)
189
                local_logger.info(self.locale.gettext(
190
                    'File {file_name} has just been renamed as {new_file_name}')
191
                                     .replace('{file_name}', current_file)
192
                                     .replace('{new_file_name}', current_file))
193
            resulted_files.append(str(new_file_name))
194
        timer.stop()
195
        return resulted_files
196
197
    def fn_open_file_and_get_content(self, input_file, content_type='json'):
198
        if os.path.isfile(input_file):
199
            with open(input_file, 'r') as file_handler:
200
                print(datetime.utcnow().strftime(self.timestamp_format) + '- ' +
201
                      self.locale.gettext('File {file_name} has just been opened')
202
                      .replace('{file_name}', str(input_file)))
203
                return self.fn_get_file_content(file_handler, content_type)
204
        else:
205
            print(datetime.utcnow().strftime(self.timestamp_format) + '- ' +
206
                  self.locale.gettext('File {file_name} does not exist')
207
                  .replace('{file_name}', str(input_file)))
208
209
    def fn_store_file_statistics(self, in_dict):
210
        in_dict['timer'].start()
211
        list_file_names = [in_dict['file list']]
212
        if type(in_dict['file list']) == list:
213
            list_file_names = in_dict['file list']
214
        for current_file_name in list_file_names:
215
            dt_when_last_modified = 'date when last modified'
216
            file_statistics = str(self.fn_get_file_statistics({
217
                'file name': current_file_name,
218
                'checksum included': in_dict['checksum included'],
219
            }))\
220
                .replace('date when created', self.locale.gettext('date when created')) \
221
                .replace(dt_when_last_modified, self.locale.gettext(dt_when_last_modified)) \
222
                .replace('size [bytes]', self.locale.gettext('size [bytes]')) \
223
                .replace('Checksum', self.locale.gettext('Checksum'))
224
            in_dict['logger'].info(self.locale.gettext(
225
                'File "{file_name}" has the following characteristics: {file_statistics}')
226
                                   .replace('{file_meaning}', in_dict['file meaning'])
227
                                   .replace('{file_name}', current_file_name)
228
                                   .replace('{file_statistics}', file_statistics))
229
        in_dict['timer'].stop()
230