compile_pysrc.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import argparse
  2. import os
  3. import shutil
  4. import subprocess
  5. import sys
  6. import tarfile
  7. LIMIT = 6000
  8. def parse_args():
  9. parser = argparse.ArgumentParser()
  10. parser.add_argument('--input', required=True)
  11. parser.add_argument('--output', required=True)
  12. parser.add_argument('--rescompiler', required=True)
  13. subparsers = parser.add_subparsers(dest='mode')
  14. parser_py2 = subparsers.add_parser('py2')
  15. parser_py2.add_argument('--py_compile', required=True)
  16. parser_py2.add_argument('--python', required=True)
  17. parser_py3 = subparsers.add_parser('py3')
  18. parser_py3.add_argument('--pycc', required=True)
  19. return parser.parse_args()
  20. def call(cmd, cwd=None, env=None):
  21. return subprocess.check_output(cmd, stdin=None, stderr=subprocess.STDOUT, cwd=cwd, env=env)
  22. def iterate_py2_resource_params(py_files):
  23. for py in py_files:
  24. mod = py[:-3].replace('/', '.')
  25. key = '/py_modules/{}'.format(mod)
  26. yield py, key
  27. yield '-', 'resfs/src/{}={}'.format(key, py)
  28. yield '{}.yapyc'.format(py), '/py_code/{}'.format(mod)
  29. def iterate_py3_resource_params(py_files):
  30. for py in py_files:
  31. for ext in ('', '.yapyc3'):
  32. path = '{}{}'.format(py, ext)
  33. dest = 'py/{}'.format(path)
  34. key = 'resfs/file/{}'.format(dest)
  35. src = 'resfs/src/{}={}'.format(key, os.path.basename(path))
  36. yield '-', src
  37. yield path, key
  38. def main():
  39. args = parse_args()
  40. names = []
  41. with tarfile.open(args.input, 'r') as tar:
  42. names = tar.getnames()
  43. if sys.version_info >= (3, 12):
  44. tar.extractall(filter='data')
  45. else:
  46. tar.extractall()
  47. if args.mode == 'py3':
  48. pycc_cmd = [args.pycc]
  49. pycc_ext = '.yapyc3'
  50. iterate_resource_params = iterate_py3_resource_params
  51. else:
  52. pycc_cmd = [args.python, args.py_compile]
  53. pycc_ext = '.yapyc'
  54. iterate_resource_params = iterate_py2_resource_params
  55. py_files = sorted(names)
  56. for py in py_files:
  57. cmd = pycc_cmd + ['{}-'.format(os.path.basename(py)), py, '{}{}'.format(py, pycc_ext)]
  58. call(cmd)
  59. outputs = []
  60. cmd = [args.rescompiler, '{}.0'.format(args.output)]
  61. size = 0
  62. for path, key in iterate_resource_params(py_files):
  63. addendum = len(path) + len(key)
  64. if size + addendum > LIMIT and len(cmd) > 2:
  65. call(cmd)
  66. outputs.append(cmd[1])
  67. cmd[1] = '{}.{}'.format(args.output, len(outputs))
  68. cmd = cmd[0:2]
  69. size = 0
  70. cmd.extend([path, key])
  71. size += addendum
  72. if len(outputs) == 0:
  73. cmd[1] = args.output
  74. call(cmd)
  75. else:
  76. call(cmd)
  77. outputs.append(cmd[1])
  78. with open(args.output, 'w') as fout:
  79. for fname in outputs:
  80. with open(fname, 'r') as fin:
  81. shutil.copyfileobj(fin, fout)
  82. if __name__ == '__main__':
  83. main()