checkpyc.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #! /usr/bin/env python3
  2. # Check that all ".pyc" files exist and are up-to-date
  3. # Uses module 'os'
  4. import sys
  5. import os
  6. from stat import ST_MTIME
  7. import importlib.util
  8. # PEP 3147 compatibility (PYC Repository Directories)
  9. cache_from_source = (importlib.util.cache_from_source if sys.implementation.cache_tag
  10. else lambda path: path + 'c')
  11. def main():
  12. if len(sys.argv) > 1:
  13. verbose = (sys.argv[1] == '-v')
  14. silent = (sys.argv[1] == '-s')
  15. else:
  16. verbose = silent = False
  17. MAGIC = importlib.util.MAGIC_NUMBER
  18. if not silent:
  19. print('Using MAGIC word', repr(MAGIC))
  20. for dirname in sys.path:
  21. try:
  22. names = os.listdir(dirname)
  23. except OSError:
  24. print('Cannot list directory', repr(dirname))
  25. continue
  26. if not silent:
  27. print('Checking ', repr(dirname), '...')
  28. for name in sorted(names):
  29. if name.endswith('.py'):
  30. name = os.path.join(dirname, name)
  31. try:
  32. st = os.stat(name)
  33. except OSError:
  34. print('Cannot stat', repr(name))
  35. continue
  36. if verbose:
  37. print('Check', repr(name), '...')
  38. name_c = cache_from_source(name)
  39. try:
  40. with open(name_c, 'rb') as f:
  41. magic_str = f.read(4)
  42. mtime_str = f.read(4)
  43. except IOError:
  44. print('Cannot open', repr(name_c))
  45. continue
  46. if magic_str != MAGIC:
  47. print('Bad MAGIC word in ".pyc" file', end=' ')
  48. print(repr(name_c))
  49. continue
  50. mtime = get_long(mtime_str)
  51. if mtime in {0, -1}:
  52. print('Bad ".pyc" file', repr(name_c))
  53. elif mtime != st[ST_MTIME]:
  54. print('Out-of-date ".pyc" file', end=' ')
  55. print(repr(name_c))
  56. def get_long(s):
  57. if len(s) != 4:
  58. return -1
  59. return s[0] + (s[1] << 8) + (s[2] << 16) + (s[3] << 24)
  60. if __name__ == '__main__':
  61. main()