diff options
Diffstat (limited to 'instances.py')
-rw-r--r-- | instances.py | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/instances.py b/instances.py new file mode 100644 index 0000000..d7059be --- /dev/null +++ b/instances.py @@ -0,0 +1,153 @@ +# importing the global modules +import pexpect +import os +import re +import time +import sys + +#importing the local variables +from soc.settings import PROJECT_DIR +from soc.config import SCILAB_FLAGS, SCIMAX_LOADER, UPLOADS_PATH + +''' An object of class ScilabInstance handles spawning and maintaining of multiple +scilab instances. + +maxsize is the upper bound of number of Scilab instances that can be alive at the +same time. + +instances list maintains a pool of free Scilab instances. + +count is the number of Scilab instances alive currently. + +spawn_instance method is used to create Pexpect objects, which in turn spawn Scilab +instance. A new instance is spawned only if the count is not exceeding the value of +maxsize. + +kill_instances method is used to kill the free Scilab instances in the list instances, +based on the parameter count passed while invoking the method. + +get_available_instance method is used to fetch a non-busy Scilab instance. +It receives one from the list instances or else invokes spawn_instances method to +fetch a new instance to execute the Scilab code. If there are no Scilab instances +available, the request has to wait until an instance is available. + +execute_code method executes the code passed as one of its parameter. It invokes +get_available_instance method, fetches a Scilab instance and executes the code. +After the execution of the code, the Pexpect object containing Scilab instance is +put back into the instances list. +''' +class ScilabInstance(object): + + #defining instance variables + def __init__(self): + self.maxsize = 5 + self.instances = [] + self.count = 0 + + # spawning an instance + def spawn_instance(self): + if (self.count < self.maxsize): + new_instance = pexpect.spawn('scilab-adv-cli') + self.count += 1 + try: + new_instance.expect('-->', timeout = 30) + self.instances.append(new_instance) + except: + new_instance.close() + self.count -= 1 + + # killing some spawned instances + def kill_instances(self, count): + for i in range(count): + instance = self.instances.pop(0) + instance.close() + self.count -= 1 + + # returns an active_instancescilab instance. This will block till it gets an active_instance. + def get_available_instance(self): + if not self.instances and self.count < self.maxsize: + self.spawn_instance() + while not self.instances: + pass + return self.instances.pop(0) + + + def execute_code(self, code, token, book_id, dependency_exists): + #Check for system commands + system_commands = re.compile( + 'unix\(.*\)|unix_g\(.*\)|unix_w\(.*\)|unix_x\(.*\)|unix_s\(.*\)|host|newfun|execstr|ascii|mputl|dir\(\)' + ) + if system_commands.search(code): + return { + 'output': 'System Commands not allowed', + } + + #Remove all clear; + code = re.sub(r'clear.*all|clear|clc\(\)|clc', '', code) + + plot_exists = False + + #Finding the plot and appending xs2jpg function + #p = re.compile(r'.*plot.*\(.*\).*\n|bode\(.*\)|evans\(.*\)') + p = re.compile(r'plot*|.*plot.*\(.*\).*\n|bode\(.*\)|evans\(.*\)') + + plot_path = '' + if p.search(code): + plot_exists = True + code = code + '\n' + current_time = time.time() + plot_path = PROJECT_DIR + '/static/tmp/{0}.png'.format(str(current_time)) + #code += 'xs2jpg(gcf(), "{0}");\n'.format(plot_path) + + #Check whether to load scimax / maxima + if 'syms' in code or 'Syms' in code: + code = code.replace('syms', 'Syms') + code = 'exec(\'{0}\');\nmaxinit\n'.format(SCIMAX_LOADER) + code + + file_path = PROJECT_DIR + '/static/tmp/' + token + '.sci' + + #traps even syntax errors eg: endfunton + f = open(file_path, "w") + f.write("clear;"); + f.write('driver("PNG");\n') + f.write('xinit("{0}");\n'.format(plot_path)) + f.write('mode(2);\n') + if dependency_exists: + f.write( + 'getd("{0}/{1}/DEPENDENCIES/");'.format(UPLOADS_PATH, book_id) + ) + f.write('lines(0);\n') + f.write(code) + f.write('\nxend();') + f.close() + + cmd = 'exec("' + file_path + '", 2);' + + active_instance= self.get_available_instance() + active_instance.sendline(cmd) + + try: + active_instance.expect('\[0m ', timeout = 30) + active_instance.expect('', timeout = 30) + output = self.trim(active_instance.before) + self.instances.append(active_instance) + + except: + active_instance.before += "Exception Occured: It seems that you are running \ + an infinite code" + output = self.trim(active_instance.before) + active_instance.close() + self.count -= 1 + if(self.count == 0): + self.spawn_instance() + + data = { + 'output': output, + 'plot_path': plot_path.replace(PROJECT_DIR, '') + } + return data + + def trim(self, output): + output = [line for line in output.split('\n') if line.strip() != ''] + output = '\n'.join(output) + return output
\ No newline at end of file |