Subversion Repositories programming

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
358 ira 1
################################################################################
2
# The PAR2 Classifier Module
3
#
4
# Copyright 2006, Ira W. Snyder (devel@irasnyder.com)
5
# License: GNU General Public License v2 (or, at your option, any later version)
6
#
7
# This class makes a best guess as to what type of set we're dealing
8
# with here. Of course, this is just a _GUESS_, but I hope it's pretty good.
9
#
10
# Future Improvements
11
# 1. Read a config file to get a few extra customizable types, which
12
#    will let you run an arbitrary command on a set of files that contains
13
#    a certain type of file
14
################################################################################
15
 
16
import os, re, sys
17
 
18
class Par2Classifier (object):
19
 
20
    def __init__ (self, Par2Parser):
21
        # Give this function a valid Par2Parser that has already
22
        # been run on your set of files. It will be used to figure
23
        # out the types that are in this set
24
 
25
        # An enum of types
26
        ( self.UNKNOWN_TYPE,     # Represents a type that we don't know about yet
27
 
28
          self.S_SPLIT_000,      # Single file protected,    LXSplit, starting with .000
29
          self.M_SPLIT_000,      # Multiple files protected, LXSplit, starting with .000
30
          self.S_SPLIT_001,      # Single file protected,    LXSplit, starting with .001
31
          self.M_SPLIT_001,      # Multiple files protected, LXSplit, starting with .001
32
 
33
          self.S_PROT_SPLIT_000, # All .DDD files protected, LXSplit, starting with .000 (single set)
34
          self.M_PROT_SPLIT_000, # All .DDD files protected, LXSplit, starting with .000 (multiple sets)
35
          self.S_PROT_SPLIT_001, # All .DDD files protected, LXSplit, starting with .001 (single set)
36
          self.M_PROT_SPLIT_001, # All .DDD files protected, LXSplit, starting with .001 (multiple sets)
37
 
38
          self.S_RAR_OLD,        # Single set of rars,   Old style,   starting with .rDD
39
          self.M_RAR_OLD,        # Multiple set of rars, Old style,   starting with .rDD
40
          self.S_RAR_NEW,        # Single set of rars,   New style,   starting with .partDD.rar
41
          self.M_RAR_NEW,        # Multiple set of rars, New style,   starting with .partDD.rar
42
 
43
        ) = range (13)      # WARNING: If adding types, increment this number appropriately
44
 
45
 
46
        self.Par2Parser = Par2Parser
47
        self.type = self.UNKNOWN_TYPE
48
        self.heads = []
49
 
50
    def __get_type (self):
51
        # This will return one of the enums above corresponding to the
52
        # best guess about what type of set we're trying to extract.
53
        #
54
        # This information will be used later to decide how to repair
55
        # and possibly extract this set of files
56
 
57
        matches = self.__apply_regex ('^.*\.000$', self.Par2Parser.protected_files)
58
 
59
        # Check to see if we've got a M_PROT_SPLIT_000 set
60
        if len (matches) > 1:
61
            return      self.M_PROT_SPLIT_000
62
 
63
        # Check to see if we've got a S_PROT_SPLIT_000 set
64
        if len (matches) == 1:
65
            return      self.S_PROT_SPLIT_000
66
 
67
        matches = self.__apply_regex ('^.*\.001$', self.Par2Parser.protected_files)
68
 
69
        # Check to see if we've got a M_PROT_SPLIT_001 set
70
        if len (matches) > 1:
71
            return      self.M_PROT_SPLIT_001
72
 
73
        # Check if we've got a S_PROT_SPLIT_001 set
74
        if len (matches) == 1:
75
            return      self.S_PROT_SPLIT_001
76
 
77
        matches = self.__apply_regex ('^.*\.000$', self.Par2Parser.possible_files)
78
 
79
        # Check if we've got a M_SPLIT_000 set
80
        if len (matches) > 1 and len (self.Par2Parser.protected_files) > 1:
81
            return      self.M_SPLIT_000
82
 
83
        # Check if we've got a S_SPLIT_000 set
84
        if len (matches) == 1 and len (self.Par2Parser.protected_files) == 1:
85
            return      self.S_SPLIT_000
86
 
87
        matches = self.__apply_regex ('^.*\.001$', self.Par2Parser.possible_files)
88
 
89
        # Check if we've got a M_SPLIT_001 set
90
        if len (matches) > 1 and len (self.Par2Parser.protected_files) > 1:
91
            return      self.M_SPLIT_001
92
 
93
        # Check if we've got a S_SPLIT_001 set
94
        if len (matches) == 1 and len (self.Par2Parser.protected_files) == 1:
95
            return      self.S_SPLIT_001
96
 
97
        matches = self.__apply_regex ('^.*\.part0*1\.rar$',
98
                                      self.Par2Parser.protected_files,
99
                                      ignorecase=True)
100
 
101
        # Check if we've got a M_RAR_NEW set
102
        if len (matches) > 1:
103
            return      self.M_RAR_NEW
104
 
105
        # Check if we've got a S_RAR_NEW set
106
        if len (matches) == 1:
107
            return      self.S_RAR_NEW
108
 
109
        matches = self.__apply_regex ('^.*\.r00$',
110
                                      self.Par2Parser.protected_files,
111
                                      ignorecase=True)
112
 
113
        # Check if we've got a M_RAR_OLD set
114
        if len (matches) > 1:
115
            return      self.M_RAR_OLD
116
 
117
        # Check if we've got a S_RAR_OLD set
118
        if len (matches) == 1:
119
            return      self.S_RAR_OLD
120
 
121
        return self.UNKNOWN_TYPE
122
 
123
    def __apply_regex (self, regex_str, li, ignorecase=False, search=False):
124
        """Runs the regex given through the list, and returns matches
125
           a list of things that either match() (the default) or search()"""
126
 
127
        # Decide whether or not to use re.IGNORECASE
128
        if ignorecase:
129
            regex = re.compile (regex_str, re.IGNORECASE)
130
        else:
131
            regex = re.compile (regex_str)
132
 
133
        # Decide whether to use re.search() or re.match()
134
        if search:
135
            return [i for i in li if regex.search (i)]
136
        else:
137
            return [i for i in li if regex.match (i)]
138
 
139
    def __get_extractable_files (self):
140
        # Returns a list of all of the "head" extractable files
141
        # NOTE: an extractable file is a .000, .001, .r00, .rar
142
        #       or whatever else makes sense for this type of set
143
        #
144
        if self.type == self.S_SPLIT_000 or self.type == self.M_SPLIT_000:
145
            return self.__apply_regex ('^.*\.000$', self.Par2Parser.possible_files)
146
 
147
        if self.type == self.S_SPLIT_001 or self.type == self.M_SPLIT_001:
148
            return self.__apply_regex ('^.*\.001$', self.Par2Parser.possible_files)
149
 
150
        if self.type == self.S_PROT_SPLIT_000 or self.type == self.M_PROT_SPLIT_000:
151
            return self.__apply_regex ('^.*\.000$', self.Par2Parser.protected_files)
152
 
153
        if self.type == self.S_PROT_SPLIT_001 or self.type == self.M_PROT_SPLIT_001:
154
            return self.__apply_regex ('^.*\.001$', self.Par2Parser.protected_files)
155
 
156
        if self.type == self.S_RAR_OLD or self.type == self.M_RAR_OLD:
157
            return self.__apply_regex ('^.*\.r00$', self.Par2Parser.protected_files,
158
                    ignorecase=True)
159
 
160
        if self.type == self.S_RAR_NEW or self.type == self.M_RAR_NEW:
161
            return self.__apply_regex ('^.*\.part0*1\.rar$', self.Par2Parser.protected_files,
162
                    ignorecase=True)
163
 
164
        return [] # Return nothing by default (this covers UNKNOWN_TYPE)
165
 
166
    def do_magic (self):
167
        """Do all the magic to fill our fields by classifying files
168
           and finding the extractable heads"""
169
 
170
        self.type = self.__get_type ()
171
        self.heads = self.__get_extractable_files ()
172
 
173
 
174
if __name__ == '__main__':
175
    pass