]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/tool/checker.py
No longer building the C++ version of the OGL lib
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / checker.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2001-2004, MetaSlash Inc. All rights reserved.
4
5 """
6 Copyright notice from pychecker:
7
8 Copyright (c) 2000-2001, MetaSlash Inc.
9 All rights reserved.
10
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are
13 met:
14
15 - Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17
18 - Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the
21 distribution.
22
23 - Neither name of MetaSlash Inc. nor the names of contributors
24 may be used to endorse or promote products derived
25 from this software without specific prior written permission.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
31 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 """
39
40
41 """
42 Check python source code files for possible errors and print warnings
43
44 Contact Info:
45 http://pychecker.sourceforge.net/
46 pychecker-list@lists.sourceforge.net
47 """
48
49 import string
50 import types
51 import sys
52 import imp
53 import os
54 import glob
55 import traceback
56 import re
57 import wx
58 _ = wx.GetTranslation
59
60 # see __init__.py for meaning, this must match the version there
61 LOCAL_MAIN_VERSION = 1
62
63
64 def setupNamespace(path) :
65 # remove pychecker if it's the first component, it needs to be last
66 if sys.path[0][-9:] == 'pychecker' :
67 del sys.path[0]
68
69 # make sure pychecker is last in path, so we can import
70 checker_path = os.path.dirname(os.path.dirname(path))
71 if checker_path not in sys.path :
72 sys.path.append(checker_path)
73
74 if __name__ == '__main__' :
75 setupNamespace(sys.argv[0])
76
77 from pychecker import utils
78 from pychecker import printer
79 from pychecker import warn
80 from pychecker import OP
81 from pychecker import Config
82 from pychecker import function
83 from pychecker.Warning import Warning
84
85 # Globals for storing a dictionary of info about modules and classes
86 _allModules = {}
87 _cfg = None
88
89 # Constants
90 _DEFAULT_MODULE_TOKENS = ('__builtins__', '__doc__', '__file__', '__name__',
91 '__path__')
92 _DEFAULT_CLASS_TOKENS = ('__doc__', '__name__', '__module__')
93
94 _VERSION_MISMATCH_ERROR = '''
95 There seem to be two versions of PyChecker being used.
96 One is probably in python/site-packages, the other in a local directory.
97 If you want to run the local version, you must remove the version
98 from site-packages. Or you can install the current version
99 by doing python setup.py install.
100 '''
101
102 def cfg() :
103 return utils.cfg()
104
105 def _flattenList(list) :
106 "Returns a list which contains no lists"
107
108 new_list = []
109 for element in list :
110 if type(element) == types.ListType :
111 new_list.extend(_flattenList(element))
112 else :
113 new_list.append(element)
114
115 return new_list
116
117 def getModules(arg_list) :
118 "Returns a list of module names that can be imported"
119
120 global _output
121
122 new_arguments = []
123 for arg in arg_list :
124 # is this a wildcard filespec? (necessary for windows)
125 if '*' in arg or '?' in arg or '[' in arg :
126 arg = glob.glob(arg)
127 new_arguments.append(arg)
128
129 PY_SUFFIXES = ['.py']
130 PY_SUFFIX_LENS = [3]
131 if _cfg.quixote:
132 PY_SUFFIXES.append('.ptl')
133 PY_SUFFIX_LENS.append(4)
134
135 modules = []
136 for arg in _flattenList(new_arguments) :
137 fullpath = arg
138 # is it a .py file?
139 for suf, suflen in zip(PY_SUFFIXES, PY_SUFFIX_LENS):
140 if len(arg) > suflen and arg[-suflen:] == suf:
141 arg_dir = os.path.dirname(arg)
142 if arg_dir and not os.path.exists(arg) :
143 txt = _('File or pathname element does not exist: "%s"') % arg
144 _output.AddLines(txt)
145 continue
146
147 module_name = os.path.basename(arg)[:-suflen]
148 if arg_dir not in sys.path :
149 sys.path.insert(0, arg_dir)
150 arg = module_name
151 modules.append((arg, fullpath))
152
153 return modules
154
155 def _q_file(f):
156 # crude hack!!!
157 # imp.load_module requires a real file object, so we can't just
158 # fiddle def lines and yield them
159 import tempfile
160 fd, newfname = tempfile.mkstemp(suffix=".py", text=True)
161 newf = os.fdopen(fd, 'r+')
162 os.unlink(newfname)
163 for line in f:
164 mat = re.match(r'(\s*def\s+\w+\s*)\[(html|plain)\](.*)', line)
165 if mat is None:
166 newf.write(line)
167 else:
168 newf.write(mat.group(1)+mat.group(3)+'\n')
169 newf.seek(0)
170 return newf
171
172 def _q_find_module(p, path):
173 if not _cfg.quixote:
174 return imp.find_module(p, path)
175 else:
176 for direc in path:
177 try:
178 return imp.find_module(p, [direc])
179 except ImportError:
180 f = os.path.join(direc, p+".ptl")
181 if os.path.exists(f):
182 return _q_file(file(f)), f, ('.ptl', 'U', 1)
183
184 def _findModule(name) :
185 """Returns the result of an imp.find_module(), ie, (file, filename, smt)
186 name can be a module or a package name. It is *not* a filename."""
187
188 path = sys.path[:]
189 packages = string.split(name, '.')
190 for p in packages :
191 # smt = (suffix, mode, type)
192 file, filename, smt = _q_find_module(p, path)
193 if smt[-1] == imp.PKG_DIRECTORY :
194 try :
195 # package found - read path info from init file
196 m = imp.load_module(p, file, filename, smt)
197 finally :
198 if file is not None :
199 file.close()
200
201 # importing xml plays a trick, which replaces itself with _xmlplus
202 # both have subdirs w/same name, but different modules in them
203 # we need to choose the real (replaced) version
204 if m.__name__ != p :
205 try :
206 file, filename, smt = _q_find_module(m.__name__, path)
207 m = imp.load_module(p, file, filename, smt)
208 finally :
209 if file is not None :
210 file.close()
211
212 new_path = m.__path__
213 if type(new_path) == types.ListType :
214 new_path = filename
215 if new_path not in path :
216 path.insert(1, new_path)
217 elif smt[-1] != imp.PY_COMPILED:
218 if p is not packages[-1] :
219 if file is not None :
220 file.close()
221 raise ImportError, "No module named %s" % packages[-1]
222 return file, filename, smt
223
224 # in case we have been given a package to check
225 return file, filename, smt
226
227
228 class Variable :
229 "Class to hold all information about a variable"
230
231 def __init__(self, name, type):
232 self.name = name
233 self.type = type
234 self.value = None
235
236 def __str__(self) :
237 return self.name
238
239 __repr__ = utils.std_repr
240
241
242 def _filterDir(object, ignoreList) :
243 "Return a list of tokens (attributes) in a class, except for ignoreList"
244
245 tokens = dir(object)
246 for token in ignoreList :
247 if token in tokens :
248 tokens.remove(token)
249 return tokens
250
251 def _getClassTokens(c) :
252 return _filterDir(c, _DEFAULT_CLASS_TOKENS)
253
254
255 class Class :
256 "Class to hold all information about a class"
257
258 def __init__(self, name, module) :
259 self.name = name
260 self.classObject = getattr(module, name)
261
262 modname = getattr(self.classObject, '__module__', None)
263 if modname is None:
264 # hm, some ExtensionClasses don't have a __module__ attribute
265 # so try parsing the type output
266 typerepr = repr(type(self.classObject))
267 mo = re.match("^<type ['\"](.+)['\"]>$", typerepr)
268 if mo:
269 modname = ".".join(mo.group(1).split(".")[:-1])
270
271 self.module = sys.modules.get(modname)
272 if not self.module:
273 self.module = module
274
275 global _output
276 txt = _("warning: couldn't find real module for class %s (module name: %s)\n") % (self.classObject, modname)
277 _output.AddLines(txt)
278
279 self.ignoreAttrs = 0
280 self.methods = {}
281 self.members = { '__class__': types.ClassType,
282 '__doc__': types.StringType,
283 '__dict__': types.DictType, }
284 self.memberRefs = {}
285 self.statics = {}
286 self.lineNums = {}
287
288 def __str__(self) :
289 return self.name
290
291 __repr__ = utils.std_repr
292
293 def getFirstLine(self) :
294 "Return first line we can find in THIS class, not any base classes"
295
296 lineNums = []
297 classDir = dir(self.classObject)
298 for m in self.methods.values() :
299 if m != None and m.function.func_code.co_name in classDir:
300 lineNums.append(m.function.func_code.co_firstlineno)
301 if lineNums :
302 return min(lineNums)
303 return 0
304
305
306 def allBaseClasses(self, c = None) :
307 "Return a list of all base classes for this class and it's subclasses"
308
309 baseClasses = []
310 if c == None :
311 c = self.classObject
312 for base in c.__bases__ :
313 baseClasses = baseClasses + [ base ] + self.allBaseClasses(base)
314 return baseClasses
315
316 def __getMethodName(self, func_name, className = None) :
317 if func_name[0:2] == '__' and func_name[-2:] != '__' :
318 if className == None :
319 className = self.name
320 if className[0] != '_' :
321 className = '_' + className
322 func_name = className + func_name
323 return func_name
324
325 def addMethod(self, method, methodName = None) :
326 if type(method) == types.StringType :
327 self.methods[method] = None
328 else :
329 assert methodName is not None, "must supply methodName"
330 self.methods[methodName] = function.Function(method, 1)
331
332 def addMethods(self, classObject) :
333 for classToken in _getClassTokens(classObject) :
334 token = getattr(classObject, classToken, None)
335 if token is None:
336 continue
337
338 # Looks like a method. Need to code it this way to
339 # accommodate ExtensionClass and Python 2.2. Yecchh.
340 if (hasattr(token, "func_code") and
341 hasattr(token.func_code, "co_argcount")):
342 self.addMethod(token, token.__name__)
343
344 elif hasattr(token, '__get__') and \
345 not hasattr(token, '__set__') and \
346 type(token) is not types.ClassType :
347 self.addMethod(getattr(token, '__name__', classToken))
348 else :
349 self.members[classToken] = type(token)
350 self.memberRefs[classToken] = None
351
352 self.cleanupMemberRefs()
353 # add standard methods
354 for methodName in ('__class__',) :
355 self.addMethod(methodName, classObject.__name__)
356
357 def addMembers(self, classObject) :
358 if not cfg().onlyCheckInitForMembers :
359 for classToken in _getClassTokens(classObject) :
360 method = getattr(classObject, classToken, None)
361 if type(method) == types.MethodType :
362 self.addMembersFromMethod(method.im_func)
363 else:
364 try:
365 self.addMembersFromMethod(classObject.__init__.im_func)
366 except AttributeError:
367 pass
368
369 def addMembersFromMethod(self, method) :
370 if not hasattr(method, 'func_code') :
371 return
372
373 func_code, code, i, maxCode, extended_arg = OP.initFuncCode(method)
374 stack = []
375 while i < maxCode :
376 op, oparg, i, extended_arg = OP.getInfo(code, i, extended_arg)
377 if op >= OP.HAVE_ARGUMENT :
378 operand = OP.getOperand(op, func_code, oparg)
379 if OP.LOAD_CONST(op) or OP.LOAD_FAST(op) :
380 stack.append(operand)
381 elif OP.STORE_ATTR(op) :
382 if len(stack) > 0 :
383 if stack[-1] == cfg().methodArgName:
384 value = None
385 if len(stack) > 1 :
386 value = type(stack[-2])
387 self.members[operand] = value
388 self.memberRefs[operand] = None
389 stack = []
390
391 self.cleanupMemberRefs()
392
393 def cleanupMemberRefs(self) :
394 try :
395 del self.memberRefs[Config.CHECKER_VAR]
396 except KeyError :
397 pass
398
399 def abstractMethod(self, m):
400 """Return 1 if method is abstract, None if not
401 An abstract method always raises an exception.
402 """
403 if not self.methods.get(m, None):
404 return None
405 func_code, bytes, i, maxCode, extended_arg = \
406 OP.initFuncCode(self.methods[m].function)
407 # abstract if the first conditional is RAISE_VARARGS
408 while i < maxCode:
409 op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
410 if OP.RAISE_VARARGS(op):
411 return 1
412 if OP.conditional(op):
413 break
414 return None
415
416 def isAbstract(self):
417 """Return the method names that make a class abstract.
418 An abstract class has at least one abstract method."""
419 result = []
420 for m in self.methods.keys():
421 if self.abstractMethod(m):
422 result.append(m)
423 return result
424
425 def _getLineInFile(moduleName, linenum):
426 line = ''
427 file, filename, smt = _findModule(moduleName)
428 try:
429 lines = file.readlines()
430 line = string.rstrip(lines[linenum - 1])
431 except (IOError, IndexError):
432 pass
433 file.close()
434 return line
435
436 def importError(moduleName):
437 exc_type, exc_value, tb = sys.exc_info()
438
439 # First, try to get a nice-looking name for this exception type.
440 exc_name = getattr(exc_type, '__name__', None)
441 if not exc_name:
442 # either it's a string exception or a user-defined exception class
443 # show string or fully-qualified class name
444 exc_name = str(exc_type)
445
446 # Print a traceback, unless this is an ImportError. ImportError is
447 # presumably the most common import-time exception, so this saves
448 # the clutter of a traceback most of the time. Also, the locus of
449 # the error is usually irrelevant for ImportError, so the lack of
450 # traceback shouldn't be a problem.
451 if exc_type is SyntaxError:
452 # SyntaxErrors are special, we want to control how we format
453 # the output and make it consistent for all versions of Python
454 e = exc_value
455 msg = '%s (%s, line %d)' % (e.msg, e.filename, e.lineno)
456 line = _getLineInFile(moduleName, e.lineno)
457 offset = e.offset
458 if type(offset) is not types.IntType:
459 offset = 0
460 exc_value = '%s\n %s\n %s^' % (msg, line, ' ' * offset)
461 elif exc_type is not ImportError:
462 global _output
463 txt = _(" Caught exception importing module %s:\n") % moduleName
464 _output.AddLines(txt)
465
466 try:
467 tbinfo = traceback.extract_tb(tb)
468 except:
469 tbinfo = []
470 txt = _(" Unable to format traceback\n")
471 _output.AddLines(txt)
472 for filename, line, func, text in tbinfo[1:]:
473 txt = _(" File \"%s\", line %d") % (filename, line)
474 _output.AddLines(txt)
475 if func != "?":
476 txt = _(", in %s()") % func
477 _output.AddLines(txt)
478 _output.AddLines("\n")
479 if text:
480 txt = _(" %s\n") % text
481 _output.AddLines(txt)
482
483 # And finally print the exception type and value.
484 # Careful formatting exc_value -- can fail for some user exceptions
485 txt = " %s: " % exc_name
486 _output.AddLines(txt)
487 try:
488 txt = str(exc_value) + '\n'
489 _output.AddLines(txt)
490 except:
491 txt = _('**error formatting exception value**\n')
492 _output.AddLines(txt)
493
494
495 def _getPyFile(filename):
496 """Return the file and '.py' filename from a filename which could
497 end with .py, .pyc, or .pyo"""
498
499 if filename[-1] in 'oc' and filename[-4:-1] == '.py':
500 return filename[:-1]
501 return filename
502
503 class Module :
504 "Class to hold all information for a module"
505
506 def __init__(self, moduleName, check = 1, fullpath = None) :
507 self.moduleName = moduleName
508 self.variables = {}
509 self.functions = {}
510 self.classes = {}
511 self.modules = {}
512 self.moduleLineNums = {}
513 self.attributes = [ '__dict__' ]
514 self.main_code = None
515 self.module = None
516 self.check = check
517 self.fullpath = fullpath
518 _allModules[moduleName] = self
519
520 def __str__(self) :
521 return self.moduleName
522
523 __repr__ = utils.std_repr
524
525 def addVariable(self, var, varType) :
526 self.variables[var] = Variable(var, varType)
527
528 def addFunction(self, func) :
529 self.functions[func.__name__] = function.Function(func)
530
531 def __addAttributes(self, c, classObject) :
532 for base in classObject.__bases__ :
533 self.__addAttributes(c, base)
534 c.addMethods(classObject)
535 c.addMembers(classObject)
536
537 def addClass(self, name) :
538 self.classes[name] = c = Class(name, self.module)
539 try:
540 objName = str(c.classObject)
541 except TypeError:
542 # this can happen if there is a goofy __getattr__
543 c.ignoreAttrs = 1
544 else:
545 packages = string.split(objName, '.')
546 c.ignoreAttrs = packages[0] in cfg().blacklist
547 if not c.ignoreAttrs :
548 self.__addAttributes(c, c.classObject)
549
550 def addModule(self, name) :
551 module = _allModules.get(name, None)
552 if module is None :
553 self.modules[name] = module = Module(name, 0)
554 if imp.is_builtin(name) == 0 :
555 module.load()
556 else :
557 globalModule = globals().get(name)
558 if globalModule :
559 module.attributes.extend(dir(globalModule))
560 else :
561 self.modules[name] = module
562
563 def filename(self) :
564 try :
565 filename = self.module.__file__
566 except AttributeError :
567 filename = self.moduleName
568 return _getPyFile(filename)
569
570 def load(self, warnings = None):
571 try :
572 # there's no need to reload modules we already have
573 global _output, _statusDlg, _count
574 txt = _("Loading Module %s\n") % self.moduleName
575 _output.AddLines(txt)
576 _count += 1
577 if _count == 100:
578 _count = 95
579 _statusDlg.Update(_count, txt)
580
581 module = sys.modules.get(self.moduleName)
582 if module :
583 if not _allModules[self.moduleName].module :
584 return self._initModule(module)
585 return 1
586
587 return self._initModule(self.setupMainCode())
588 except (SystemExit, KeyboardInterrupt) :
589 exc_type, exc_value, exc_tb = sys.exc_info()
590 raise exc_type, exc_value
591 except SyntaxError, (message, (fileName, line, col, text)):
592 # ActiveGrid: added this for better feedback when module couldn't be loaded.
593 w = Warning(self.fullpath, line, _("Syntax Error: %s\n%s\n%s^error near here") % (message, text, ' '*(col-1)))
594 warnings.append(w)
595 return 0
596 except:
597 w = Warning(self.moduleName, 1, sys.exc_info()[0] + " NOT PROCESSED UNABLE TO IMPORT")
598 warnings.append(w)
599 importError(self.moduleName)
600 return 0
601
602 def initModule(self, module) :
603 if not self.module:
604 filename = _getPyFile(module.__file__)
605 if string.lower(filename[-3:]) == '.py':
606 try:
607 file = open(filename)
608 except IOError:
609 pass
610 else:
611 self._setupMainCode(file, filename, module)
612 return self._initModule(module)
613 return 1
614
615 def _initModule(self, module):
616 self.module = module
617 self.attributes = dir(self.module)
618
619 pychecker_attr = getattr(module, Config.CHECKER_VAR, None)
620 if pychecker_attr is not None :
621 utils.pushConfig()
622 utils.updateCheckerArgs(pychecker_attr, 'suppressions', 0, [])
623
624 for tokenName in _filterDir(self.module, _DEFAULT_MODULE_TOKENS) :
625 token = getattr(self.module, tokenName)
626 if isinstance(token, types.ModuleType) :
627 # get the real module name, tokenName could be an alias
628 self.addModule(token.__name__)
629 elif isinstance(token, types.FunctionType) :
630 self.addFunction(token)
631 elif isinstance(token, types.ClassType) or \
632 hasattr(token, '__bases__') :
633 self.addClass(tokenName)
634 else :
635 self.addVariable(tokenName, type(token))
636
637 if pychecker_attr is not None :
638 utils.popConfig()
639 return 1
640
641 def setupMainCode(self) :
642 file, filename, smt = _findModule(self.moduleName)
643 # FIXME: if the smt[-1] == imp.PKG_DIRECTORY : load __all__
644 module = imp.load_module(self.moduleName, file, filename, smt)
645 self._setupMainCode(file, filename, module)
646 return module
647
648 def _setupMainCode(self, file, filename, module):
649 try :
650 self.main_code = function.create_from_file(file, filename, module)
651 finally :
652 if file != None :
653 file.close()
654
655
656 def getAllModules() :
657 "Returns a list of all modules that should be checked."
658 modules = []
659 for module in _allModules.values() :
660 if module.check :
661 modules.append(module)
662 return modules
663
664 _BUILTIN_MODULE_ATTRS = { 'sys': [ 'ps1', 'ps2', 'tracebacklimit',
665 'exc_type', 'exc_value', 'exc_traceback',
666 'last_type', 'last_value', 'last_traceback',
667 ],
668 }
669
670 def fixupBuiltinModules(needs_init=0):
671 for moduleName in sys.builtin_module_names :
672 if needs_init:
673 _ = Module(moduleName, 0)
674 module = _allModules.get(moduleName, None)
675 if module is not None :
676 try :
677 m = imp.init_builtin(moduleName)
678 except ImportError :
679 pass
680 else :
681 extra_attrs = _BUILTIN_MODULE_ATTRS.get(moduleName, [])
682 module.attributes = [ '__dict__' ] + dir(m) + extra_attrs
683
684
685 def _printWarnings(warnings, stream=None):
686 if stream is None:
687 stream = sys.stdout
688
689 warnings.sort()
690 lastWarning = None
691 for warning in warnings :
692 if lastWarning != None :
693 # ignore duplicate warnings
694 if cmp(lastWarning, warning) == 0 :
695 continue
696 # print blank line between files
697 if lastWarning.file != warning.file :
698 global _output
699 _output.AddLines("\n")
700
701 lastWarning = warning
702 _output.AddLines(warning.format() + "\n")
703
704
705 def processFiles(files, cfg = None, pre_process_cb = None) :
706 # insert this here, so we find files in the local dir before std library
707 if sys.path[0] != '' :
708 sys.path.insert(0, '')
709
710 # ensure we have a config object, it's necessary
711 global _cfg
712 if cfg is not None :
713 _cfg = cfg
714 elif _cfg is None :
715 _cfg = Config.Config()
716
717 warnings = []
718 utils.initConfig(_cfg)
719 for moduleName, filename in getModules(files) :
720 if callable(pre_process_cb) :
721 pre_process_cb(moduleName)
722 module = Module(moduleName, fullpath = filename)
723
724 module.load(warnings)
725 utils.popConfig()
726 return warnings
727
728
729 def getWarnings(files, cfg = None, suppressions = None):
730 warnings = processFiles(files, cfg)
731 fixupBuiltinModules()
732 return warnings + warn.find(getAllModules(), _cfg, suppressions)
733
734
735 def _print_processing(name) :
736 if not _cfg.quiet :
737 global _output, _statusDlg, _count
738 txt = _("Processing %s...\n") % name
739 _output.AddLines(txt)
740 _count += 1
741 _statusDlg.Update(_count, txt)
742
743
744
745 def checkSyntax(filename, messageView):
746 """ Massively hacked version of main for ActiveGrid IDE integration """
747 global _cfg
748 _cfg, files, suppressions = Config.setupFromArgs([filename])
749 if not files :
750 return 0
751
752 global _output, _statusDlg, _count
753 _output = messageView
754 # wxBug: Need to show progress dialog box, or message window never gets updated until the method returns
755 _statusDlg = wx.ProgressDialog(_("Check Code"), _("Checking %s") % filename, maximum = 100, style = wx.PD_AUTO_HIDE | wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
756 _count = 0
757
758 # insert this here, so we find files in the local dir before std library
759 sys.path.insert(0, '')
760
761 importWarnings = processFiles(files, _cfg, _print_processing)
762 fixupBuiltinModules()
763 if _cfg.printParse :
764 for module in getAllModules() :
765 printer.module(module)
766
767 warnings = warn.find(getAllModules(), _cfg, suppressions)
768
769 _statusDlg.Update(100, _("Done"))
770 _statusDlg.Destroy()
771
772 if not _cfg.quiet :
773 _output.AddLines(_("\nWarnings and Errors...\n"))
774 if warnings or importWarnings :
775 _printWarnings(importWarnings + warnings)
776 return 1
777
778 if not _cfg.quiet :
779 _output.AddLines(_("No Syntax Errors"))
780 return 0
781
782 ##
783 ##
784 ##def main(argv) :
785 ## __pychecker__ = 'no-miximport'
786 ## import pychecker
787 ## if LOCAL_MAIN_VERSION != pychecker.MAIN_MODULE_VERSION :
788 ## sys.stderr.write(_VERSION_MISMATCH_ERROR)
789 ## sys.exit(100)
790 ##
791 ## # remove empty arguments
792 ## argv = filter(None, argv)
793 ##
794 ## # if the first arg starts with an @, read options from the file
795 ## # after the @ (this is mostly for windows)
796 ## if len(argv) >= 2 and argv[1][0] == '@':
797 ## # read data from the file
798 ## command_file = argv[1][1:]
799 ## try:
800 ## f = open(command_file, 'r')
801 ## command_line = f.read()
802 ## f.close()
803 ## except IOError, err:
804 ## sys.stderr.write("Unable to read commands from file: %s\n %s\n" % \
805 ## (command_file, err))
806 ## sys.exit(101)
807 ##
808 ## # convert to an argv list, keeping argv[0] and the files to process
809 ## argv = argv[:1] + string.split(command_line) + argv[2:]
810 ##
811 ## global _cfg
812 ## _cfg, files, suppressions = Config.setupFromArgs(argv[1:])
813 ## if not files :
814 ## return 0
815 ##
816 ## # insert this here, so we find files in the local dir before std library
817 ## sys.path.insert(0, '')
818 ##
819 ## importWarnings = processFiles(files, _cfg, _print_processing)
820 ## fixupBuiltinModules()
821 ## if _cfg.printParse :
822 ## for module in getAllModules() :
823 ## printer.module(module)
824 ##
825 ## warnings = warn.find(getAllModules(), _cfg, suppressions)
826 ## if not _cfg.quiet :
827 ## print "\nWarnings...\n"
828 ## if warnings or importWarnings :
829 ## _printWarnings(importWarnings + warnings)
830 ## return 1
831 ##
832 ## if not _cfg.quiet :
833 ## print "None"
834 ## return 0
835 ##
836 ##
837 ##if __name__ == '__main__' :
838 ## try :
839 ## sys.exit(main(sys.argv))
840 ## except Config.UsageError :
841 ## sys.exit(127)
842 ##
843 ##else :
844 ## _orig__import__ = None
845 ## _suppressions = None
846 ## _warnings_cache = {}
847 ##
848 ## def _get_unique_warnings(warnings):
849 ## for i in range(len(warnings)-1, -1, -1):
850 ## w = warnings[i].format()
851 ## if _warnings_cache.has_key(w):
852 ## del warnings[i]
853 ## else:
854 ## _warnings_cache[w] = 1
855 ## return warnings
856 ##
857 ## def __import__(name, globals=None, locals=None, fromlist=None):
858 ## if globals is None:
859 ## globals = {}
860 ## if locals is None:
861 ## locals = {}
862 ## if fromlist is None:
863 ## fromlist = []
864 ##
865 ## check = not sys.modules.has_key(name) and name[:10] != 'pychecker.'
866 ## pymodule = _orig__import__(name, globals, locals, fromlist)
867 ## if check :
868 ## try :
869 ## module = Module(pymodule.__name__)
870 ## if module.initModule(pymodule):
871 ## warnings = warn.find([module], _cfg, _suppressions)
872 ## _printWarnings(_get_unique_warnings(warnings))
873 ## else :
874 ## print 'Unable to load module', pymodule.__name__
875 ## except Exception:
876 ## name = getattr(pymodule, '__name__', str(pymodule))
877 ## importError(name)
878 ##
879 ## return pymodule
880 ##
881 ## def _init() :
882 ## global _cfg, _suppressions, _orig__import__
883 ##
884 ## args = string.split(os.environ.get('PYCHECKER', ''))
885 ## _cfg, files, _suppressions = Config.setupFromArgs(args)
886 ## utils.initConfig(_cfg)
887 ## fixupBuiltinModules(1)
888 ##
889 ## # keep the orig __import__ around so we can call it
890 ## import __builtin__
891 ## _orig__import__ = __builtin__.__import__
892 ## __builtin__.__import__ = __import__
893 ##
894 ## if not os.environ.get('PYCHECKER_DISABLED') :
895 ## _init()
896 ##