Hello community,
here is the log from the commit of package python-metakernel for openSUSE:Factory checked in at 2019-06-01 09:56:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-metakernel (Old)
and /work/SRC/openSUSE:Factory/.python-metakernel.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-metakernel"
Sat Jun 1 09:56:24 2019 rev:2 rq:706397 version:0.23.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-metakernel/python-metakernel.changes 2019-05-22 11:05:35.246579415 +0200
+++ /work/SRC/openSUSE:Factory/.python-metakernel.new.5148/python-metakernel.changes 2019-06-01 09:56:28.203181507 +0200
@@ -1,0 +2,20 @@
+Wed May 29 20:10:40 UTC 2019 - Todd R
+
+- Update to 0.23.0
+ * Clean up configurability handling and docs
+ * fix handling of kernel class
+ * export the metakernel app
+ * Add settings handling
+ * switch to powershell on windows
+ * clean up interrupt behavior and error handling
+ * clean up stdin handler
+ * clean up replwrap prompt handling
+ * avoid double printing output
+ * add support for cr printing
+ * Fix handling metadata in _formatter
+ * Define cluster_size and cluster_rank on host kernel
+ * kernel.parent can be None in some situations
+ * Allow help and info to return mime-type data
+ * Adjustment for newer jedi
+
+-------------------------------------------------------------------
Old:
----
metakernel-0.20.14.tar.gz
New:
----
metakernel-0.23.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-metakernel.spec ++++++
--- /var/tmp/diff_new_pack.iPLD1n/_old 2019-06-01 09:56:28.723181329 +0200
+++ /var/tmp/diff_new_pack.iPLD1n/_new 2019-06-01 09:56:28.727181328 +0200
@@ -17,35 +17,26 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
-# Tests require an active terminal
%bcond_with test
Name: python-metakernel
-Version: 0.20.14
+Version: 0.23.0
Release: 0
Summary: Metakernel for Jupyter
License: BSD-3-Clause
Group: Development/Languages/Python
URL: https://github.com/Calysto/metakernel
Source: https://files.pythonhosted.org/packages/source/m/metakernel/metakernel-%{version}.tar.gz
-BuildRequires: %{python_module ipykernel}
-BuildRequires: %{python_module ipython}
-BuildRequires: %{python_module jupyter_client}
-BuildRequires: %{python_module jupyter_core}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: jupyter-ipykernel
-Requires: jupyter-jupyter_client
-Requires: jupyter-jupyter_core
+Requires: python-ipykernel
Requires: python-ipython
+Requires: python-jupyter_client
+Requires: python-jupyter_core
Requires: python-pexpect >= 4.2
Provides: python-jupyter_metakernel = %{version}
-Obsoletes: python-jupyter_metakernel <= %{version}
+Obsoletes: python-jupyter_metakernel < %{version}
BuildArch: noarch
-%if %{with test}
-BuildRequires: %{python_module pexpect >= 4.2}
-BuildRequires: bash
-%endif
%ifpython3
Provides: jupyter-metakernel = %{version}
%endif
@@ -74,10 +65,10 @@
%fdupes %{buildroot}%{$python_sitelib}
}
-%if %{with test}
-%check
-%python_exec setup.py test
-%endif
+# Tests require an active terminal
+# %%check
+# %%python_exec setup.py test
+# %%endif
%files %{python_files}
%doc CONTRIBUTORS.rst HISTORY.rst README.rst
++++++ metakernel-0.20.14.tar.gz -> metakernel-0.23.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/PKG-INFO new/metakernel-0.23.0/PKG-INFO
--- old/metakernel-0.20.14/PKG-INFO 2018-01-23 22:30:35.000000000 +0100
+++ new/metakernel-0.23.0/PKG-INFO 2019-05-10 20:02:16.000000000 +0200
@@ -1,12 +1,12 @@
Metadata-Version: 1.1
Name: metakernel
-Version: 0.20.14
+Version: 0.23.0
Summary: Metakernel for Jupyter
Home-page: https://github.com/Calysto/metakernel
Author: Steven Silvester
Author-email: steven.silvester@ieee.org
License: UNKNOWN
-Description: A Jupyter/IPython kernel template which includes core magic functions (including help, command and file path completion, parallel and distributed processing, downloads, and much more).
+Description: A Jupyter kernel base class in Python which includes core magic functions (including help, command and file path completion, parallel and distributed processing, downloads, and much more).
.. image:: https://badge.fury.io/py/metakernel.png/
:target: http://badge.fury.io/py/metakernel
@@ -17,9 +17,15 @@
.. image:: https://travis-ci.org/Calysto/metakernel.svg
:target: https://travis-ci.org/Calysto/metakernel
+ .. image:: https://anaconda.org/conda-forge/metakernel/badges/version.svg
+ :target: https://anaconda.org/conda-forge/metakernel
- See IPython's docs on `wrapper kernels
- http://ipython.org/ipython-doc/dev/development/wrapperkernels.html`_.
+ .. image:: https://anaconda.org/conda-forge/metakernel/badges/downloads.svg
+ :target: https://anaconda.org/conda-forge/metakernel
+
+
+ See Jupyter's docs on `wrapper kernels
+ http://jupyter-client.readthedocs.io/en/stable/wrapperkernels.html`_.
Additional magics can be installed within the new kernel package under a `magics` subpackage.
@@ -55,25 +61,44 @@
Installation
----------------
- You can install Metakernel through `pip`:
+ You can install Metakernel through ``pip``:
+
+ .. code::bash
+
+ pip install metakernel --upgrade
+
+ Installing `metakernel` from the `conda-forge` channel can be achieved by adding `conda-forge` to your channels with:
+
+ .. code::bash
+
+ conda config --add channels conda-forge
+
+ Once the `conda-forge` channel has been enabled, `metakernel` can be installed with:
+ .. code::bash
- `pip install metakernel --upgrade`
+ conda install metakernel
+
+ It is possible to list all of the versions of `metakernel` available on your platform with:
+
+ .. code::bash
+
+ conda search metakernel --channel conda-forge
Use MetaKernel Magics in IPython
--------------------------------
- Although MetaKernel is a system for building new kernels, you can use a subset of the magics in the IPython kernel.
+ Although MetaKernel is a system for building new kernels, you can use a subset of the magics in the IPython kernel.
- .. code-block:: python
+ .. code:: python
from metakernel import register_ipython_magics
register_ipython_magics()
- Put the following in your (or a system-wide) ipython_config.py file:
+ Put the following in your (or a system-wide) ``ipython_config.py`` file:
- .. code-block:: python
+ .. code:: python
# /etc/ipython/ipython_config.py
c = get_config()
@@ -83,6 +108,102 @@
]
c.InteractiveShellApp.exec_lines = startup
+ Use MetaKernel Languages in Parallel
+
+ To use a MetaKernel language in parallel, do the following:
+
+ 1. Make sure that the Python module `ipyparallel` is installed. In the shell, type:
+
+ .. code:: bash
+
+ pip install ipyparallel
+
+
+ 2. To enable the extension in the notebook, in the shell, type:
+
+ .. code:: bash
+
+ ipcluster nbextension enable
+
+
+ 3. To start up a cluster, with 10 nodes, on a local IP address, in the shell, type:
+
+ .. code:: bash
+
+ ipcluster start --n=10 --ip=192.168.1.108
+
+
+ 4. Initialize the code to use the 10 nodes, inside the notebook from a host kernel ``MODULE`` and ``CLASSNAME`` (can be any metakernel kernel):
+
+ .. code:: bash
+
+ %parallel MODULE CLASSNAME
+
+
+ For example:
+
+ .. code:: bash
+
+ %parallel calysto_scheme CalystoScheme
+
+
+ 5. Run code in parallel, inside the notebook, type:
+
+ Execute a single line, in parallel:
+
+ .. code:: bash
+
+ %px (+ 1 1)
+
+
+ Or execute the entire cell, in parallel:
+
+ .. code:: bash
+
+ %%px
+ (* cluster_rank cluster_rank)
+
+
+ Results come back in a Python list (Scheme vector), in ``cluster_rank`` order. (This will be a JSON representation in the future).
+
+ Therefore, the above would produce the result:
+
+ .. code:: bash
+
+ #10(0 1 4 9 16 25 36 49 64 81)
+
+ You can get the results back in any of the parallel magics (``%px``, ``%%px``, or ``%pmap``) in the host kernel by accessing the variable ``_`` (single underscore), or by using the ``--set_variable VARIABLE`` flag, like so:
+
+ .. code:: bash
+
+ %%px --set_variable results
+ (* cluster_rank cluster_rank)
+
+
+ Then, in the next cell, you can access ``results``.
+
+ Notice that you can use the variable ``cluster_rank`` to partition parts of a problem so that each node is working on something different.
+
+ In the examples above, use ``-e`` to evaluate the code in the host kernel as well. Note that ``cluster_rank`` is not defined on the host machine, and that this assumes the host kernel is the same as the parallel machines.
+
+
+ Configuration
+ -------------
+ ``Metakernel`` implementations can subclasses can be configured by the user. The
+ configuration file name is determined by the ``app_name`` property of the subclass.
+ For example, in the ``Octave`` kernel, it is ``octave_kernel``. The user of the kernel can add an ``octave_kernel_config.py`` file to their
+ ``jupyter`` config path. The base ``MetaKernel`` class offers ``plot_settings`` as a configurable trait. Subclasses can defined other traits that they wish to make
+ configurable.
+
+ As an example:
+
+ .. code:: bash
+
+ cat ~/.jupyter/octave_kernel_config.py
+ # use Qt as the default backend for plots
+ c.OctaveKernel.plot_settings = dict(backend='qt')
+
+
Documentation
-----------------------
@@ -101,13 +222,11 @@
.. _History: https://github.com/Calysto/metakernel/blob/master/HISTORY.rst
-
-
Platform: UNKNOWN
Classifier: Framework :: IPython
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2
Classifier: Topic :: System :: Shells
-Requires: ipykernel (< 6.0)
+Requires: ipykernel
Requires: pexpect (>= 4.2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/README.rst new/metakernel-0.23.0/README.rst
--- old/metakernel-0.20.14/README.rst 2018-01-23 21:06:42.000000000 +0100
+++ new/metakernel-0.23.0/README.rst 2019-05-10 20:01:47.000000000 +0200
@@ -1,4 +1,4 @@
-A Jupyter/IPython kernel template which includes core magic functions (including help, command and file path completion, parallel and distributed processing, downloads, and much more).
+A Jupyter kernel base class in Python which includes core magic functions (including help, command and file path completion, parallel and distributed processing, downloads, and much more).
.. image:: https://badge.fury.io/py/metakernel.png/
:target: http://badge.fury.io/py/metakernel
@@ -9,9 +9,15 @@
.. image:: https://travis-ci.org/Calysto/metakernel.svg
:target: https://travis-ci.org/Calysto/metakernel
+.. image:: https://anaconda.org/conda-forge/metakernel/badges/version.svg
+ :target: https://anaconda.org/conda-forge/metakernel
-See IPython's docs on `wrapper kernels
-http://ipython.org/ipython-doc/dev/development/wrapperkernels.html`_.
+.. image:: https://anaconda.org/conda-forge/metakernel/badges/downloads.svg
+ :target: https://anaconda.org/conda-forge/metakernel
+
+
+See Jupyter's docs on `wrapper kernels
+http://jupyter-client.readthedocs.io/en/stable/wrapperkernels.html`_.
Additional magics can be installed within the new kernel package under a `magics` subpackage.
@@ -47,25 +53,44 @@
Installation
----------------
-You can install Metakernel through `pip`:
+You can install Metakernel through ``pip``:
+
+.. code::bash
+
+ pip install metakernel --upgrade
+
+Installing `metakernel` from the `conda-forge` channel can be achieved by adding `conda-forge` to your channels with:
+
+.. code::bash
+
+ conda config --add channels conda-forge
+
+Once the `conda-forge` channel has been enabled, `metakernel` can be installed with:
+.. code::bash
-`pip install metakernel --upgrade`
+ conda install metakernel
+
+It is possible to list all of the versions of `metakernel` available on your platform with:
+
+.. code::bash
+
+ conda search metakernel --channel conda-forge
Use MetaKernel Magics in IPython
--------------------------------
-Although MetaKernel is a system for building new kernels, you can use a subset of the magics in the IPython kernel.
+Although MetaKernel is a system for building new kernels, you can use a subset of the magics in the IPython kernel.
-.. code-block:: python
+.. code:: python
from metakernel import register_ipython_magics
register_ipython_magics()
-Put the following in your (or a system-wide) ipython_config.py file:
+Put the following in your (or a system-wide) ``ipython_config.py`` file:
-.. code-block:: python
+.. code:: python
# /etc/ipython/ipython_config.py
c = get_config()
@@ -75,6 +100,102 @@
]
c.InteractiveShellApp.exec_lines = startup
+Use MetaKernel Languages in Parallel
+
+To use a MetaKernel language in parallel, do the following:
+
+1. Make sure that the Python module `ipyparallel` is installed. In the shell, type:
+
+.. code:: bash
+
+ pip install ipyparallel
+
+
+2. To enable the extension in the notebook, in the shell, type:
+
+.. code:: bash
+
+ ipcluster nbextension enable
+
+
+3. To start up a cluster, with 10 nodes, on a local IP address, in the shell, type:
+
+.. code:: bash
+
+ ipcluster start --n=10 --ip=192.168.1.108
+
+
+4. Initialize the code to use the 10 nodes, inside the notebook from a host kernel ``MODULE`` and ``CLASSNAME`` (can be any metakernel kernel):
+
+.. code:: bash
+
+ %parallel MODULE CLASSNAME
+
+
+For example:
+
+.. code:: bash
+
+ %parallel calysto_scheme CalystoScheme
+
+
+5. Run code in parallel, inside the notebook, type:
+
+Execute a single line, in parallel:
+
+.. code:: bash
+
+ %px (+ 1 1)
+
+
+Or execute the entire cell, in parallel:
+
+.. code:: bash
+
+ %%px
+ (* cluster_rank cluster_rank)
+
+
+Results come back in a Python list (Scheme vector), in ``cluster_rank`` order. (This will be a JSON representation in the future).
+
+Therefore, the above would produce the result:
+
+.. code:: bash
+
+ #10(0 1 4 9 16 25 36 49 64 81)
+
+You can get the results back in any of the parallel magics (``%px``, ``%%px``, or ``%pmap``) in the host kernel by accessing the variable ``_`` (single underscore), or by using the ``--set_variable VARIABLE`` flag, like so:
+
+.. code:: bash
+
+ %%px --set_variable results
+ (* cluster_rank cluster_rank)
+
+
+Then, in the next cell, you can access ``results``.
+
+Notice that you can use the variable ``cluster_rank`` to partition parts of a problem so that each node is working on something different.
+
+In the examples above, use ``-e`` to evaluate the code in the host kernel as well. Note that ``cluster_rank`` is not defined on the host machine, and that this assumes the host kernel is the same as the parallel machines.
+
+
+Configuration
+-------------
+``Metakernel`` implementations can subclasses can be configured by the user. The
+configuration file name is determined by the ``app_name`` property of the subclass.
+For example, in the ``Octave`` kernel, it is ``octave_kernel``. The user of the kernel can add an ``octave_kernel_config.py`` file to their
+``jupyter`` config path. The base ``MetaKernel`` class offers ``plot_settings`` as a configurable trait. Subclasses can defined other traits that they wish to make
+configurable.
+
+As an example:
+
+.. code:: bash
+
+ cat ~/.jupyter/octave_kernel_config.py
+ # use Qt as the default backend for plots
+ c.OctaveKernel.plot_settings = dict(backend='qt')
+
+
Documentation
-----------------------
@@ -92,5 +213,3 @@
.. _online: http://Calysto.github.io/metakernel/
.. _History: https://github.com/Calysto/metakernel/blob/master/HISTORY.rst
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/__init__.py new/metakernel-0.23.0/metakernel/__init__.py
--- old/metakernel-0.20.14/metakernel/__init__.py 2018-01-23 22:18:33.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/__init__.py 2019-05-10 20:02:08.000000000 +0200
@@ -1,5 +1,6 @@
from ._metakernel import (
- ExceptionWrapper, MetaKernel, IPythonKernel, register_ipython_magics, get_metakernel)
+ ExceptionWrapper, MetaKernel, IPythonKernel, register_ipython_magics, get_metakernel,
+ MetaKernelApp)
from . import pexpect
from .replwrap import REPLWrapper, u
from .process_metakernel import ProcessMetaKernel
@@ -8,6 +9,6 @@
__all__ = ['Magic', 'MetaKernel', 'option']
-__version__ = '0.20.14'
+__version__ = '0.23.0'
del magic, _metakernel, parser, process_metakernel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/_metakernel.py new/metakernel-0.23.0/metakernel/_metakernel.py
--- old/metakernel-0.20.14/metakernel/_metakernel.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/_metakernel.py 2019-05-10 20:01:47.000000000 +0200
@@ -17,11 +17,13 @@
warnings.filterwarnings('ignore', module='IPython.html.widgets')
+from jupyter_core.paths import jupyter_config_path, jupyter_config_dir
from IPython.paths import get_ipython_dir
from ipykernel.kernelapp import IPKernelApp
from ipykernel.kernelbase import Kernel
from ipykernel.comm import CommManager
from traitlets.config import Application
+from traitlets import Dict, Unicode
try:
from ipywidgets.widgets.widget import Widget
@@ -78,6 +80,7 @@
class MetaKernel(Kernel):
+ app_name = 'metakernel'
identifier_regex = r'[^\d\W][\w\.]*'
func_call_regex = r'([^\d\W][\w\.]*)\([^\)\()]*\Z'
magic_prefixes = dict(magic='%', shell='!', help='?')
@@ -85,7 +88,7 @@
help_links = [
{
'text': "MetaKernel Magics",
- 'url': "https://github.com/calysto/metakernel/blob/master/metakernel/magics/README.m...",
+ 'url': "https://metakernel.readthedocs.io/en/latest/source/README.html",
},
]
language_info = {
@@ -101,10 +104,12 @@
# 'file_extension': '.py',
'help_links': help_links,
}
+ plot_settings = Dict(dict(backend='inline')).tag(config=True)
+
meta_kernel = None
@classmethod
- def run_as_main(cls):
+ def run_as_main(cls, *args, **kwargs):
"""Launch or install a metakernel.
Modules implementing a metakernel subclass can use the following lines:
@@ -112,7 +117,8 @@
if __name__ == '__main__':
MetaKernelSubclass.run_as_main()
"""
- MetaKernelApp.launch_instance(kernel_class=cls)
+ kwargs['app_name'] = cls.app_name
+ MetaKernelApp.launch_instance(kernel_class=cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
super(MetaKernel, self).__init__(*args, **kwargs)
@@ -130,6 +136,8 @@
sys.stdout.write = self.Write
except:
pass # Can't change stdout
+ self.redirect_to_log = False
+ self.shell = None
self.sticky_magics = OrderedDict()
self._i = None
self._ii = None
@@ -144,7 +152,6 @@
self.comm_manager.register_target('ipython.widget',
lazy_import_handle_comm_opened)
- self.plot_settings = dict(backend='inline')
self.hist_file = get_history_file(self)
self.parser = Parser(self.identifier_regex, self.func_call_regex,
self.magic_prefixes, self.help_suffix)
@@ -156,6 +163,21 @@
self.reload_magics()
# provide a way to get the current instance
self.set_variable("kernel", self)
+ # Run command line filenames, if given:
+ if self.parent is not None and self.parent.extra_args:
+ level = self.log.level
+ self.log.setLevel("INFO")
+ self.redirect_to_log = True
+ self.Write("Executing files...")
+ for filename in self.parent.extra_args:
+ self.Write(" %s..." % filename)
+ try:
+ self.do_execute_file(filename)
+ except Exception as exc:
+ self.log.info(" %s" % (exc,))
+ self.Write("Executing files: done!")
+ self.log.setLevel(level)
+ self.redirect_to_log = False
def makeSubkernel(self, kernel):
"""
@@ -315,11 +337,18 @@
else:
level = 1
text = self.get_help_on(code, level)
- self.log.debug(text)
if text:
- self.payload = [{"data": {"text/plain": text},
- "start_line_number": 0,
- "source": "page"}]
+ content = {
+ "start_line_number": 0,
+ "source": "page",
+ }
+ if isinstance(text, dict):
+ content["data"] = text ## {mime-type: ..., mime-type:...}
+ self.log.debug(str(text))
+ else:
+ content["data"] = {"text/plain": text}
+ self.log.debug(text)
+ self.payload = [content]
elif info['magic'] or self.sticky_magics:
retval = None
@@ -399,8 +428,8 @@
return
content = {
'execution_count': self.execution_count,
- 'data': data,
- 'metadata': {},
+ 'data': data[0],
+ 'metadata': data[1],
}
if not silent:
if Widget and isinstance(retval, Widget):
@@ -529,10 +558,14 @@
cursor_pos=cursor_pos)
if docstring:
- content["data"] = {"text/plain": docstring}
content["status"] = "ok"
content["found"] = True
- self.log.debug(docstring)
+ if isinstance(docstring, dict): ## {"text/plain": ..., mime-type: ...}
+ content["data"] = docstring
+ self.log.debug(str(docstring))
+ else:
+ content["data"] = {"text/plain": docstring}
+ self.log.debug(docstring)
return content
@@ -549,13 +582,13 @@
# Make a metakernel/magics if it doesn't exist:
local_magics_dir = get_local_magics_dir()
# Search all of the places there could be magics:
- paths = [local_magics_dir,
- os.path.join(os.path.dirname(os.path.abspath(__file__)), "magics")]
try:
- paths += [os.path.join(os.path.dirname(
+ paths = [os.path.join(os.path.dirname(
os.path.abspath(inspect.getfile(self.__class__))), "magics")]
except:
- pass
+ paths = []
+ paths += [local_magics_dir,
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "magics")]
for magic_dir in paths:
sys.path.append(magic_dir)
magic_files.extend(glob.glob(os.path.join(magic_dir, "*.py")))
@@ -602,8 +635,8 @@
self.Error(e)
return
content = {
- 'data': data,
- 'metadata': {}
+ 'data': data[0],
+ 'metadata': data[1]
}
self.send_response(
self.iopub_socket,
@@ -628,13 +661,19 @@
stream_content = {
'name': 'stdout', 'text': message}
self.log.debug('Print: %s' % message)
- self.send_response(self.iopub_socket, 'stream', stream_content)
+ if self.redirect_to_log:
+ self.log.info(message)
+ else:
+ self.send_response(self.iopub_socket, 'stream', stream_content)
def Write(self, message):
stream_content = {
'name': 'stdout', 'text': message}
self.log.debug('Write: %s' % message)
- self.send_response(self.iopub_socket, 'stream', stream_content)
+ if self.redirect_to_log:
+ self.log.info(message)
+ else:
+ self.send_response(self.iopub_socket, 'stream', stream_content)
def Error(self, *args, **kwargs):
message = format_message(*args, **kwargs)
@@ -643,7 +682,16 @@
'name': 'stderr',
'text': RED + message + NORMAL
}
- self.send_response(self.iopub_socket, 'stream', stream_content)
+ if self.redirect_to_log:
+ self.log.info(message)
+ else:
+ self.send_response(self.iopub_socket, 'stream', stream_content)
+
+ def send_response(self, *args, **kwargs):
+ ### if we are running via %parallel, we might not have a
+ ### session
+ if self.session:
+ super(MetaKernel, self).send_response(*args, **kwargs)
def call_magic(self, line):
"""
@@ -687,6 +735,24 @@
class MetaKernelApp(IPKernelApp):
+ config_dir = Unicode()
+
+ def _config_dir_default(self):
+ return jupyter_config_dir()
+
+ @property
+ def config_file_paths(self):
+ path = jupyter_config_path()
+ if self.config_dir not in path:
+ path.insert(0, self.config_dir)
+ path.insert(0, os.getcwd())
+ return path
+
+ @classmethod
+ def launch_instance(cls, *args, **kwargs):
+ cls.name = kwargs.pop('app_name', 'metakernel')
+ super(MetaKernelApp, cls).launch_instance(*args, **kwargs)
+
@property
def subcommands(self):
# Slightly awkward way to pass the actual kernel class to the install
@@ -699,7 +765,7 @@
self.argv = argv
def start(self):
- kernel_spec = self.kernel_class.kernel_json
+ kernel_spec = self.kernel_class().kernel_json
with TemporaryDirectory() as td:
dirname = os.path.join(td, kernel_spec['name'])
os.mkdir(dirname)
@@ -767,14 +833,19 @@
if obj:
reprs[mimetype] = obj
- retval = {}
+ format_dict = {}
+ metadata_dict = {}
for (mimetype, value) in reprs.items():
+ metadata = None
try:
value = value()
except Exception:
pass
if not value:
continue
+ if isinstance(value, tuple):
+ metadata = value[1]
+ value = value[0]
if isinstance(value, bytes):
try:
value = value.decode('utf-8')
@@ -782,10 +853,12 @@
value = base64.encodestring(value)
value = value.decode('utf-8')
try:
- retval[mimetype] = str(value)
+ format_dict[mimetype] = str(value)
except:
- retval[mimetype] = value
- return retval
+ format_dict[mimetype] = value
+ if metadata is not None:
+ metadata_dict[mimetype] = metadata
+ return (format_dict, metadata_dict)
def format_message(*args, **kwargs):
Binary files old/metakernel-0.20.14/metakernel/images/logo-512x512.png and new/metakernel-0.23.0/metakernel/images/logo-512x512.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/magic.py new/metakernel-0.23.0/metakernel/magic.py
--- old/metakernel-0.20.14/metakernel/magic.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/magic.py 2019-04-30 11:15:55.000000000 +0200
@@ -12,6 +12,7 @@
# python3
_maxsize = sys.maxsize
+
class MagicOptionParser(optparse.OptionParser):
def error(self, msg):
raise Exception('Magic Parse error: "%s"' % msg)
@@ -24,7 +25,18 @@
## FIXME: override help to also stop processing
## currently --help gives syntax error
+
class Magic(object):
+ """
+ Base class to define magics for MetaKernel based kernels.
+
+ Users can redefine the default magics provided by Metakernel
+ by creating a module with the exact same name as the
+ Metakernel magic.
+
+ For example, you can override %matplotlib in your kernel by
+ writing a new magic inside magics/matplotlib_magic.py
+ """
def __init__(self, kernel):
self.kernel = kernel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/magics/parallel_magic.py new/metakernel-0.23.0/metakernel/magics/parallel_magic.py
--- old/metakernel-0.20.14/metakernel/magics/parallel_magic.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/magics/parallel_magic.py 2019-04-30 11:15:55.000000000 +0200
@@ -40,7 +40,7 @@
%parallel bash_kernel BashKernel
%parallel bash_kernel BashKernel -k bash
- %parallel bash_kernel BashKernel --i [0,2:5,9,...]
+ %parallel bash_kernel BashKernel -i [0,2:5,9,...]
cluster_size and cluster_rank variables are set upon
initialization of the remote node (if the kernel
@@ -144,6 +144,9 @@
self.client[:].scatter('cluster_rank', self.client.ids, flatten=True)
self.view["kernels['%s'].set_variable(\"cluster_rank\", cluster_rank)" % (
kernel_name)]
+ ## So that these are available in the host kernel:
+ self.kernel.set_variable("cluster_size", len(self.client))
+ self.kernel.set_variable("cluster_rank", -1)
self.retval = None
@option(
@@ -155,7 +158,11 @@
help=('evaluate code in the current kernel, too. The current ' +
'kernel should be of the same language as the cluster.')
)
- def line_px(self, expression, kernel_name=None, evaluate=False):
+ @option(
+ '-s', '--set_variable', action='store', default=None,
+ help='set the variable with the parallel results rather than returning them'
+ )
+ def line_px(self, expression, kernel_name=None, evaluate=False, set_variable=None):
"""
%px EXPRESSION - send EXPRESSION to the cluster.
@@ -172,6 +179,7 @@
Use %parallel to initialize the cluster.
"""
+ results = None
expression = str(expression)
if kernel_name is None:
kernel_name = self.kernel_name
@@ -179,7 +187,7 @@
count = 1
while count <= 5:
try:
- self.retval = self.view["kernels['%s'].do_execute_direct(\"%s\")" % (
+ results = self.view["kernels['%s'].do_execute_direct(\"%s\")" % (
kernel_name, self._clean_code(expression))]
break
except:
@@ -191,10 +199,15 @@
self.retry = False
else:
try:
- self.retval = self.view["kernels['%s'].do_execute_direct(\"%s\")" % (
+ results = self.view["kernels['%s'].do_execute_direct(\"%s\")" % (
kernel_name, self._clean_code(expression))]
except Exception as e:
- self.retval = str(e)
+ results = str(e)
+ if set_variable is None:
+ self.retval = results
+ else:
+ self.kernel.set_variable(set_variable, results)
+ self.retval = None
if evaluate:
self.code = expression
@@ -211,7 +224,11 @@
help=('evaluate code in the current kernel, too. The current ' +
'kernel should be of the same language as the cluster.')
)
- def cell_px(self, kernel_name=None, evaluate=False):
+ @option(
+ '-s', '--set_variable', action='store', default=None,
+ help='set the variable with the parallel results rather than returning them'
+ )
+ def cell_px(self, kernel_name=None, evaluate=False, set_variable=None):
"""
%%px - send cell to the cluster.
@@ -224,11 +241,20 @@
"""
if kernel_name is None:
kernel_name = self.kernel_name
- self.retval = self.view["kernels['%s'].do_execute_direct(\"%s\")" % (
+ results = self.view["kernels['%s'].do_execute_direct(\"%s\")" % (
kernel_name, self._clean_code(self.code))]
+ if set_variable is None:
+ self.retval = results
+ else:
+ self.kernel.set_variable(set_variable, results)
+ self.retval = None
self.evaluate = evaluate
- def line_pmap(self, function_name, args, kernel_name=None):
+ @option(
+ '-s', '--set_variable', action='store', default=None,
+ help='set the variable with the parallel results rather than returning them'
+ )
+ def line_pmap(self, function_name, args, kernel_name=None, set_variable=None):
"""
%pmap FUNCTION [ARGS1,ARGS2,...] - ("parallel map") call a FUNCTION on args
@@ -276,7 +302,12 @@
from IPython.parallel.util import interactive
f = interactive(lambda arg, kname=kernel_name, fname=function_name: \
kernels[kname].do_function_direct(fname, arg))
- self.retval = self.view_load_balanced.map_async(f, eval(args))
+ results = self.view_load_balanced.map_async(f, eval(args))
+ if set_variable is None:
+ self.retval = results
+ else:
+ self.kernel.set_variable(set_variable, results)
+ self.retval = None
def post_process(self, retval):
try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/magics/python_magic.py new/metakernel-0.23.0/metakernel/magics/python_magic.py
--- old/metakernel-0.20.14/metakernel/magics/python_magic.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/magics/python_magic.py 2019-04-30 11:15:55.000000000 +0200
@@ -156,7 +156,15 @@
position = (info['line_num'], info['column'])
interpreter = Interpreter(text, [self.env])
- if jedi.__version__ >= LooseVersion('0.10.0'):
+ if jedi.__version__ >= LooseVersion('0.12.0'):
+ lines = split_lines(text)
+ name = get_on_completion_name(
+ interpreter._module_node,
+ lines,
+ position
+ )
+ before = text[:len(text) - len(name)]
+ elif jedi.__version__ >= LooseVersion('0.10.0'):
lines = split_lines(text)
name = get_on_completion_name(
interpreter._get_module_node(),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/magics/shell_magic.py new/metakernel-0.23.0/metakernel/magics/shell_magic.py
--- old/metakernel-0.20.14/metakernel/magics/shell_magic.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/magics/shell_magic.py 2019-05-03 13:32:40.000000000 +0200
@@ -3,7 +3,7 @@
from __future__ import print_function
from metakernel import Magic, pexpect
-from metakernel.replwrap import cmd, bash
+from metakernel.replwrap import powershell, bash
import os
@@ -57,8 +57,8 @@
if not self.cmd:
if os.name == 'nt':
- self.cmd = 'cmd'
- self.repl = cmd()
+ self.cmd = 'powershell'
+ self.repl = powershell()
elif pexpect.which('bash'):
self.cmd = 'bash'
self.repl = bash()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/process_metakernel.py new/metakernel-0.23.0/metakernel/process_metakernel.py
--- old/metakernel-0.20.14/metakernel/process_metakernel.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/process_metakernel.py 2019-05-04 11:33:12.000000000 +0200
@@ -4,6 +4,7 @@
from .replwrap import REPLWrapper, bash
from subprocess import check_output
import re
+import sys
__version__ = '0.0'
@@ -71,6 +72,7 @@
interrupted = False
output = ''
+ error = None
stream_handler = self.Print if not silent else None
try:
output = wrapper.run_command(code.rstrip(), timeout=None,
@@ -82,7 +84,11 @@
except EOF:
self.Print(child.before)
self.do_shutdown(True)
- return
+ error = RuntimeError('End of File')
+ tb = 'End of File'
+ except Exception as e:
+ ex_type, error, tb = sys.exc_info()
+ self.Error(str(e))
if interrupted:
self.kernel_resp = {
@@ -99,6 +105,15 @@
'ename': '', 'evalue': str(exitcode),
'traceback': trace,
}
+
+ elif error:
+ self.kernel_resp = {
+ 'status': 'error',
+ 'execution_count': self.execution_count,
+ 'ename': '', 'evalue': str(error),
+ 'traceback': str(tb),
+ }
+
else:
self.kernel_resp = {
'status': 'ok',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/replwrap.py new/metakernel-0.23.0/metakernel/replwrap.py
--- old/metakernel-0.20.14/metakernel/replwrap.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/replwrap.py 2019-05-03 13:32:40.000000000 +0200
@@ -3,6 +3,7 @@
import re
import signal
import os
+import time
import atexit
from . import pexpect
@@ -42,13 +43,15 @@
as positional parameters, so you can use ``{}`` style formatting to
insert them into the command.
:param str new_prompt_regex: The more unique prompt to expect after the change.
- :param str stdin_prompt_regex: The regex for a stdin prompt from the
+ :param str stdin_prompt_regex: The regex for a stdin prompt from the
child process. The prompt itself will be sent to the `stdin_handler`,
so any sentinel value inserted will have to be removed by the caller.
:param str extra_init_cmd: Commands to do extra initialisation, such as
disabling pagers.
:param str prompt_emit_cmd: Optional kernel command that emits the prompt
when one is not emitted by default (typically happens on Windows only)
+ :param bool force_prompt_on_continuation: Whether to force a prompt when
+ we need to interrupt a continuation prompt.
:param bool echo: Whether the child should echo, or in the case
of Windows, whether the child does echo.
"""
@@ -59,6 +62,7 @@
stdin_prompt_regex=PEXPECT_STDIN_PROMPT,
extra_init_cmd=None,
prompt_emit_cmd=None,
+ force_prompt_on_continuation=False,
echo=False):
if isinstance(cmd_or_spawn, basestring):
self.child = pexpect.spawnu(cmd_or_spawn, echo=echo,
@@ -82,6 +86,7 @@
self.echo = echo
self.prompt_emit_cmd = prompt_emit_cmd
+ self._force_prompt_on_continuation = force_prompt_on_continuation
if prompt_change_cmd is None:
self.prompt_regex = u(prompt_regex)
@@ -117,25 +122,71 @@
def _expect_prompt(self, timeout=None):
"""Expect a prompt from the child.
"""
- stream_handler = self._stream_handler
- stdin_handler = self._stdin_handler
expects = [self.prompt_regex, self.continuation_prompt_regex,
self.stdin_prompt_regex]
- if stream_handler:
- expects += [u(self.child.crlf)]
if self.prompt_emit_cmd:
self.sendline(self.prompt_emit_cmd)
+
+ if self._stream_handler:
+ return self._expect_prompt_stream(expects, timeout)
+
while True:
pos = self.child.expect(expects, timeout=timeout)
- if pos == 2 and stdin_handler:
- resp = stdin_handler(self.child.before + self.child.after)
+ if pos < 2:
+ return pos
+ elif not self._stdin_handler:
+ raise ValueError('Stdin Requested but not stdin handler available')
+
+ resp = self._stdin_handler(line + self.child.after)
+ self.sendline(resp)
+
+ def _expect_prompt_stream(self, expects, timeout=None):
+ """Expect a prompt with streaming output.
+ """
+ expects += [u(self.child.crlf)]
+ stream_handler = self._stream_handler
+ stdin_handler = self._stdin_handler
+ t0 = time.time()
+ if timeout == -1:
+ timeout = 30
+ got_cr = False
+
+ while True:
+ if timeout is not None and time.time() - t0 > timeout:
+ raise pexpect.TIMEOUT('Timed out')
+
+ line_timeout = 0.2
+ try:
+ pos = self.child.expect(expects, timeout=line_timeout)
+ except pexpect.TIMEOUT:
+ while 1:
+ try:
+ self.child.expect([u('\r')], timeout=0)
+ stream_handler('\r', end='')
+ if got_cr:
+ stream_handler(self.child.before, end='')
+ got_cr = True
+ except pexpect.TIMEOUT:
+ break
+ continue
+
+ # Handle cr state
+ line = self.child.before
+ if got_cr:
+ line = '\r' + line
+ got_cr = False
+
+ if pos == 2:
+ if not stdin_handler:
+ raise ValueError('Stdin Requested but not stdin handler available')
+ resp = stdin_handler(line + self.child.after)
self.sendline(resp)
- elif pos == 3: # End of line received
- stream_handler(self.child.before)
+ elif pos == 3: # End of line
+ stream_handler(line)
else:
- if len(self.child.before) != 0 and stream_handler:
+ if len(line) != 0:
# prompt received, but partial line precedes it
- stream_handler(self.child.before)
+ stream_handler(line)
break
return pos
@@ -149,6 +200,10 @@
:param int timeout: How long to wait for the next prompt. -1 means the
default from the :class:`pexpect.spawn` object (default 30 seconds).
None means to wait indefinitely.
+ :param func stream_handler - A function that accepts a string to print and
+ and optional line ending.
+ :param stdin_handler - A function that prompts the user for input and
+ returns a response.
"""
# Split up multiline commands and feed them in bit-by-bit
cmdlines = command.splitlines()
@@ -172,11 +227,14 @@
# Command was fully submitted, now wait for the next prompt
if self._expect_prompt(timeout=timeout) == 1:
# We got the continuation prompt - command was incomplete
- self.interrupt()
+ self.interrupt(continuation=True)
raise ValueError("Continuation prompt found - input was incomplete:\n" + command)
+
+ if self._stream_handler:
+ return u''
return u''.join(res + [self.child.before])
- def interrupt(self):
+ def interrupt(self, continuation=False):
"""Interrupt the process and wait for a prompt.
Returns
@@ -187,12 +245,15 @@
self.child.sendintr()
else:
self.child.kill(signal.SIGINT)
+ if continuation and self._force_prompt_on_continuation:
+ self.sendline(self.prompt_change_cmd or '')
while 1:
try:
self._expect_prompt(timeout=-1)
break
except KeyboardInterrupt:
pass
+
return self.child.before
def terminate(self):
@@ -244,8 +305,6 @@
extra_init_cmd=extra_init_cmd)
-def cmd(command='cmd', prompt_regex=re.compile(r'[A-Z]:\\.*>')):
- """"Start a cmd shell and return a :class:`REPLWrapper` object."""
- if not os.name == 'nt':
- raise OSError('cmd only available on Windows')
- return REPLWrapper(command, prompt_regex, None, echo=True)
+def powershell(command='powershell', prompt_regex='>'):
+ """"Start a powershell and return a :class:`REPLWrapper` object."""
+ return REPLWrapper(command, prompt_regex, 'Function prompt {{ "{0}" }}', echo=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/tests/test_process_metakernel.py new/metakernel-0.23.0/metakernel/tests/test_process_metakernel.py
--- old/metakernel-0.20.14/metakernel/tests/test_process_metakernel.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/tests/test_process_metakernel.py 2019-04-30 11:15:55.000000000 +0200
@@ -22,3 +22,7 @@
html = HTML("some html")
kernel.Display(html)
+
+ kernel.do_execute(r'for i in {1..3};do echo -ne "$i\r"; sleep 1; done', None)
+ text = get_log_text(kernel)
+ assert r'1\r2\r3\r' in text
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel/tests/test_replwrap.py new/metakernel-0.23.0/metakernel/tests/test_replwrap.py
--- old/metakernel-0.20.14/metakernel/tests/test_replwrap.py 2018-01-23 21:41:36.000000000 +0100
+++ new/metakernel-0.23.0/metakernel/tests/test_replwrap.py 2019-04-30 11:15:55.000000000 +0200
@@ -2,6 +2,7 @@
import unittest
import re
import os
+import sys
from metakernel import pexpect, replwrap
@@ -59,7 +60,7 @@
if platform.python_implementation() == 'PyPy':
raise unittest.SkipTest("This test fails on PyPy because of REPL differences")
- p = replwrap.python()
+ p = replwrap.python(sys.executable)
res = p.run_command('4+7')
assert res.strip() == '11'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel.egg-info/PKG-INFO new/metakernel-0.23.0/metakernel.egg-info/PKG-INFO
--- old/metakernel-0.20.14/metakernel.egg-info/PKG-INFO 2018-01-23 22:30:35.000000000 +0100
+++ new/metakernel-0.23.0/metakernel.egg-info/PKG-INFO 2019-05-10 20:02:16.000000000 +0200
@@ -1,12 +1,12 @@
Metadata-Version: 1.1
Name: metakernel
-Version: 0.20.14
+Version: 0.23.0
Summary: Metakernel for Jupyter
Home-page: https://github.com/Calysto/metakernel
Author: Steven Silvester
Author-email: steven.silvester@ieee.org
License: UNKNOWN
-Description: A Jupyter/IPython kernel template which includes core magic functions (including help, command and file path completion, parallel and distributed processing, downloads, and much more).
+Description: A Jupyter kernel base class in Python which includes core magic functions (including help, command and file path completion, parallel and distributed processing, downloads, and much more).
.. image:: https://badge.fury.io/py/metakernel.png/
:target: http://badge.fury.io/py/metakernel
@@ -17,9 +17,15 @@
.. image:: https://travis-ci.org/Calysto/metakernel.svg
:target: https://travis-ci.org/Calysto/metakernel
+ .. image:: https://anaconda.org/conda-forge/metakernel/badges/version.svg
+ :target: https://anaconda.org/conda-forge/metakernel
- See IPython's docs on `wrapper kernels
- http://ipython.org/ipython-doc/dev/development/wrapperkernels.html`_.
+ .. image:: https://anaconda.org/conda-forge/metakernel/badges/downloads.svg
+ :target: https://anaconda.org/conda-forge/metakernel
+
+
+ See Jupyter's docs on `wrapper kernels
+ http://jupyter-client.readthedocs.io/en/stable/wrapperkernels.html`_.
Additional magics can be installed within the new kernel package under a `magics` subpackage.
@@ -55,25 +61,44 @@
Installation
----------------
- You can install Metakernel through `pip`:
+ You can install Metakernel through ``pip``:
+
+ .. code::bash
+
+ pip install metakernel --upgrade
+
+ Installing `metakernel` from the `conda-forge` channel can be achieved by adding `conda-forge` to your channels with:
+
+ .. code::bash
+
+ conda config --add channels conda-forge
+
+ Once the `conda-forge` channel has been enabled, `metakernel` can be installed with:
+ .. code::bash
- `pip install metakernel --upgrade`
+ conda install metakernel
+
+ It is possible to list all of the versions of `metakernel` available on your platform with:
+
+ .. code::bash
+
+ conda search metakernel --channel conda-forge
Use MetaKernel Magics in IPython
--------------------------------
- Although MetaKernel is a system for building new kernels, you can use a subset of the magics in the IPython kernel.
+ Although MetaKernel is a system for building new kernels, you can use a subset of the magics in the IPython kernel.
- .. code-block:: python
+ .. code:: python
from metakernel import register_ipython_magics
register_ipython_magics()
- Put the following in your (or a system-wide) ipython_config.py file:
+ Put the following in your (or a system-wide) ``ipython_config.py`` file:
- .. code-block:: python
+ .. code:: python
# /etc/ipython/ipython_config.py
c = get_config()
@@ -83,6 +108,102 @@
]
c.InteractiveShellApp.exec_lines = startup
+ Use MetaKernel Languages in Parallel
+
+ To use a MetaKernel language in parallel, do the following:
+
+ 1. Make sure that the Python module `ipyparallel` is installed. In the shell, type:
+
+ .. code:: bash
+
+ pip install ipyparallel
+
+
+ 2. To enable the extension in the notebook, in the shell, type:
+
+ .. code:: bash
+
+ ipcluster nbextension enable
+
+
+ 3. To start up a cluster, with 10 nodes, on a local IP address, in the shell, type:
+
+ .. code:: bash
+
+ ipcluster start --n=10 --ip=192.168.1.108
+
+
+ 4. Initialize the code to use the 10 nodes, inside the notebook from a host kernel ``MODULE`` and ``CLASSNAME`` (can be any metakernel kernel):
+
+ .. code:: bash
+
+ %parallel MODULE CLASSNAME
+
+
+ For example:
+
+ .. code:: bash
+
+ %parallel calysto_scheme CalystoScheme
+
+
+ 5. Run code in parallel, inside the notebook, type:
+
+ Execute a single line, in parallel:
+
+ .. code:: bash
+
+ %px (+ 1 1)
+
+
+ Or execute the entire cell, in parallel:
+
+ .. code:: bash
+
+ %%px
+ (* cluster_rank cluster_rank)
+
+
+ Results come back in a Python list (Scheme vector), in ``cluster_rank`` order. (This will be a JSON representation in the future).
+
+ Therefore, the above would produce the result:
+
+ .. code:: bash
+
+ #10(0 1 4 9 16 25 36 49 64 81)
+
+ You can get the results back in any of the parallel magics (``%px``, ``%%px``, or ``%pmap``) in the host kernel by accessing the variable ``_`` (single underscore), or by using the ``--set_variable VARIABLE`` flag, like so:
+
+ .. code:: bash
+
+ %%px --set_variable results
+ (* cluster_rank cluster_rank)
+
+
+ Then, in the next cell, you can access ``results``.
+
+ Notice that you can use the variable ``cluster_rank`` to partition parts of a problem so that each node is working on something different.
+
+ In the examples above, use ``-e`` to evaluate the code in the host kernel as well. Note that ``cluster_rank`` is not defined on the host machine, and that this assumes the host kernel is the same as the parallel machines.
+
+
+ Configuration
+ -------------
+ ``Metakernel`` implementations can subclasses can be configured by the user. The
+ configuration file name is determined by the ``app_name`` property of the subclass.
+ For example, in the ``Octave`` kernel, it is ``octave_kernel``. The user of the kernel can add an ``octave_kernel_config.py`` file to their
+ ``jupyter`` config path. The base ``MetaKernel`` class offers ``plot_settings`` as a configurable trait. Subclasses can defined other traits that they wish to make
+ configurable.
+
+ As an example:
+
+ .. code:: bash
+
+ cat ~/.jupyter/octave_kernel_config.py
+ # use Qt as the default backend for plots
+ c.OctaveKernel.plot_settings = dict(backend='qt')
+
+
Documentation
-----------------------
@@ -101,13 +222,11 @@
.. _History: https://github.com/Calysto/metakernel/blob/master/HISTORY.rst
-
-
Platform: UNKNOWN
Classifier: Framework :: IPython
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2
Classifier: Topic :: System :: Shells
-Requires: ipykernel (< 6.0)
+Requires: ipykernel
Requires: pexpect (>= 4.2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel.egg-info/SOURCES.txt new/metakernel-0.23.0/metakernel.egg-info/SOURCES.txt
--- old/metakernel-0.20.14/metakernel.egg-info/SOURCES.txt 2018-01-23 22:30:35.000000000 +0100
+++ new/metakernel-0.23.0/metakernel.egg-info/SOURCES.txt 2019-05-10 20:02:16.000000000 +0200
@@ -21,6 +21,7 @@
metakernel.egg-info/requires.txt
metakernel.egg-info/top_level.txt
metakernel/images/logo-32x32.png
+metakernel/images/logo-512x512.png
metakernel/images/logo-64x64.png
metakernel/magics/__init__.py
metakernel/magics/activity_magic.py
@@ -109,6 +110,7 @@
metakernel_bash/README.md
metakernel_bash/metakernel_bash.py
metakernel_bash/setup.py
+metakernel_bash/__pycache__/metakernel_bash.cpython-37.pyc
metakernel_echo/README.md
metakernel_echo/metakernel_echo.py
metakernel_echo/setup.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel.egg-info/requires.txt new/metakernel-0.23.0/metakernel.egg-info/requires.txt
--- old/metakernel-0.20.14/metakernel.egg-info/requires.txt 2018-01-23 22:30:35.000000000 +0100
+++ new/metakernel-0.23.0/metakernel.egg-info/requires.txt 2019-05-10 20:02:16.000000000 +0200
@@ -1,2 +1,2 @@
-ipykernel<6.0
+ipykernel
pexpect>=4.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel_bash/README.md new/metakernel-0.23.0/metakernel_bash/README.md
--- old/metakernel-0.20.14/metakernel_bash/README.md 2018-01-23 21:06:42.000000000 +0100
+++ new/metakernel-0.23.0/metakernel_bash/README.md 2019-04-30 11:15:55.000000000 +0200
@@ -11,7 +11,7 @@
Then, you need to install the metakernel bash kernel spec:
```shell
-python metakernel_bash install
+python -m metakernel_bash install
```
## Running
Binary files old/metakernel-0.20.14/metakernel_bash/__pycache__/metakernel_bash.cpython-37.pyc and new/metakernel-0.23.0/metakernel_bash/__pycache__/metakernel_bash.cpython-37.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel_echo/README.md new/metakernel-0.23.0/metakernel_echo/README.md
--- old/metakernel-0.20.14/metakernel_echo/README.md 2018-01-23 21:06:42.000000000 +0100
+++ new/metakernel-0.23.0/metakernel_echo/README.md 2019-04-30 11:15:55.000000000 +0200
@@ -11,7 +11,7 @@
Then, you need to install the metakernel echo kernel spec:
```shell
-python metakernel_echo install
+python -m metakernel_echo install
```
## Running
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/metakernel_python/README.md new/metakernel-0.23.0/metakernel_python/README.md
--- old/metakernel-0.20.14/metakernel_python/README.md 2018-01-23 21:06:42.000000000 +0100
+++ new/metakernel-0.23.0/metakernel_python/README.md 2019-04-30 11:15:55.000000000 +0200
@@ -11,7 +11,7 @@
Then, you need to install the metakernel kernel spec:
```shell
-python metakernel_python install
+python -m metakernel_python install
```
## Running
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metakernel-0.20.14/setup.cfg new/metakernel-0.23.0/setup.cfg
--- old/metakernel-0.20.14/setup.cfg 2018-01-23 22:30:35.000000000 +0100
+++ new/metakernel-0.23.0/setup.cfg 2019-05-10 20:02:16.000000000 +0200
@@ -9,6 +9,9 @@
[wheel]
universal = 1
+[metadata]
+license_file = LICENSE.txt
+
[egg_info]
tag_build =
tag_date = 0