1 | """ |
---|
2 | This is the base file reader class all file readers should inherit from. |
---|
3 | All generic functionality required for a file loader/reader is built into this |
---|
4 | class |
---|
5 | """ |
---|
6 | |
---|
7 | import os |
---|
8 | import logging |
---|
9 | from abc import abstractmethod |
---|
10 | from loader_exceptions import NoKnownLoaderException, FileContentsException,\ |
---|
11 | DataReaderException |
---|
12 | from data_info import Data1D, Data2D, DataInfo, plottable_1D, plottable_2D,\ |
---|
13 | combine_data_info_with_plottable |
---|
14 | |
---|
15 | logger = logging.getLogger(__name__) |
---|
16 | |
---|
17 | |
---|
18 | class FileReader(object): |
---|
19 | # List of Data1D and Data2D objects to be sent back to data_loader |
---|
20 | output = [] |
---|
21 | # Current plottable1D/2D object being loaded in |
---|
22 | current_dataset = None |
---|
23 | # Current DataInfo objecct being loaded in |
---|
24 | current_datainfo = None |
---|
25 | # Wildcards |
---|
26 | type = ["Text files (*.txt)"] |
---|
27 | # List of allowed extensions |
---|
28 | ext = ['.txt'] |
---|
29 | # Bypass extension check and try to load anyway |
---|
30 | allow_all = False |
---|
31 | |
---|
32 | def read(self, filepath): |
---|
33 | """ |
---|
34 | Basic file reader |
---|
35 | |
---|
36 | :param filepath: The full or relative path to a file to be loaded |
---|
37 | """ |
---|
38 | if os.path.isfile(filepath): |
---|
39 | basename, extension = os.path.splitext(os.path.basename(filepath)) |
---|
40 | # If the file type is not allowed, return nothing |
---|
41 | if extension in self.ext or self.allow_all: |
---|
42 | # Try to load the file, but raise an error if unable to. |
---|
43 | try: |
---|
44 | input_f = open(filepath, 'rb') |
---|
45 | self.get_file_contents(input_f) |
---|
46 | except RuntimeError: |
---|
47 | pass |
---|
48 | except OSError as e: |
---|
49 | msg = "Unable to open file: {}\n".format(filepath) |
---|
50 | msg += e.message |
---|
51 | self.handle_error_message(msg) |
---|
52 | except Exception as e: |
---|
53 | self.handle_error_message(e.message) |
---|
54 | else: |
---|
55 | msg = "Unable to find file at: {}\n".format(filepath) |
---|
56 | msg += "Please check your file path and try again." |
---|
57 | self.handle_error_message(msg) |
---|
58 | # Return a list of parsed entries that dataloader can manage |
---|
59 | return self.output |
---|
60 | |
---|
61 | def handle_error_message(self, msg): |
---|
62 | """ |
---|
63 | Generic error handler to add an error to the current datainfo to |
---|
64 | propogate the error up the error chain. |
---|
65 | :param msg: Error message |
---|
66 | """ |
---|
67 | if isinstance(self.current_datainfo, DataInfo): |
---|
68 | self.current_datainfo.errors.append(msg) |
---|
69 | else: |
---|
70 | logger.warning(msg) |
---|
71 | |
---|
72 | def send_to_output(self): |
---|
73 | """ |
---|
74 | Helper that automatically combines the info and set and then appends it |
---|
75 | to output |
---|
76 | """ |
---|
77 | data_obj = combine_data_info_with_plottable(self.current_dataset, |
---|
78 | self.current_datainfo) |
---|
79 | self.output.append(data_obj) |
---|
80 | |
---|
81 | @abstractmethod |
---|
82 | def get_file_contents(self, contents): |
---|
83 | """ |
---|
84 | All reader classes that inherit from here should implement |
---|
85 | :param contents: |
---|
86 | """ |
---|
87 | pass |
---|