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 <toddrme2...@gmail.com> + +- 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.silves...@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.md", + '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.silves...@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