Use exceptions for error handling
[rarslave2.git] / RarslaveDetector.py
1 #!/usr/bin/env python
2 # vim: set ts=4 sts=4 sw=4 textwidth=92:
3
4 """
5 Class which runs each detector in the PAR2Set classes, and attempts
6 to run all matches on the current set.
7 """
8
9 __author__    = "Ira W. Snyder (devel@irasnyder.com)"
10 __copyright__ = "Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)"
11 __license__   = "GNU GPL v2 (or, at your option, any later version)"
12
13 #    RarslaveDetector.py
14 #
15 #    Copyright (C) 2006,2007  Ira W. Snyder (devel@irasnyder.com)
16 #
17 #    This program is free software; you can redistribute it and/or modify
18 #    it under the terms of the GNU General Public License as published by
19 #    the Free Software Foundation; either version 2 of the License, or
20 #    (at your option) any later version.
21 #
22 #    This program is distributed in the hope that it will be useful,
23 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
24 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 #    GNU General Public License for more details.
26 #
27 #    You should have received a copy of the GNU General Public License
28 #    along with this program; if not, write to the Free Software
29 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30
31 import rsutil.common
32
33 # PAR2Set-derived types
34 import PAR2Set.Join
35 import PAR2Set.ZIP
36 import PAR2Set.OldRAR
37 import PAR2Set.NewRAR
38 import PAR2Set.ExtractFirstOldRAR
39 import PAR2Set.ExtractFirstNewRAR
40 import PAR2Set.NoExtract
41
42 import logging
43
44 class RarslaveDetector (object):
45
46         """A class to detect the type of a set, and then run the appropriate class
47            on the set."""
48
49         # A tuple of tuples of the following type:
50         # (type_detection_function, type_working_class)
51         TYPES = (       (PAR2Set.Join.detector,   PAR2Set.Join.Join),
52                                 (PAR2Set.ZIP.detector,    PAR2Set.ZIP.ZIP),
53                                 (PAR2Set.OldRAR.detector, PAR2Set.OldRAR.OldRAR),
54                                 (PAR2Set.NewRAR.detector, PAR2Set.NewRAR.NewRAR),
55                                 (PAR2Set.ExtractFirstOldRAR.detector, PAR2Set.ExtractFirstOldRAR.ExtractFirstOldRAR),
56                                 (PAR2Set.ExtractFirstNewRAR.detector, PAR2Set.ExtractFirstNewRAR.ExtractFirstNewRAR),
57                                 (PAR2Set.NoExtract.detector, PAR2Set.NoExtract.NoExtract),
58                         )
59
60         def __init__ (self, dir, p2file):
61                 """Constructor
62
63                    dir -- the directory containing this set
64                    p2file -- a single PAR2 file from this set"""
65
66                 # The real "meat" of the class
67                 self.dir = dir
68                 self.p2file = p2file
69                 self.basename = rsutil.common.get_basename (p2file)
70
71                 # Find files that match by name only
72                 self.name_matched_files = rsutil.common.find_name_matches (self.dir, self.basename)
73
74                 # Find all par2 files for this set using name matches
75                 self.all_p2files = rsutil.common.find_par2_files (self.name_matched_files)
76
77                 # Try to get the protected files for this set
78                 self.prot_matched_files = rsutil.common.parse_all_par2 (self.dir, self.p2file, self.all_p2files)
79
80         def runMatchingTypes (self):
81                 """Run all matching PAR2Set types for which the detection function detects that
82                    the class is valid."""
83
84                 detected = False
85                 success = False
86
87                 for (detector, classname) in self.TYPES:
88                         if detector (self.name_matched_files, self.prot_matched_files):
89                                 # The detector matched, so we're up and running!
90
91                                 p2set = classname (self.dir, self.p2file)
92
93                                 detected = True
94                                 logging.debug ('Detected type: %s' % p2set)
95
96                                 # Try to have rarslave do it's thing
97                                 try:
98                                         # Have rarslave do it's thing
99                                         p2set.runAll ()
100
101                                         # It succeeded, exit the loop early
102                                         success = True
103                                         break
104                                 except (OSError, RuntimeError):
105                                         logging.error('Detected type (%s) failed for: %s' % (p2set, self.p2file))
106                                 except:
107                                         logging.error('Unknown exception occurred')
108                                         raise
109
110                 # Make sure we detected at least one valid type
111                 if not detected:
112                         logging.warning ('Unable to determine type: %s' % self.p2file)
113                         logging.debug ('The following information will help in writing a detector:')
114                         logging.debug ('name_matches: %s' % self.name_matched_files)
115                         logging.debug ('prot_matches: %s' % self.prot_matched_files)
116
117                 # Make sure that something worked
118                 if success == False:
119                         logging.critical('All types failed for: %s' % self.p2file)
120
121 def main ():
122         pass
123
124 if __name__ == '__main__':
125         main ()
126