pycompile.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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. def check_for_errors(comparison):
  12. '''Wrap comparison operator with code checking for PyCompileError.
  13. If PyCompileError was raised, re-raise it again to abort execution,
  14. otherwise perform comparison as expected.
  15. '''
  16. def operator(self, other):
  17. exc_type, value, traceback = sys.exc_info()
  18. if exc_type is not None and issubclass(exc_type,
  19. py_compile.PyCompileError):
  20. print("Cannot compile %s" % value.file)
  21. raise value
  22. return comparison(self, other)
  23. return operator
  24. class ReportProblem(int):
  25. '''Class that pretends to be an int() object but implements all of its
  26. comparison operators such that it'd detect being called in
  27. PyCompileError handling context and abort execution
  28. '''
  29. VALUE = 1
  30. def __new__(cls, *args, **kwargs):
  31. return int.__new__(cls, ReportProblem.VALUE, **kwargs)
  32. @check_for_errors
  33. def __lt__(self, other):
  34. return ReportProblem.VALUE < other
  35. @check_for_errors
  36. def __eq__(self, other):
  37. return ReportProblem.VALUE == other
  38. def __ge__(self, other):
  39. return not self < other
  40. def __gt__(self, other):
  41. return not self < other and not self == other
  42. def __ne__(self, other):
  43. return not self == other
  44. compileall.compile_dir(sys.argv[1], quiet=ReportProblem())