1 """
2 Defines a class that handles directory scanning, and calls handler methods for matching files.
3 """
4 import logging
5 import os
6 import re
7 import string
8
9 import fileinfo
10
12 """
13 Class used to scan a whole directory tree and to determine which files
14 should be checked for license conformity based on include/exclude patterns.
15 """
16
17 __logger=logging.getLogger('lichk')
18
19
20 - def __init__(self,filechecker=None,includes=None,excludes=None):
21 """
22 Builds a new instance of FileScanner.
23
24 @param filechecker: an instance of L{FileChecker} that will be used to determine the file type from it's extensions. If C{None} a default FileChecker will be used.
25 @param includes: a list of regular expressions. If C{None}, a default list of includes will be built from the extensions managed by this instance's filechecker.
26 @param excludes: a list of regular expressions matching files that will not be examined for license conformity. If C{None}, a default list of excludes, read from the C{excludes.txt} file in the C{data} subdirectory of this module will be loaded.
27
28 """
29 if filechecker == None :
30 self.filechecker=fileinfo.FileChecker()
31 else :
32 self.filechecker=filechecker
33 if includes == None :
34 self.__logger.debug("Loading default includes.")
35 self.includes=self.__getDefaultIncludes()
36 else :
37 self.includes=includes
38 if excludes == None :
39 self.__logger.debug("Loading default excludes.")
40 self.excludes=self.__getDefaultExcludes()
41 else :
42 self.excludes=excludes
43
44
45 - def scan(self,topdir,handler=None) :
46 """
47 Performs a recursive scan from a directory and calls a handler function for all positive files.
48 To determine if a file is positive, the L{matches} function must return C{True}.
49
50 @param topdir: the name of the directory where the scanning should start.
51 @param handler: an instance of a handler object whose handle method will be called for each positive file.
52 @todo: Handler objects are still to be defined.
53
54 """
55 self.__logger.debug("Start scan of top-level directory : %s" % topdir)
56 for (dirpath,dirnames,filenames) in os.walk(topdir) :
57 for filename in filenames :
58 absfilename=os.path.join(dirpath,filename)
59 if self.matches(absfilename) :
60 self.__logger.debug("Match for %s" % absfilename)
61 fileinfo=self.filechecker.getFileInfo(absfilename)
62 if fileinfo is not None :
63 self.__logger.debug("About to handle file %s" % absfilename)
64 else :
65 self.__logger.debug("No info for file %s" % absfilename)
66 else :
67 self.__logger.debug("No match for %s" % absfilename)
68
69
71 """
72 Returns C{True} if a file matches a set of conditions, C{False} otherwise.
73
74 The conditions for the filename are :
75 1. It doesn't match any exclude pattern.
76 2. If the list of include patterns is not empty, it must match an include pattern.
77 3. If the list of include patterns is empty, the filename is considered a match.
78
79 @param filename: the name of the file to test.
80
81 @returns: C{True} for matching files, C{False} otherwise.
82 @rtype: Boolean
83
84
85 """
86 ismatch=True;
87 for exclude in self.excludes :
88 if re.match("^%s$"%exclude,filename) :
89 ismatch=False
90 break
91 if ismatch == True and len(self.includes)>0 :
92 ismatch=False
93 for include in self.includes :
94 if re.match("^%s$"%include,filename) :
95 ismatch=True
96 break
97 return ismatch
98
100 excludes=[]
101 fd=open(os.path.join(os.path.dirname(__file__),'data','excludes.txt'))
102 for line in fd :
103 line=line.strip()
104 if len(line) > 0 :
105 excludepatterns=re.split('\s+',line)
106 for pattern in excludepatterns :
107 excludes.append(pattern)
108 fd.close()
109 self.__logger.debug("List of exclude patterns : %s" % excludes)
110 return excludes
111
113 """
114 Returns the list of exclude patterns of this instance.
115
116 @return: a list of string with the regexps for the exclude patterns.
117 @rtype: [string,]
118 """
119 return self.excludes
120
122 """
123 Sets the list of exclude patterns for this instance.
124
125 @param excludes: a list of regexp-strings denoting the exclude patterns.
126 """
127 self.excludes=excludes
128
130 includes=[]
131 for extension in self.filechecker.getExtensions() :
132 includes.append(".*\.%s"%extension)
133 return includes
134
136 """
137 Returns the list of include patterns of this instance.
138
139 @return: a list of string with the regexps for the include patterns.
140 @rtype: [string,]
141 """
142 return self.includes
143
145 """
146 Sets the list of include patterns for this instance.
147
148 @param includes: a list of regexp-strings denoting the include patterns.
149 """
150 self.includes=includes
151