Skip to content

Commit

Permalink
Use native Python threading instead of sublime.set_timeout_async
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristopherDMack committed May 26, 2016
1 parent ba5c746 commit f372559
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,6 +3,7 @@ chase_the.log
test.sublime-snippet
*.pyc
*.log
*.lst

###SublimeText###

Expand Down
11 changes: 11 additions & 0 deletions SAS.sublime-build.direct-call
@@ -0,0 +1,11 @@
{
"target": "run_sas_program",
"selector": "source.sas",
"comment": "I wasn't able to get run_sas_program.py to work as expected. Amazingly long delays that seem to be related to the sublime.set_timeout_async call."
}

{
"path": "%LOCALAPPDATA%\\Microsoft\\AppV\\Client\\Integration\\518575B4-F54F-4F1D-87BB-13A27BE68B4C\\Root\\VFS\\ProgramFilesX64\\SASHome\\SASFoundation\\9.4\\",
"cmd": ["sas.exe", "-nosplash", "-sysin", "$file", "-log", "$file_path/$file_base_name.log", "-print", "$file_path/$file_base_name.lst", "-nologo", "-noovp", "-rsasuser", "-unbuflog"],
"selector": "source.sas"
}
142 changes: 82 additions & 60 deletions run_sas_program.py
@@ -1,21 +1,80 @@
# prototyping custom build command.
import sublime, sublime_plugin, subprocess, os, re
import threading

class RunSasProgramCommand(sublime_plugin.WindowCommand):
def check_log(self, log_path, err_regx):
if os.path.exists(log_path):
log = open(log_path)
log_contents = log.read()
log.close()
num_errs = len(re.findall(err_regx, log_contents))
self.window.open_file(log_path)
self.window.active_view().run_command('show_next_error')
return "\nLog file: " + log_path + "\n" + "Found " + str(num_errs) + " errors/warnings."
def run(self):
self.window.active_view().run_command('save')
prg_filename = self.window.active_view().file_name()
extension = os.path.splitext(prg_filename)[-1].lower()
if extension == '.sas':
log_filename = prg_filename[:-3] + 'log'
lst_filename = prg_filename[:-3] + 'lst'
lrn_filename = lst_filename + '.last.run'
wrkdir, prog = os.path.split(prg_filename)
if os.path.exists(lrn_filename):
os.remove(lrn_filename)
s = sublime.load_settings('SAS_Package.sublime-settings')
# Direct path to exe. Is there a better way to do this?
sas_path = s.get('sas-path', os.environ['LOCALAPPDATA'] + '\\Microsoft\\AppV\\Client\\Integration\\518575B4-F54F-4F1D-87BB-13A27BE68B4C\\Root\\VFS\\ProgramFilesX64\\SASHome\\SASFoundation\\9.4\\sas.exe')
sas_args = s.get('sas-args', ['-nologo', '-noovp'])
err_regx = s.get('err-regx', "(^(error|warning:)|uninitialized|[^l]remerge|Invalid data for)(?! (the .{4,15} product with which|your system is scheduled|will be expiring soon, and|this upcoming expiration.|information on your warning period.))")
s.set('sas-path', sas_path)
s.set('sas-args', sas_args)
s.set('err-regx', err_regx)
sublime.save_settings('SAS_Package.sublime-settings')
err_regx = re.compile(err_regx, re.MULTILINE + re.IGNORECASE)
if os.path.exists(sas_path):
call_args = [sas_path, '-sysin', prg_filename, '-log', log_filename, '-print', lst_filename, '-SASINITIALFOLDER', wrkdir] + sas_args
# print subprocess.list2cmdline(call_args)
threads = []
thread = RunSasThreaded(self, call_args, prg_filename, lst_filename, log_filename, err_regx, sas_path)
threads.append(thread)
thread.start()
self.handle_threads(threads)
else:
sublime.message_dialog("Problem--could not find sas.exe at " + sas_path + ". Please update the sas-path setting in SAS_Package.sublime-settings in the User package folder.")
else:
return "PROBLEM!--could not find log file " + log_path + "!"
sublime.message_dialog('Sorry--this only works with .sas files.')

# Loop through list of threads and look for those
# no longer running
def handle_threads(self, threads):
next_threads = []
for thread in threads:
if thread.is_alive():
next_threads.append(thread)
continue
if thread.result == False:
continue
threads = next_threads

def run_calc(self):
# sublime.message_dialog("boobies!")
subprocess.call('calc.exe')
class RunSasThreaded(threading.Thread):
def __init__(self, window_reference, call_args, prg_filename, lst_filename, log_filename, err_regx, sas_path):
self.call_args = call_args
self.window_reference = window_reference
self.prg_filename = prg_filename
self.lst_filename = lst_filename
self.log_filename = log_filename
self.err_regx = err_regx
self.sas_path = sas_path
self.result = None
threading.Thread.__init__(self)

def run(self):
subprocess.call(self.call_args)
sublime.status_message("Finished running " + self.prg_filename)
if os.path.exists(self.lst_filename):
self.window_reference.window.open_file(self.lst_filename)
if os.path.exists(self.log_filename):
res = "Finished!\n"
for l in self.find_logs(self.log_filename):
res += self.check_log(l, self.err_regx)
sublime.message_dialog(res)
else:
sublime.message_dialog("Problem! Did not find the expected log file (" + self.log_filename + ").")
# print sas_path + " exists?: " + str(os.path.exists(sas_path))
# sublime.message_dialog("Pretend I ran " + sas_path)

def find_logs(self, main_logfile):
# Searches the main log for evidence of other, PROC PRINTTO-spawned logs and returns an array of file paths
Expand Down Expand Up @@ -59,51 +118,14 @@ def find_logs(self, main_logfile):
ret.append(corrected_path)
return ret

def shell_out_to_sas(self, call_args, prg_filename, lst_filename, log_filename, err_regx, sas_path):
subprocess.call(call_args)
sublime.status_message("Finished running " + prg_filename)
if os.path.exists(lst_filename):
self.window.open_file(lst_filename)
if os.path.exists(log_filename):
res = "Finished!\n"
for l in self.find_logs(log_filename):
res += self.check_log(l, err_regx)
sublime.message_dialog(res)
else:
sublime.message_dialog("Problem! Did not find the expected log file (" + log_filename + ").")
# print sas_path + " exists?: " + str(os.path.exists(sas_path))
# sublime.message_dialog("Pretend I ran " + sas_path)
# self.window.open_file(r'C:\Users\Roy\AppData\Roaming\Sublime Text 3\Packages\SAS\notes.txt')



def run(self):
self.window.active_view().run_command('save')
prg_filename = self.window.active_view().file_name()
extension = os.path.splitext(prg_filename)[-1].lower()
if extension == '.sas':
log_filename = prg_filename[:-3] + 'log'
lst_filename = prg_filename[:-3] + 'lst'
lrn_filename = lst_filename + '.last.run'
wrkdir, prog = os.path.split(prg_filename)
if os.path.exists(lrn_filename):
os.remove(lrn_filename)
s = sublime.load_settings('SAS_Package.sublime-settings')
sas_path = s.get('sas-path', "C:\\Program Files\\SAS\\SASFoundation\\9.2\\sas.exe")
sas_args = s.get('sas-args', ['-nologo', '-noovp'])
err_regx = s.get('err-regx', "(^(error|warning:)|uninitialized|[^l]remerge|Invalid data for)(?! (the .{4,15} product with which|your system is scheduled|will be expiring soon, and|this upcoming expiration.|information on your warning period.))")
s.set('sas-path', sas_path)
s.set('sas-args', sas_args)
s.set('err-regx', err_regx)
sublime.save_settings('SAS_Package.sublime-settings')
err_regx = re.compile(err_regx, re.MULTILINE + re.IGNORECASE)
if os.path.exists(sas_path):
call_args = [sas_path, '-sysin', prg_filename, '-log', log_filename, '-print', lst_filename, '-SASINITIALFOLDER', wrkdir] + sas_args
# print subprocess.list2cmdline(call_args)
# sublime.set_timeout_async(self.run_calc, 0)
sublime.set_timeout_async(lambda: self.shell_out_to_sas(call_args, prg_filename, lst_filename, log_filename, err_regx, sas_path), 0)
else:
sublime.message_dialog("Problem--could not find sas.exe at " + sas_path + ". Please update the sas-path setting in SAS_Package.sublime-settings in the User package folder.")
def check_log(self, log_path, err_regx):
if os.path.exists(log_path):
log = open(log_path)
log_contents = log.read()
log.close()
num_errs = len(re.findall(err_regx, log_contents))
self.window_reference.window.open_file(log_path)
self.window_reference.window.active_view().run_command('show_next_error')
return "\nLog file: " + log_path + "\n" + "Found " + str(num_errs) + " errors/warnings."
else:
sublime.message_dialog('Sorry--this only works with .sas files.')

return "PROBLEM!--could not find log file " + log_path + "!"
11 changes: 11 additions & 0 deletions test1.sas
@@ -0,0 +1,11 @@
data fakedata;
do i = 5 to 100000000;
rnd = int(ranuni(0)*4 - 2);
res = logbeta(i, i-rnd);
output;
end;
run;

title "Output of Test1.sas";
proc print data=fakedata(obs=10);
run;
11 changes: 11 additions & 0 deletions test2.sas
@@ -0,0 +1,11 @@
data fakedata;
do i = 5 to 100000000;
rnd = int(ranuni(0)*4 - 2);
res = logbeta(i, i-rnd);
output;
end;
run;

title "Output of Test2.sas";
proc print data=fakedata(obs=10);
run;

0 comments on commit f372559

Please sign in to comment.