pycompile.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #!/usr/bin/env python
  2. '''Wrapper for python2 and python3 around compileall to raise exception
  3. when a python byte code generation failed.
  4. Inspired from:
  5. http://stackoverflow.com/questions/615632/how-to-detect-errors-from-compileall-compile-dir
  6. '''
  7. from __future__ import print_function
  8. import sys
  9. import py_compile
  10. import compileall
  11. import argparse
  12. def check_for_errors(comparison):
  13. '''Wrap comparison operator with code checking for PyCompileError.
  14. If PyCompileError was raised, re-raise it again to abort execution,
  15. otherwise perform comparison as expected.
  16. '''
  17. def operator(self, other):
  18. exc_type, value, traceback = sys.exc_info()
  19. if exc_type is not None and issubclass(exc_type,
  20. py_compile.PyCompileError):
  21. print("Cannot compile %s" % value.file)
  22. raise value
  23. return comparison(self, other)
  24. return operator
  25. class ReportProblem(int):
  26. '''Class that pretends to be an int() object but implements all of its
  27. comparison operators such that it'd detect being called in
  28. PyCompileError handling context and abort execution
  29. '''
  30. VALUE = 1
  31. def __new__(cls, *args, **kwargs):
  32. return int.__new__(cls, ReportProblem.VALUE, **kwargs)
  33. @check_for_errors
  34. def __lt__(self, other):
  35. return ReportProblem.VALUE < other
  36. @check_for_errors
  37. def __eq__(self, other):
  38. return ReportProblem.VALUE == other
  39. def __ge__(self, other):
  40. return not self < other
  41. def __gt__(self, other):
  42. return not self < other and not self == other
  43. def __ne__(self, other):
  44. return not self == other
  45. parser = argparse.ArgumentParser(description='Compile Python source files in a directory tree.')
  46. parser.add_argument("target", metavar='DIRECTORY',
  47. help='Directory to scan')
  48. parser.add_argument("--force", action='store_true',
  49. help="Force compilation even if alread compiled")
  50. args = parser.parse_args()
  51. compileall.compile_dir(args.target, force=args.force, quiet=ReportProblem())