1 import sys, os, re, string, traceback, linda
2 from linda import root, outputobj, clparser
3 from linda.debug import dprint
4 from linda.parser.datavalidator import DataValidator
5 from linda.parser.debfilename import DebFilenameParser
6
8 """
9 The LindaChecker class is used by all checks, as they inheriate from it. It provides an initialisation method that sets up internal variables for the
10 check to use, such as:
11 - self.lab: The lab directory itself.
12 - self.err_dict: The error dictionary. There should be no need to access this directly.
13 - self.file: The check file itself.
14 - self.pkg_name: The package name being checked.
15 - self.version: The package version being checked.
16 - self.information: Contains information such as what files are contained in the package, and what 'file', 'objdump' and 'ldd' outputs for each of them. See the documentation on Collector for more information.
17
18 This method also provides a hook method called init, which means checks can also perform their own initisagtion.
19 """
20 - def __init__(self, lab, file, information):
21 self.lab = lab
22 self.err_dict = ErrDict()
23 self.file = file
24 debfn = DebFilenameParser(file)
25 self.pkg_name = debfn.package
26 self.version = debfn.version
27 self.information = information
28 if hasattr(self, 'init'):
29 getattr(self, 'init')()
30
32 """
33 This method is called whenever an error is encountered in a package. It adds
34 the tag and data to the internal err_dict object.
35 """
36 self.err_dict.add_error(tag, message)
37
39 """
40 This method checks if the version of a package is native. It returns false if
41 the package is not native, and returns true if it is.
42 """
43 if self.version.find('-') != -1:
44 return 0
45 else:
46 return 1
47
51
53 if self.errs.has_key(key):
54 self.errs[key].append(data)
55 else:
56 self.errs[key] = [data]
57
59 return self.errs[key]
60
62 del self.errs[key]
63
65 return self.errs.keys()
66
69
72 self.registry = {}
73 self.cur_file = ''
74
76 self.register_all('%s/checks' % root)
77 if not clparser['disable-local']:
78 for dir in (os.path.expanduser('~/.linda/checks'), \
79 '/etc/linda/checks'):
80 if os.path.isdir(dir):
81 self.register_all(dir)
82 dprint(_("Registry: %s") % self.registry, 3)
83 for type in ('source', 'binary', 'changes', 'udeb'):
84 for level in (1, 2):
85 if self.registry.has_key(type):
86 if self.registry[type].has_key(level):
87 for klass in self.registry[type][level]:
88 dprint(_("%s: %s") % (klass.__name__, \
89 klass.__file__), 4)
90
92 klass.__file__ = self.cur_file
93 for type in ('source', 'binary', 'changes', 'udeb'):
94 for level in (1, 2):
95 if hasattr(klass, 'check_%s_%s' % (type, level)):
96 self.registry.setdefault(type, {}).setdefault(level, []).\
97 append(klass)
98
100 if not os.path.isdir(dir):
101 return
102 for file in os.listdir(dir):
103 file = os.path.join(dir, file)
104 if file.endswith('.py'):
105 try:
106 self.cur_file = file
107 local_checks = {'_': __builtins__['_'], 'dprint': dprint, \
108 'DataValidator': DataValidator, 'os': os}
109 execfile(file, local_checks)
110 except StandardError:
111 print _("Failed to import %s.") % file
112 traceback.print_exc(file=sys.stdout)
113
114 - def apply(self, lab, file, information, level):
115 type = self.transliterate(os.path.splitext(file)[1][1:])
116 if not self.registry.has_key(type):
117 raise CheckRunningException('No checks registered with a type of %s.' % type)
118 if not self.registry[type].has_key(level):
119 raise CheckRunningException('No checks registered with a type of %s, and a level of %d.' % (type, level))
120 errdicts = {}
121 for klass in self.registry[type][level]:
122 dprint(_("Instantiating check: %s") % klass.__name__)
123 instance = klass(lab, file, information)
124 method = getattr(instance, 'check_' + type + '_' + repr(level))
125 if hasattr(outputobj, 'group_pre_print'):
126 outputobj.add_type(type, level)
127 outputobj.group_pre_print()
128 dprint(_("Calling %s.%s().") % (klass.__name__, method.__name__))
129 try:
130 method()
131 except KeyboardInterrupt:
132 print _("Check %s interrupted.") % klass.__name__
133 if not clparser['quiet'] and clparser['traceback']:
134 traceback.print_exc(file=sys.stdout)
135 except Exception:
136 if not clparser['quiet']:
137 excptype, value = sys.exc_info()[:2]
138 print _("Check %s failed. Exception %s thrown (%s).") % \
139 (klass.__name__, excptype.__name__, value)
140 if clparser['traceback']:
141 traceback.print_exc(file=sys.stdout)
142 check_dir = os.path.split(os.path.split(instance.__file__)[0])[0]
143 tmp_file = instance.__class__.__name__.lower()
144 if tmp_file.endswith('check'):
145 tmp_file = tmp_file[:-5]
146 data_file = os.path.join(check_dir, 'data', '%s.data' % tmp_file)
147 errdicts[data_file] = instance.err_dict
148 return errdicts
149
151 checks_to_run = clparser['checks'].replace(' ', '').split(',')
152 list_to_cull = []
153 for pkg_type in ('binary', 'source'):
154 for level in (1, 2):
155 for x in self.registry[pkg_type][level]:
156 class_str = x.__name__.lower()
157 not_found = 0
158 for y in checks_to_run:
159 if not re.match(y, class_str, re.IGNORECASE + \
160 re.DOTALL):
161 not_found += 1
162 if not_found == len(checks_to_run):
163 list_to_cull.append(x)
164 for x in list_to_cull:
165 self.registry[pkg_type][level].remove(x)
166 list_to_cull = []
167
169 for pkg_type in clparser['list-checks'][0]:
170 for level in clparser['list-checks'][1]:
171 if self.registry[pkg_type][level]:
172 print "%s checks (level %d): " % (pkg_type.title(), level)
173 for x in self.registry[pkg_type][level]:
174 if x.__doc__ is not None:
175 docstr = x.__doc__
176 else:
177 docstr = "No doc string."
178 print " - %s: %s" % (x.__name__, docstr)
179
181 mapping = {'deb': 'binary', 'dsc': 'source', 'changes': 'changes', \
182 'udeb': 'udeb'}
183 return mapping[type]
184
187