diff options
-rw-r--r-- | HISTORY.rst | 2 | ||||
-rw-r--r-- | README.rst | 3 | ||||
-rw-r--r-- | kernelspec/kernel.json | 5 | ||||
-rw-r--r-- | scilab_kernel.py | 223 | ||||
-rw-r--r-- | setup.py | 21 |
5 files changed, 150 insertions, 104 deletions
diff --git a/HISTORY.rst b/HISTORY.rst index 7ff8366..9721522 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -5,4 +5,4 @@ Release History 0.1 (2014-08-09) ++++++++++++++++++ -- Initial release: provides completion, history and calltips. +- Initial release: provides all basic features, including inline plots. @@ -6,7 +6,8 @@ To test it, install with ``setup.py``, then:: ipython qtconsole --kernel scilab -It supports command history, the ``?`` help magic, and completion. +It supports command history, the ``?`` help magic and calltips, +plotting, and completion. For details of how this works, see IPython's docs on `wrapper kernels <http://ipython.org/ipython-doc/dev/development/wrapperkernels.html>`_. diff --git a/kernelspec/kernel.json b/kernelspec/kernel.json deleted file mode 100644 index ca1dfd3..0000000 --- a/kernelspec/kernel.json +++ /dev/null @@ -1,5 +0,0 @@ -{"argv":["python","-m","scilab_kernel", "-f", "{connection_file}"], - "display_name":"Scilab", - "language":"scilab", - "codemirror_mode":"octave" -} diff --git a/scilab_kernel.py b/scilab_kernel.py index 3a46d2a..9480a71 100644 --- a/scilab_kernel.py +++ b/scilab_kernel.py @@ -48,7 +48,7 @@ class ScilabKernel(Kernel): def __init__(self, **kwargs): Kernel.__init__(self, **kwargs) - self.log.setLevel(logging.CRITICAL) + self.log.setLevel(logging.INFO) # Signal handlers are inherited by forked processes, # and we can't easily reset it from the subprocess. @@ -59,6 +59,8 @@ class ScilabKernel(Kernel): try: self.scilab_wrapper = scilab scilab.restart() + # start scilab and override gettext function + self.scilab_wrapper._eval('_ = ""') finally: signal.signal(signal.SIGINT, sig) @@ -152,30 +154,19 @@ class ScilabKernel(Kernel): return default token = tokens[-1] - if os.sep in token: - dname = os.path.dirname(token) - rest = os.path.basename(token) - - if os.path.exists(dname): - files = os.listdir(dname) - matches = [f for f in files if f.startswith(rest)] - start = cursor_pos - len(rest) - - else: - return default - - else: - start = cursor_pos - len(token) - cmd = 'completion("%s")' % token - output = self.scilab_wrapper._eval([cmd]) - if output is None or output == '': - return default + start = cursor_pos - len(token) + cmd = 'x = completion("%s");' % token + output = self.scilab_wrapper._eval(cmd) + matches = [] + if not output is None: matches = output.replace('!', ' ').split() for item in dir(self.scilab_wrapper): if item.startswith(token) and not item in matches: matches.append(item) + matches.extend(_complete_path(token)) + return {'matches': matches, 'cursor_start': start, 'cursor_end': cursor_pos, 'metadata': dict(), 'status': 'ok'} @@ -189,9 +180,9 @@ class ScilabKernel(Kernel): else: token = code[:cursor_pos - 1].replace(';', '').split()[-1] - self.log.info(token) - docstring = self._get_scilab_info(token, - detail_level)['docstring'] + info = _get_scilab_info(self.scilab_wrapper, self.inspector, + token, detail_level) + docstring = info['docstring'] if docstring: data = {'text/plain': docstring} @@ -251,7 +242,9 @@ class ScilabKernel(Kernel): return token = tokens[-1] - info = self._get_scilab_info(token, detail_level) + info = _get_scilab_info(self.scilab_wrapper, self.inspector, + token, detail_level) + if 'built-in Scilab function.' in info['docstring']: self.scilab_wrapper.help(token) @@ -260,7 +253,7 @@ class ScilabKernel(Kernel): self.send_response(self.iopub_socket, 'stream', stream_content) else: - output = self._get_printable_info(info, detail_level) + output = _get_printable_info(self.inspector, info, detail_level) stream_content = {'name': 'stdout', 'data': output} self.send_response(self.iopub_socket, 'stream', stream_content) @@ -281,86 +274,126 @@ class ScilabKernel(Kernel): return {'status': 'error', 'execution_count': self.execution_count, 'ename': '', 'evalue': err, 'traceback': []} - def _get_printable_info(self, info, detail_level=0): - inspector = self.inspector - displayfields = [] - def add_fields(fields): - for title, key in fields: - field = info[key] - if field is not None: - displayfields.append((title, field.rstrip())) +def _get_printable_info(inspector, info, detail_level=0): + displayfields = [] - add_fields(inspector.pinfo_fields1) - add_fields(inspector.pinfo_fields2) - add_fields(inspector.pinfo_fields3) + def add_fields(fields): + for title, key in fields: + field = info[key] + if field is not None: + displayfields.append((title, field.rstrip())) - # Source or docstring, depending on detail level and whether - # source found. - if detail_level > 0 and info['source'] is not None: - source = cast_unicode(info['source']) - displayfields.append(("Source", source)) + add_fields(inspector.pinfo_fields1) + add_fields(inspector.pinfo_fields2) + add_fields(inspector.pinfo_fields3) - elif info['docstring'] is not None: - displayfields.append(("Docstring", info["docstring"])) + # Source or docstring, depending on detail level and whether + # source found. + if detail_level > 0 and info['source'] is not None: + source = cast_unicode(info['source']) + displayfields.append(("Source", source)) - # Info for objects: - else: - add_fields(inspector.pinfo_fields_obj) - - # Finally send to printer/pager: - if displayfields: - return inspector._format_fields(displayfields) - - def _get_scilab_info(self, obj, detail_level): - info = dict(argspec=None, base_class=None, call_def=None, - call_docstring=None, class_docstring=None, - definition=None, docstring=None, file=None, - found=False, init_definition=None, - init_docstring=None, isalias=0, isclass=None, - ismagic=0, length=None, name='', namespace=None, - source=None, string_form=None, type_name='') - - sci = self.scilab_wrapper - - if obj in dir(sci): - obj = getattr(sci, obj) - return self.inspector.info(obj, detail_level=detail_level) - - exist = sci.run('exists("%s")' % obj) - if exist == 0: - return info - - typeof = sci._eval('typeof(%s)' % obj) - lookup = dict(st="structure array", ce="cell array", - fptr="built-in Scilab function") - typeof = lookup.get(typeof, typeof) - - var = None - if typeof in ['function', 'built-in Scilab function']: - docstring = sci._get_doc(obj) - else: - docstring = 'A %s' % typeof - try: - var = sci.get(obj) - except Scilab2PyError: - pass - - if typeof == 'function': - source = sci._eval('fun2string(%s)' % obj) - source = source.replace('!', '').splitlines() - source = '\n'.join(source[::2]) - else: - source = docstring + elif info['docstring'] is not None: + displayfields.append(("Docstring", info["docstring"])) - info['found'] = True - info['docstring'] = docstring - info['type_name'] = typeof.capitalize() - info['source'] = source - info['string_form'] = obj if var is None else str(var) + # Info for objects: + else: + add_fields(inspector.pinfo_fields_obj) + # Finally send to printer/pager: + if displayfields: + return inspector._format_fields(displayfields) + + +def _get_scilab_info(scilab, inspector, obj, detail_level): + info = dict(argspec=None, base_class=None, call_def=None, + call_docstring=None, class_docstring=None, + definition=None, docstring=None, file=None, + found=False, init_definition=None, + init_docstring=None, isalias=0, isclass=None, + ismagic=0, length=None, name='', namespace=None, + source=None, string_form=None, type_name='') + + sci = scilab + + if obj in dir(sci): + obj = getattr(sci, obj) + return inspector.info(obj, detail_level=detail_level) + + exist = sci._eval('exists("%s");' % obj) + if exist == 0 or exist is None: return info + typeof = sci._eval('typeof(%s);' % obj) or 'Error' + lookup = dict(st="structure array", ce="cell array", + fptr="built-in Scilab function") + typeof = lookup.get(typeof, typeof) + + var = None + if typeof in ['function', 'built-in Scilab function']: + docstring = sci._get_doc(obj) or '' + + if typeof == 'built-in Scilab function': + before = """Use run("help %s") for full docs.""" % obj + after = "Type `help %s` to bring up the Help Browser" % obj + docstring = docstring.replace(before, after) + + else: + docstring = 'A %s' % typeof + try: + var = sci.get(obj) + except Scilab2PyError: + pass + + source = docstring + + if typeof == 'function': + source = sci._eval('fun2string(%s);' % obj) or '' + source = source.replace('!', '').splitlines() + source = '\n'.join(source[::2]) + + info['found'] = True + info['docstring'] = docstring + info['type_name'] = typeof.capitalize() + info['source'] = source + info['string_form'] = obj if var is None else str(var) + + return info + + +def _listdir(root): + "List directory 'root' appending the path separator to subdirs." + res = [] + for name in os.listdir(root): + path = os.path.join(root, name) + if os.path.isdir(path): + name += os.sep + res.append(name) + return res + + +def _complete_path(path=None): + """Perform completion of filesystem path. + + http://stackoverflow.com/questions/5637124/tab-completion-in-pythons-raw-input + """ + if not path: + return _listdir('.') + dirname, rest = os.path.split(path) + tmp = dirname if dirname else '.' + res = [os.path.join(dirname, p) + for p in _listdir(tmp) if p.startswith(rest)] + # more than one match, or single match which does not exist (typo) + if len(res) > 1 or not os.path.exists(path): + return res + # resolved to a single directory, so return list of files below it + if os.path.isdir(path): + return [os.path.join(path, p) for p in _listdir(path)] + # exact file match terminates this completion + return [path + ' '] + + if __name__ == '__main__': from IPython.kernel.zmq.kernelapp import IPKernelApp IPKernelApp.launch_instance(kernel_class=ScilabKernel) @@ -1,5 +1,6 @@ from distutils.core import setup from distutils.command.install import install +import json import os import sys @@ -9,11 +10,27 @@ if sys.argv[-1] == 'publish': sys.exit() +kernel_json = {"argv": [sys.executable, "-m", "scilab_kernel", "-f", + "{connection_file}"], + "display_name": "Scilab", + "language": "scilab", + "codemirror_mode": "Octave" + } + + class install_with_kernelspec(install): def run(self): + # Regular installation install.run(self) - from IPython.kernel.kernelspec import install_kernel_spec - install_kernel_spec('kernelspec', 'scilab', replace=True) + + # Now write the kernelspec + from IPython.kernel.kernelspec import KernelSpecManager + from IPython.utils.path import ensure_dir_exists + destdir = os.path.join(KernelSpecManager().user_kernel_dir, 'scilab') + ensure_dir_exists(destdir) + with open(os.path.join(destdir, 'kernel.json'), 'w') as f: + json.dump(kernel_json, f, sort_keys=True) + with open('README.rst') as f: readme = f.read() |