import sys
import os
from stat import ST_MTIME
import json as js
import subprocess as subp
import portalocker
get_fname = lambda full_name: os.path.split(full_name)[1]
def change_ext(f_name, ext):
return os.path.splitext(f_name)[0] + ext
def clear_file(f):
f.seek(0)
f.truncate()
class _log(object): # used to track changes to avoid parallel and extra recompilation
def __init__(self, f_name):
self.f_name=f_name
self.error={}
self.f_obj=None
self.log = None
def open_read(self):
f_name=self.f_name
try:
if os.path.isfile(f_name):
md='r+'
else:
md='w'
f = open(f_name, md)
self.f_obj = f
portalocker.lock(f, portalocker.LOCK_EX )
if md=='r+':
tmp= f.read()
self.log = (tmp and js.loads(tmp)) or {}
else:
self.log = {}
except :
self.error['open_read'] = sys.exc_info()[0]
return self.error['open_read'] is None
def save(self):
if not self.f_obj:
return
try:
clear_file(self.f_obj)
self.f_obj.write(js.dumps(self.log))
self.f_obj.close()
except :
self.error['save'] = sys.exc_info()[0]
def set_compile_time(self, pyj_fname):
if self.log is None:
return
f_stat = os.stat(pyj_fname)
self.log[ get_fname(pyj_fname) ] = f_stat[ST_MTIME]
def is_up_to_date(self, pyj_fname):
if self.log is None:
return False
f_stat = os.stat(pyj_fname)
return self.log[ get_fname(pyj_fname) ] == f_stat[ST_MTIME]
class rs_compiler(object):
def __init__(self, path_to_nodejs, path_to_RS):
self.node = path_to_nodejs
self.rs_engine = path_to_RS
self.last_ret_code = None
self.last_rslts = None
def _rs_compile(self, src, dst, log, force_compile=False):
ret = None
if force_compile or not log.is_up_to_date(src) or not os.path.isfile(dst):
ret = subp.call( [self.node, self.rs_engine, src, '-p', '-o', dst])
if ret==0:
log.set_compile_time(src)
self.last_ret_code = ret
return ret
def rs_compile_dir(self, src, dst, force_compile=False):
log = _log(os.path.join(dst, 'compile_inf.json' )) # 'compile_inf.json' - contains dict { 'file_1.pyj' : ST_MTIME, 'file_2.pyj' : ST_MTIME ... }
# it will be created/overwrited in the same dir as JS-files
if not log.open_read():
return {};
joinp = os.path.join
all_dir = os.listdir(src)
src_files = [f for f in all_dir if os.path.isfile(joinp(src, f)) and f[-4:]=='.pyj']
ret={}
for f in src_files:
src_f = joinp(src, f)
dst_f = joinp(dst, change_ext(f, '.js'))
self._rs_compile(src_f, dst_f, log, force_compile=force_compile)
rslt=dict(
ret_code = self.last_ret_code,
open_read = log.error.get('open_read', None),
log_save_err = log.error.get('save', None),
)
ret[f] = rslt
self.last_rslts=ret
log.save()
return ret
def main():
pass
if __name__ == '__main__':
main()