comparison jupyter_c_kernel/kernel.py @ 20:696cc0775abb

Change package name
author Brendan Rius <brendan@omixy.com>
date Fri, 29 Apr 2016 09:58:55 +0100
parents c_kernel/kernel.py@101e99452042
children ee3ac764f5f0
comparison
equal deleted inserted replaced
19:92e342d23ebc 20:696cc0775abb
1 from ipykernel.kernelbase import Kernel
2 import subprocess
3 import tempfile
4 import os
5
6
7 class CKernel(Kernel):
8 implementation = 'jupyter_c_kernel'
9 implementation_version = '1.0'
10 language = 'c'
11 language_version = 'C11'
12 language_info = {'name': 'c',
13 'mimetype': 'text/plain',
14 'file_extension': 'c'}
15 banner = "C kernel.\n" \
16 "Uses gcc, compiles in C11, and creates source code files and executables in temporary folder.\n"
17
18 def __init__(self, *args, **kwargs):
19 super(CKernel, self).__init__(*args, **kwargs)
20 self.files = []
21
22 def cleanup_files(self):
23 """Remove all the temporary files created by the kernel"""
24 for file in self.files:
25 os.remove(file)
26
27 def new_temp_file(self, **kwargs):
28 """Create a new temp file to be deleted when the kernel shuts down"""
29 # We don't want the file to be deleted when closed, but only when the kernel stops
30 kwargs['delete'] = False
31 kwargs['mode'] = 'w'
32 file = tempfile.NamedTemporaryFile(**kwargs)
33 self.files.append(file.name)
34 return file
35
36 @staticmethod
37 def execute_command(cmd):
38 """Execute a command and returns the return code, stdout and stderr"""
39 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
40 stdout, stderr = p.communicate()
41 return p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
42
43 @staticmethod
44 def compile_with_gcc(source_filename, binary_filename):
45 args = ['gcc', source_filename, '-std=c11', '-o', binary_filename]
46 return CKernel.execute_command(args)
47
48 def do_execute(self, code, silent, store_history=True,
49 user_expressions=None, allow_stdin=False):
50
51 retcode, stdout, stderr = None, '', ''
52 with self.new_temp_file(suffix='.c') as source_file:
53 source_file.write(code)
54 source_file.flush()
55 with self.new_temp_file(suffix='.out') as binary_file:
56 retcode, stdout, stderr = self.compile_with_gcc(source_file.name, binary_file.name)
57 if retcode != 0:
58 stderr += "[C kernel] GCC exited with code {}, the executable will not be executed".format(retcode)
59 self.log.info("GCC return code: {}".format(retcode))
60 self.log.info("GCC stdout: {}".format(stdout))
61 self.log.info("GCC stderr: {}".format(stderr))
62
63 if retcode == 0: # If the compilation succeeded
64 retcode, out, err = CKernel.execute_command([binary_file.name])
65 if retcode != 0:
66 stderr += "[C kernel] Executable exited with code {}".format(retcode)
67 self.log.info("Executable retcode: {}".format(retcode))
68 self.log.info("Executable stdout: {}".format(out))
69 self.log.info("Executable stderr: {}".format(err))
70 stdout += out
71 stderr += err
72 else:
73 self.log.info('Compilation failed, the program will not be executed')
74
75 if not silent:
76 stream_content = {'name': 'stderr', 'text': stderr}
77 self.send_response(self.iopub_socket, 'stream', stream_content)
78 stream_content = {'name': 'stdout', 'text': stdout}
79 self.send_response(self.iopub_socket, 'stream', stream_content)
80 return {'status': 'ok', 'execution_count': self.execution_count, 'payload': [], 'user_expressions': {}}
81
82 def do_shutdown(self, restart):
83 """Cleanup the created source code files and executables when shutting down the kernel"""
84 self.cleanup_files()