Hello community,

here is the log from the commit of package python-jupyter_ipykernel for 
openSUSE:Factory checked in at 2018-09-11 17:16:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jupyter_ipykernel (Old)
 and      /work/SRC/openSUSE:Factory/.python-jupyter_ipykernel.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-jupyter_ipykernel"

Tue Sep 11 17:16:51 2018 rev:10 rq:634266 version:4.9.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-jupyter_ipykernel/python-jupyter_ipykernel.changes
        2018-02-27 16:59:53.195860727 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-jupyter_ipykernel.new/python-jupyter_ipykernel.changes
   2018-09-11 17:16:59.371438520 +0200
@@ -1,0 +2,10 @@
+Fri Sep  7 15:19:52 UTC 2018 - toddrme2...@gmail.com
+
+- Update to version 4.9.0
+  * Python 3.3 is no longer supported (:ghpull:`336`)
+  * Flush stdout/stderr in KernelApp before replacing (:ghpull:`314`)
+  * Allow preserving stdout and stderr in KernelApp (:ghpull:`315`)
+  * Override writable method on OutStream (:ghpull:`316`)
+  * Add metadata to help display matplotlib figures legibly (:ghpull:`336`)
+
+-------------------------------------------------------------------

Old:
----
  ipykernel-4.8.2.tar.gz
  python-jupyter_ipykernel-doc.changes
  python-jupyter_ipykernel-doc.spec

New:
----
  ipykernel-4.9.0.tar.gz
  ipykernel.pdf
  ipykernel.zip

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-jupyter_ipykernel.spec ++++++
--- /var/tmp/diff_new_pack.D1alrO/_old  2018-09-11 17:17:00.767436375 +0200
+++ /var/tmp/diff_new_pack.D1alrO/_new  2018-09-11 17:17:00.767436375 +0200
@@ -18,13 +18,16 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-jupyter_ipykernel
-Version:        4.8.2
+Version:        4.9.0
 Release:        0
 Summary:        IPython Kernel for Jupyter
 License:        BSD-3-Clause
 Group:          Development/Languages/Python
 Url:            https://github.com/ipython/ipykernel
-Source:         
https://files.pythonhosted.org/packages/source/i/ipykernel/ipykernel-%{version}.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/i/ipykernel/ipykernel-%{version}.tar.gz
+# Please make sure you update the documentation files at every release
+Source1:        
https://media.readthedocs.org/pdf/ipykernel/stable/ipykernel.pdf
+Source2:        
https://media.readthedocs.org/htmlzip/ipykernel/stable/ipykernel.zip
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module jupyter_client}
 BuildRequires:  %{python_module jupyter_ipython >= 4.0.0}
@@ -34,6 +37,20 @@
 BuildRequires:  fdupes
 BuildRequires:  hicolor-icon-theme
 BuildRequires:  python-rpm-macros
+BuildRequires:  unzip
+# SECTION test requirements
+BuildRequires:  %{python_module jupyter_client}
+BuildRequires:  %{python_module jupyter_ipython >= 4.0.0}
+BuildRequires:  %{python_module nose}
+BuildRequires:  %{python_module nose_warnings_filters}
+BuildRequires:  %{python_module tornado >= 4.0}
+BuildRequires:  %{python_module traitlets >= 4.1.0}
+BuildRequires:  python-mock
+BuildRequires:  python-typing
+%if 0%{?suse_version} <= 1320
+Requires:       python3-typing
+%endif
+# /SECTION
 Requires:       python-jupyter_client
 Requires:       python-jupyter_ipython >= 4.0.0
 Requires:       python-tornado >= 4.0
@@ -46,13 +63,26 @@
 Requires:       python-typing
 %endif
 BuildArch:      noarch
+
 %python_subpackages
 
 %description
 This package provides the IPython kernel for Jupyter.
 
+%package     -n python-jupyter_ipykernel-doc
+Summary:        Documentation for python-jupyter_ipykernel
+Group:          Documentation/Other
+Provides:       %{python_module jupyter_ipykernel-doc = %{version}}
+
+%description -n python-jupyter_ipykernel-doc
+Documentation and help files for python-jupyter_ipykernel.
+
 %prep
 %setup -q -n ipykernel-%{version}
+cp %{SOURCE1} .
+unzip %{SOURCE2} -d docs
+mv docs/ipykernel-* docs/html
+rm docs/html/.buildinfo
 
 %build
 %python_build
@@ -75,17 +105,19 @@
                              --prefix %{buildroot}%{_prefix}
 }
 
-%post -n %{python3_prefix}-jupyter_ipykernel
-%icon_theme_cache_post
-
-%postun -n %{python3_prefix}-jupyter_ipykernel
-%icon_theme_cache_postun
+%check
+%python_expand nosetests-%{$python_bin_suffix}
 
 %files %{python_files}
-%defattr(-,root,root,-)
-%doc COPYING.md README.md
+%doc README.md
+%license COPYING.md
 %{python_sitelib}/*
 %{_datadir}/jupyter/kernels/python_%{python_bin_suffix}/
 %python3_only %{_datadir}/icons/hicolor/*/apps/JupyterIPyKernel.*
 
+%files -n python-jupyter_ipykernel-doc
+%license COPYING.md
+%doc ipykernel.pdf
+%doc docs/html
+
 %changelog

++++++ ipykernel-4.8.2.tar.gz -> ipykernel-4.9.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/PKG-INFO new/ipykernel-4.9.0/PKG-INFO
--- old/ipykernel-4.8.2/PKG-INFO        2018-02-19 17:18:51.000000000 +0100
+++ new/ipykernel-4.9.0/PKG-INFO        2018-08-29 20:43:51.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: ipykernel
-Version: 4.8.2
+Version: 4.9.0
 Summary: IPython Kernel for Jupyter
 Home-page: http://ipython.org
 Author: IPython Development Team
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/docs/changelog.rst 
new/ipykernel-4.9.0/docs/changelog.rst
--- old/ipykernel-4.8.2/docs/changelog.rst      2018-02-19 17:17:59.000000000 
+0100
+++ new/ipykernel-4.9.0/docs/changelog.rst      2018-08-29 20:43:03.000000000 
+0200
@@ -1,6 +1,21 @@
 Changes in IPython kernel
 =========================
 
+4.9
+---
+
+4.9.0
+*****
+
+`4.9.0 on GitHub <https://github.com/ipython/ipykernel/milestones/4.9>`__
+
+- Python 3.3 is no longer supported (:ghpull:`336`)
+- Flush stdout/stderr in KernelApp before replacing (:ghpull:`314`)
+- Allow preserving stdout and stderr in KernelApp (:ghpull:`315`)
+- Override writable method on OutStream (:ghpull:`316`)
+- Add metadata to help display matplotlib figures legibly (:ghpull:`336`)
+
+
 4.8
 ---
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ipykernel-4.8.2/examples/Embedding/inprocess_qtconsole.py 
new/ipykernel-4.9.0/examples/Embedding/inprocess_qtconsole.py
--- old/ipykernel-4.8.2/examples/Embedding/inprocess_qtconsole.py       
2015-04-09 10:09:32.000000000 +0200
+++ new/ipykernel-4.9.0/examples/Embedding/inprocess_qtconsole.py       
1970-01-01 01:00:00.000000000 +0100
@@ -1,46 +0,0 @@
-from __future__ import print_function
-import os
-
-from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
-from IPython.qt.inprocess import QtInProcessKernelManager
-from IPython.lib import guisupport
-
-
-def print_process_id():
-    print('Process ID is:', os.getpid())
-
-
-def main():
-    # Print the ID of the main process
-    print_process_id()
-
-    app = guisupport.get_app_qt4()
-
-    # Create an in-process kernel
-    # >>> print_process_id()
-    # will print the same process ID as the main process
-    kernel_manager = QtInProcessKernelManager()
-    kernel_manager.start_kernel()
-    kernel = kernel_manager.kernel
-    kernel.gui = 'qt4'
-    kernel.shell.push({'foo': 43, 'print_process_id': print_process_id})
-
-    kernel_client = kernel_manager.client()
-    kernel_client.start_channels()
-
-    def stop():
-        kernel_client.stop_channels()
-        kernel_manager.shutdown_kernel()
-        app.exit()
-
-    control = RichIPythonWidget()
-    control.kernel_manager = kernel_manager
-    control.kernel_client = kernel_client
-    control.exit_requested.connect(stop)
-    control.show()
-
-    guisupport.start_event_loop_qt4(app)
-
-
-if __name__ == '__main__':
-    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ipykernel-4.8.2/examples/Embedding/inprocess_terminal.py 
new/ipykernel-4.9.0/examples/Embedding/inprocess_terminal.py
--- old/ipykernel-4.8.2/examples/Embedding/inprocess_terminal.py        
2015-04-09 10:09:32.000000000 +0200
+++ new/ipykernel-4.9.0/examples/Embedding/inprocess_terminal.py        
1970-01-01 01:00:00.000000000 +0100
@@ -1,31 +0,0 @@
-from __future__ import print_function
-import os
-
-from IPython.kernel.inprocess import InProcessKernelManager
-from IPython.terminal.console.interactiveshell import 
ZMQTerminalInteractiveShell
-
-
-def print_process_id():
-    print('Process ID is:', os.getpid())
-
-
-def main():
-    print_process_id()
-
-    # Create an in-process kernel
-    # >>> print_process_id()
-    # will print the same process ID as the main process
-    kernel_manager = InProcessKernelManager()
-    kernel_manager.start_kernel()
-    kernel = kernel_manager.kernel
-    kernel.gui = 'qt4'
-    kernel.shell.push({'foo': 43, 'print_process_id': print_process_id})
-    client = kernel_manager.client()
-    client.start_channels()
-
-    shell = ZMQTerminalInteractiveShell(manager=kernel_manager, client=client)
-    shell.mainloop()
-
-
-if __name__ == '__main__':
-    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ipykernel-4.8.2/examples/Embedding/internal_ipkernel.py 
new/ipykernel-4.9.0/examples/Embedding/internal_ipkernel.py
--- old/ipykernel-4.8.2/examples/Embedding/internal_ipkernel.py 2015-09-22 
09:39:51.000000000 +0200
+++ new/ipykernel-4.9.0/examples/Embedding/internal_ipkernel.py 1970-01-01 
01:00:00.000000000 +0100
@@ -1,55 +0,0 @@
-#-----------------------------------------------------------------------------
-# Imports
-#-----------------------------------------------------------------------------
-
-import sys
-
-from IPython.lib.kernel import connect_qtconsole
-from IPython.kernel.zmq.kernelapp import IPKernelApp
-
-#-----------------------------------------------------------------------------
-# Functions and classes
-#-----------------------------------------------------------------------------
-def mpl_kernel(gui):
-    """Launch and return an IPython kernel with matplotlib support for the 
desired gui
-    """
-    kernel = IPKernelApp.instance()
-    kernel.initialize(['python', '--matplotlib=%s' % gui,
-                       #'--log-level=10'
-                       ])
-    return kernel
-
-
-class InternalIPKernel(object):
-
-    def init_ipkernel(self, backend):
-        # Start IPython kernel with GUI event loop and mpl support
-        self.ipkernel = mpl_kernel(backend)
-        # To create and track active qt consoles
-        self.consoles = []
-        
-        # This application will also act on the shell user namespace
-        self.namespace = self.ipkernel.shell.user_ns
-
-        # Example: a variable that will be seen by the user in the shell, and
-        # that the GUI modifies (the 'Counter++' button increments it):
-        self.namespace['app_counter'] = 0
-        #self.namespace['ipkernel'] = self.ipkernel  # dbg
-
-    def print_namespace(self, evt=None):
-        print("\n***Variables in User namespace***")
-        for k, v in self.namespace.items():
-            if not k.startswith('_'):
-                print('%s -> %r' % (k, v))
-        sys.stdout.flush()
-
-    def new_qt_console(self, evt=None):
-        """start a new qtconsole connected to our kernel"""
-        return connect_qtconsole(self.ipkernel.abs_connection_file, 
profile=self.ipkernel.profile)
-
-    def count(self, evt=None):
-        self.namespace['app_counter'] += 1
-
-    def cleanup_consoles(self, evt=None):
-        for c in self.consoles:
-            c.kill()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/examples/Embedding/ipkernel_qtapp.py 
new/ipykernel-4.9.0/examples/Embedding/ipkernel_qtapp.py
--- old/ipykernel-4.8.2/examples/Embedding/ipkernel_qtapp.py    2015-04-09 
10:09:32.000000000 +0200
+++ new/ipykernel-4.9.0/examples/Embedding/ipkernel_qtapp.py    1970-01-01 
01:00:00.000000000 +0100
@@ -1,75 +0,0 @@
-#!/usr/bin/env python
-"""Example integrating an IPython kernel into a GUI App.
-
-This trivial GUI application internally starts an IPython kernel, to which Qt
-consoles can be connected either by the user at the command line or started
-from the GUI itself, via a button.  The GUI can also manipulate one variable in
-the kernel's namespace, and print the namespace to the console.
-
-Play with it by running the script and then opening one or more consoles, and
-pushing the 'Counter++' and 'Namespace' buttons.
-
-Upon exit, it should automatically close all consoles opened from the GUI.
-
-Consoles attached separately from a terminal will not be terminated, though
-they will notice that their kernel died.
-"""
-#-----------------------------------------------------------------------------
-# Imports
-#-----------------------------------------------------------------------------
-
-from PyQt4 import Qt
-
-from internal_ipkernel import InternalIPKernel
-
-#-----------------------------------------------------------------------------
-# Functions and classes
-#-----------------------------------------------------------------------------
-class SimpleWindow(Qt.QWidget, InternalIPKernel):
-
-    def __init__(self, app):
-        Qt.QWidget.__init__(self)
-        self.app = app
-        self.add_widgets()
-        self.init_ipkernel('qt')
-
-    def add_widgets(self):
-        self.setGeometry(300, 300, 400, 70)
-        self.setWindowTitle('IPython in your app')
-
-        # Add simple buttons:
-        console = Qt.QPushButton('Qt Console', self)
-        console.setGeometry(10, 10, 100, 35)
-        self.connect(console, Qt.SIGNAL('clicked()'), self.new_qt_console)
-
-        namespace = Qt.QPushButton('Namespace', self)
-        namespace.setGeometry(120, 10, 100, 35)
-        self.connect(namespace, Qt.SIGNAL('clicked()'), self.print_namespace)
-
-        count = Qt.QPushButton('Count++', self)
-        count.setGeometry(230, 10, 80, 35)
-        self.connect(count, Qt.SIGNAL('clicked()'), self.count)
-
-        # Quit and cleanup
-        quit = Qt.QPushButton('Quit', self)
-        quit.setGeometry(320, 10, 60, 35)
-        self.connect(quit, Qt.SIGNAL('clicked()'), Qt.qApp, Qt.SLOT('quit()'))
-
-        self.app.connect(self.app, Qt.SIGNAL("lastWindowClosed()"),
-                         self.app, Qt.SLOT("quit()"))
-
-        self.app.aboutToQuit.connect(self.cleanup_consoles)
-
-#-----------------------------------------------------------------------------
-# Main script
-#-----------------------------------------------------------------------------
-
-if __name__ == "__main__":
-    app = Qt.QApplication([]) 
-    # Create our window
-    win = SimpleWindow(app)
-    win.show()
-    
-    # Very important, IPython-specific step: this gets GUI event loop
-    # integration going, and it replaces calling app.exec_()
-    win.ipkernel.start()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/examples/Embedding/ipkernel_wxapp.py 
new/ipykernel-4.9.0/examples/Embedding/ipkernel_wxapp.py
--- old/ipykernel-4.8.2/examples/Embedding/ipkernel_wxapp.py    2015-04-09 
10:09:32.000000000 +0200
+++ new/ipykernel-4.9.0/examples/Embedding/ipkernel_wxapp.py    1970-01-01 
01:00:00.000000000 +0100
@@ -1,119 +0,0 @@
-#!/usr/bin/env python
-"""Example integrating an IPython kernel into a GUI App.
-
-This trivial GUI application internally starts an IPython kernel, to which Qt
-consoles can be connected either by the user at the command line or started
-from the GUI itself, via a button.  The GUI can also manipulate one variable in
-the kernel's namespace, and print the namespace to the console.
-
-Play with it by running the script and then opening one or more consoles, and
-pushing the 'Counter++' and 'Namespace' buttons.
-
-Upon exit, it should automatically close all consoles opened from the GUI.
-
-Consoles attached separately from a terminal will not be terminated, though
-they will notice that their kernel died.
-
-Ref: Modified from wxPython source code wxPython/samples/simple/simple.py
-"""
-#-----------------------------------------------------------------------------
-# Imports
-#-----------------------------------------------------------------------------
-import sys
-
-import wx
-
-from internal_ipkernel import InternalIPKernel
-
-#-----------------------------------------------------------------------------
-# Functions and classes
-#-----------------------------------------------------------------------------
-
-class MyFrame(wx.Frame, InternalIPKernel):
-    """
-    This is MyFrame.  It just shows a few controls on a wxPanel,
-    and has a simple menu.
-    """
-
-    def __init__(self, parent, title):
-        wx.Frame.__init__(self, parent, -1, title,
-                          pos=(150, 150), size=(350, 285))
-
-        # Create the menubar
-        menuBar = wx.MenuBar()
-
-        # and a menu 
-        menu = wx.Menu()
-
-        # add an item to the menu, using \tKeyName automatically
-        # creates an accelerator, the third param is some help text
-        # that will show up in the statusbar
-        menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")
-
-        # bind the menu event to an event handler
-        self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)
-
-        # and put the menu on the menubar
-        menuBar.Append(menu, "&File")
-        self.SetMenuBar(menuBar)
-
-        self.CreateStatusBar()
-
-        # Now create the Panel to put the other controls on.
-        panel = wx.Panel(self)
-
-        # and a few controls
-        text = wx.StaticText(panel, -1, "Hello World!")
-        text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
-        text.SetSize(text.GetBestSize())
-        qtconsole_btn = wx.Button(panel, -1, "Qt Console")
-        ns_btn = wx.Button(panel, -1, "Namespace")
-        count_btn = wx.Button(panel, -1, "Count++")
-        close_btn = wx.Button(panel, -1, "Quit")
-
-        # bind the button events to handlers
-        self.Bind(wx.EVT_BUTTON, self.new_qt_console, qtconsole_btn)
-        self.Bind(wx.EVT_BUTTON, self.print_namespace, ns_btn)
-        self.Bind(wx.EVT_BUTTON, self.count, count_btn)
-        self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, close_btn)
-
-        # Use a sizer to layout the controls, stacked vertically and with
-        # a 10 pixel border around each
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        for ctrl in [text, qtconsole_btn, ns_btn, count_btn, close_btn]:
-            sizer.Add(ctrl, 0, wx.ALL, 10)
-        panel.SetSizer(sizer)
-        panel.Layout()
-
-        # Start the IPython kernel with gui support
-        self.init_ipkernel('wx')
-
-    def OnTimeToClose(self, evt):
-        """Event handler for the button click."""
-        print("See ya later!")
-        sys.stdout.flush()
-        self.cleanup_consoles(evt)
-        self.Close()
-        # Not sure why, but our IPython kernel seems to prevent normal WX
-        # shutdown, so an explicit exit() call is needed.
-        sys.exit()
-
-
-class MyApp(wx.App):
-    def OnInit(self):
-        frame = MyFrame(None, "Simple wxPython App")
-        self.SetTopWindow(frame)
-        frame.Show(True)
-        self.ipkernel = frame.ipkernel
-        return True
-
-#-----------------------------------------------------------------------------
-# Main script
-#-----------------------------------------------------------------------------
-
-if __name__ == '__main__':
-    app = MyApp(redirect=False, clearSigInt=False)
-
-    # Very important, IPython-specific step: this gets GUI event loop
-    # integration going, and it replaces calling app.MainLoop()
-    app.ipkernel.start()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ipykernel-4.8.2/examples/embedding/inprocess_qtconsole.py 
new/ipykernel-4.9.0/examples/embedding/inprocess_qtconsole.py
--- old/ipykernel-4.8.2/examples/embedding/inprocess_qtconsole.py       
1970-01-01 01:00:00.000000000 +0100
+++ new/ipykernel-4.9.0/examples/embedding/inprocess_qtconsole.py       
2018-08-29 20:43:01.000000000 +0200
@@ -0,0 +1,46 @@
+from __future__ import print_function
+import os
+
+from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
+from IPython.qt.inprocess import QtInProcessKernelManager
+from IPython.lib import guisupport
+
+
+def print_process_id():
+    print('Process ID is:', os.getpid())
+
+
+def main():
+    # Print the ID of the main process
+    print_process_id()
+
+    app = guisupport.get_app_qt4()
+
+    # Create an in-process kernel
+    # >>> print_process_id()
+    # will print the same process ID as the main process
+    kernel_manager = QtInProcessKernelManager()
+    kernel_manager.start_kernel()
+    kernel = kernel_manager.kernel
+    kernel.gui = 'qt4'
+    kernel.shell.push({'foo': 43, 'print_process_id': print_process_id})
+
+    kernel_client = kernel_manager.client()
+    kernel_client.start_channels()
+
+    def stop():
+        kernel_client.stop_channels()
+        kernel_manager.shutdown_kernel()
+        app.exit()
+
+    control = RichIPythonWidget()
+    control.kernel_manager = kernel_manager
+    control.kernel_client = kernel_client
+    control.exit_requested.connect(stop)
+    control.show()
+
+    guisupport.start_event_loop_qt4(app)
+
+
+if __name__ == '__main__':
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ipykernel-4.8.2/examples/embedding/inprocess_terminal.py 
new/ipykernel-4.9.0/examples/embedding/inprocess_terminal.py
--- old/ipykernel-4.8.2/examples/embedding/inprocess_terminal.py        
1970-01-01 01:00:00.000000000 +0100
+++ new/ipykernel-4.9.0/examples/embedding/inprocess_terminal.py        
2018-08-29 20:43:01.000000000 +0200
@@ -0,0 +1,31 @@
+from __future__ import print_function
+import os
+
+from IPython.kernel.inprocess import InProcessKernelManager
+from IPython.terminal.console.interactiveshell import 
ZMQTerminalInteractiveShell
+
+
+def print_process_id():
+    print('Process ID is:', os.getpid())
+
+
+def main():
+    print_process_id()
+
+    # Create an in-process kernel
+    # >>> print_process_id()
+    # will print the same process ID as the main process
+    kernel_manager = InProcessKernelManager()
+    kernel_manager.start_kernel()
+    kernel = kernel_manager.kernel
+    kernel.gui = 'qt4'
+    kernel.shell.push({'foo': 43, 'print_process_id': print_process_id})
+    client = kernel_manager.client()
+    client.start_channels()
+
+    shell = ZMQTerminalInteractiveShell(manager=kernel_manager, client=client)
+    shell.mainloop()
+
+
+if __name__ == '__main__':
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ipykernel-4.8.2/examples/embedding/internal_ipkernel.py 
new/ipykernel-4.9.0/examples/embedding/internal_ipkernel.py
--- old/ipykernel-4.8.2/examples/embedding/internal_ipkernel.py 1970-01-01 
01:00:00.000000000 +0100
+++ new/ipykernel-4.9.0/examples/embedding/internal_ipkernel.py 2018-08-29 
20:43:01.000000000 +0200
@@ -0,0 +1,55 @@
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+
+import sys
+
+from IPython.lib.kernel import connect_qtconsole
+from IPython.kernel.zmq.kernelapp import IPKernelApp
+
+#-----------------------------------------------------------------------------
+# Functions and classes
+#-----------------------------------------------------------------------------
+def mpl_kernel(gui):
+    """Launch and return an IPython kernel with matplotlib support for the 
desired gui
+    """
+    kernel = IPKernelApp.instance()
+    kernel.initialize(['python', '--matplotlib=%s' % gui,
+                       #'--log-level=10'
+                       ])
+    return kernel
+
+
+class InternalIPKernel(object):
+
+    def init_ipkernel(self, backend):
+        # Start IPython kernel with GUI event loop and mpl support
+        self.ipkernel = mpl_kernel(backend)
+        # To create and track active qt consoles
+        self.consoles = []
+        
+        # This application will also act on the shell user namespace
+        self.namespace = self.ipkernel.shell.user_ns
+
+        # Example: a variable that will be seen by the user in the shell, and
+        # that the GUI modifies (the 'Counter++' button increments it):
+        self.namespace['app_counter'] = 0
+        #self.namespace['ipkernel'] = self.ipkernel  # dbg
+
+    def print_namespace(self, evt=None):
+        print("\n***Variables in User namespace***")
+        for k, v in self.namespace.items():
+            if not k.startswith('_'):
+                print('%s -> %r' % (k, v))
+        sys.stdout.flush()
+
+    def new_qt_console(self, evt=None):
+        """start a new qtconsole connected to our kernel"""
+        return connect_qtconsole(self.ipkernel.abs_connection_file, 
profile=self.ipkernel.profile)
+
+    def count(self, evt=None):
+        self.namespace['app_counter'] += 1
+
+    def cleanup_consoles(self, evt=None):
+        for c in self.consoles:
+            c.kill()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/examples/embedding/ipkernel_qtapp.py 
new/ipykernel-4.9.0/examples/embedding/ipkernel_qtapp.py
--- old/ipykernel-4.8.2/examples/embedding/ipkernel_qtapp.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/ipykernel-4.9.0/examples/embedding/ipkernel_qtapp.py    2018-08-29 
20:43:01.000000000 +0200
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+"""Example integrating an IPython kernel into a GUI App.
+
+This trivial GUI application internally starts an IPython kernel, to which Qt
+consoles can be connected either by the user at the command line or started
+from the GUI itself, via a button.  The GUI can also manipulate one variable in
+the kernel's namespace, and print the namespace to the console.
+
+Play with it by running the script and then opening one or more consoles, and
+pushing the 'Counter++' and 'Namespace' buttons.
+
+Upon exit, it should automatically close all consoles opened from the GUI.
+
+Consoles attached separately from a terminal will not be terminated, though
+they will notice that their kernel died.
+"""
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+
+from PyQt4 import Qt
+
+from internal_ipkernel import InternalIPKernel
+
+#-----------------------------------------------------------------------------
+# Functions and classes
+#-----------------------------------------------------------------------------
+class SimpleWindow(Qt.QWidget, InternalIPKernel):
+
+    def __init__(self, app):
+        Qt.QWidget.__init__(self)
+        self.app = app
+        self.add_widgets()
+        self.init_ipkernel('qt')
+
+    def add_widgets(self):
+        self.setGeometry(300, 300, 400, 70)
+        self.setWindowTitle('IPython in your app')
+
+        # Add simple buttons:
+        console = Qt.QPushButton('Qt Console', self)
+        console.setGeometry(10, 10, 100, 35)
+        self.connect(console, Qt.SIGNAL('clicked()'), self.new_qt_console)
+
+        namespace = Qt.QPushButton('Namespace', self)
+        namespace.setGeometry(120, 10, 100, 35)
+        self.connect(namespace, Qt.SIGNAL('clicked()'), self.print_namespace)
+
+        count = Qt.QPushButton('Count++', self)
+        count.setGeometry(230, 10, 80, 35)
+        self.connect(count, Qt.SIGNAL('clicked()'), self.count)
+
+        # Quit and cleanup
+        quit = Qt.QPushButton('Quit', self)
+        quit.setGeometry(320, 10, 60, 35)
+        self.connect(quit, Qt.SIGNAL('clicked()'), Qt.qApp, Qt.SLOT('quit()'))
+
+        self.app.connect(self.app, Qt.SIGNAL("lastWindowClosed()"),
+                         self.app, Qt.SLOT("quit()"))
+
+        self.app.aboutToQuit.connect(self.cleanup_consoles)
+
+#-----------------------------------------------------------------------------
+# Main script
+#-----------------------------------------------------------------------------
+
+if __name__ == "__main__":
+    app = Qt.QApplication([]) 
+    # Create our window
+    win = SimpleWindow(app)
+    win.show()
+    
+    # Very important, IPython-specific step: this gets GUI event loop
+    # integration going, and it replaces calling app.exec_()
+    win.ipkernel.start()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/examples/embedding/ipkernel_wxapp.py 
new/ipykernel-4.9.0/examples/embedding/ipkernel_wxapp.py
--- old/ipykernel-4.8.2/examples/embedding/ipkernel_wxapp.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/ipykernel-4.9.0/examples/embedding/ipkernel_wxapp.py    2018-08-29 
20:43:01.000000000 +0200
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+"""Example integrating an IPython kernel into a GUI App.
+
+This trivial GUI application internally starts an IPython kernel, to which Qt
+consoles can be connected either by the user at the command line or started
+from the GUI itself, via a button.  The GUI can also manipulate one variable in
+the kernel's namespace, and print the namespace to the console.
+
+Play with it by running the script and then opening one or more consoles, and
+pushing the 'Counter++' and 'Namespace' buttons.
+
+Upon exit, it should automatically close all consoles opened from the GUI.
+
+Consoles attached separately from a terminal will not be terminated, though
+they will notice that their kernel died.
+
+Ref: Modified from wxPython source code wxPython/samples/simple/simple.py
+"""
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+import sys
+
+import wx
+
+from internal_ipkernel import InternalIPKernel
+
+#-----------------------------------------------------------------------------
+# Functions and classes
+#-----------------------------------------------------------------------------
+
+class MyFrame(wx.Frame, InternalIPKernel):
+    """
+    This is MyFrame.  It just shows a few controls on a wxPanel,
+    and has a simple menu.
+    """
+
+    def __init__(self, parent, title):
+        wx.Frame.__init__(self, parent, -1, title,
+                          pos=(150, 150), size=(350, 285))
+
+        # Create the menubar
+        menuBar = wx.MenuBar()
+
+        # and a menu 
+        menu = wx.Menu()
+
+        # add an item to the menu, using \tKeyName automatically
+        # creates an accelerator, the third param is some help text
+        # that will show up in the statusbar
+        menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")
+
+        # bind the menu event to an event handler
+        self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)
+
+        # and put the menu on the menubar
+        menuBar.Append(menu, "&File")
+        self.SetMenuBar(menuBar)
+
+        self.CreateStatusBar()
+
+        # Now create the Panel to put the other controls on.
+        panel = wx.Panel(self)
+
+        # and a few controls
+        text = wx.StaticText(panel, -1, "Hello World!")
+        text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
+        text.SetSize(text.GetBestSize())
+        qtconsole_btn = wx.Button(panel, -1, "Qt Console")
+        ns_btn = wx.Button(panel, -1, "Namespace")
+        count_btn = wx.Button(panel, -1, "Count++")
+        close_btn = wx.Button(panel, -1, "Quit")
+
+        # bind the button events to handlers
+        self.Bind(wx.EVT_BUTTON, self.new_qt_console, qtconsole_btn)
+        self.Bind(wx.EVT_BUTTON, self.print_namespace, ns_btn)
+        self.Bind(wx.EVT_BUTTON, self.count, count_btn)
+        self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, close_btn)
+
+        # Use a sizer to layout the controls, stacked vertically and with
+        # a 10 pixel border around each
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        for ctrl in [text, qtconsole_btn, ns_btn, count_btn, close_btn]:
+            sizer.Add(ctrl, 0, wx.ALL, 10)
+        panel.SetSizer(sizer)
+        panel.Layout()
+
+        # Start the IPython kernel with gui support
+        self.init_ipkernel('wx')
+
+    def OnTimeToClose(self, evt):
+        """Event handler for the button click."""
+        print("See ya later!")
+        sys.stdout.flush()
+        self.cleanup_consoles(evt)
+        self.Close()
+        # Not sure why, but our IPython kernel seems to prevent normal WX
+        # shutdown, so an explicit exit() call is needed.
+        sys.exit()
+
+
+class MyApp(wx.App):
+    def OnInit(self):
+        frame = MyFrame(None, "Simple wxPython App")
+        self.SetTopWindow(frame)
+        frame.Show(True)
+        self.ipkernel = frame.ipkernel
+        return True
+
+#-----------------------------------------------------------------------------
+# Main script
+#-----------------------------------------------------------------------------
+
+if __name__ == '__main__':
+    app = MyApp(redirect=False, clearSigInt=False)
+
+    # Very important, IPython-specific step: this gets GUI event loop
+    # integration going, and it replaces calling app.MainLoop()
+    app.ipkernel.start()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/ipykernel/_version.py 
new/ipykernel-4.9.0/ipykernel/_version.py
--- old/ipykernel-4.8.2/ipykernel/_version.py   2018-02-19 17:18:28.000000000 
+0100
+++ new/ipykernel-4.9.0/ipykernel/_version.py   2018-08-29 20:43:03.000000000 
+0200
@@ -1,4 +1,4 @@
-version_info = (4, 8, 2)
+version_info = (4, 9, 0)
 __version__ = '.'.join(map(str, version_info))
 
 kernel_protocol_version_info = (5, 1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/ipykernel/comm/manager.py 
new/ipykernel-4.9.0/ipykernel/comm/manager.py
--- old/ipykernel-4.8.2/ipykernel/comm/manager.py       2016-11-30 
10:07:29.000000000 +0100
+++ new/ipykernel-4.9.0/ipykernel/comm/manager.py       2018-08-29 
20:43:01.000000000 +0200
@@ -66,7 +66,7 @@
         try:
             return self.comms[comm_id]
         except KeyError:
-            self.log.warn("No such comm: %s", comm_id)
+            self.log.warning("No such comm: %s", comm_id)
             if self.log.isEnabledFor(logging.DEBUG):
                 # don't create the list of keys if debug messages aren't 
enabled
                 self.log.debug("Current comms: %s", list(self.comms.keys()))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/ipykernel/iostream.py 
new/ipykernel-4.9.0/ipykernel/iostream.py
--- old/ipykernel-4.8.2/ipykernel/iostream.py   2017-12-12 16:23:23.000000000 
+0100
+++ new/ipykernel-4.9.0/ipykernel/iostream.py   2018-08-29 20:43:01.000000000 
+0200
@@ -276,7 +276,7 @@
     topic = None
     encoding = 'UTF-8'
 
-    def __init__(self, session, pub_thread, name, pipe=None):
+    def __init__(self, session, pub_thread, name, pipe=None, echo=None):
         if pipe is not None:
             warnings.warn("pipe argument to OutStream is deprecated and 
ignored",
                 DeprecationWarning)
@@ -296,6 +296,13 @@
         self._flush_pending = False
         self._io_loop = pub_thread.io_loop
         self._new_buffer()
+        self.echo = None
+
+        if echo:
+            if hasattr(echo, 'read') and hasattr(echo, 'write'):
+                self.echo = echo
+            else:
+                raise ValueError("echo argument must be a file like object")
 
     def _is_master_process(self):
         return os.getpid() == self._master_pid
@@ -353,6 +360,15 @@
         unless the thread has been destroyed (e.g. forked subprocess).
         """
         self._flush_pending = False
+
+        if self.echo is not None:
+            try:
+                self.echo.flush()
+            except OSError as e:
+                if self.echo is not sys.__stderr__:
+                    print("Flush failed: {}".format(e),
+                          file=sys.__stderr__)
+
         data = self._flush_buffer()
         if data:
             # FIXME: this disables Session's fork-safe check,
@@ -364,6 +380,14 @@
                 parent=self.parent_header, ident=self.topic)
 
     def write(self, string):
+        if self.echo is not None:
+            try:
+                self.echo.write(string)
+            except OSError as e:
+                if self.echo is not sys.__stderr__:
+                    print("Write failed: {}".format(e),
+                          file=sys.__stderr__)
+
         if self.pub_thread is None:
             raise ValueError('I/O operation on closed file')
         else:
@@ -390,6 +414,9 @@
             for string in sequence:
                 self.write(string)
 
+    def writable(self):
+        return True
+
     def _flush_buffer(self):
         """clear the current buffer and return the current buffer data.
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/ipykernel/kernelapp.py 
new/ipykernel-4.9.0/ipykernel/kernelapp.py
--- old/ipykernel-4.8.2/ipykernel/kernelapp.py  2018-02-16 12:58:10.000000000 
+0100
+++ new/ipykernel-4.9.0/ipykernel/kernelapp.py  2018-08-29 20:43:01.000000000 
+0200
@@ -139,6 +139,7 @@
     # streams, etc.
     no_stdout = Bool(False, help="redirect stdout to the null 
device").tag(config=True)
     no_stderr = Bool(False, help="redirect stderr to the null 
device").tag(config=True)
+    quiet = Bool(True, help="Only send stdout/stderr to output 
stream").tag(config=True)
     outstream_class = DottedObjectName('ipykernel.iostream.OutStream',
         help="The importstring for the OutStream factory").tag(config=True)
     displayhook_class = 
DottedObjectName('ipykernel.displayhook.ZMQDisplayHook',
@@ -322,8 +323,18 @@
         """Redirect input streams and set a display hook."""
         if self.outstream_class:
             outstream_factory = import_item(str(self.outstream_class))
-            sys.stdout = outstream_factory(self.session, self.iopub_thread, 
u'stdout')
-            sys.stderr = outstream_factory(self.session, self.iopub_thread, 
u'stderr')
+            sys.stdout.flush()
+
+            e_stdout = None if self.quiet else sys.__stdout__
+            e_stderr = None if self.quiet else sys.__stderr__
+
+            sys.stdout = outstream_factory(self.session, self.iopub_thread,
+                                           u'stdout',
+                                           echo=e_stdout)
+            sys.stderr.flush()
+            sys.stderr = outstream_factory(self.session, self.iopub_thread,
+                                           u'stderr',
+                                           echo=e_stderr)
         if self.displayhook_class:
             displayhook_factory = import_item(str(self.displayhook_class))
             self.displayhook = displayhook_factory(self.session, 
self.iopub_socket)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/ipykernel/kernelbase.py 
new/ipykernel-4.9.0/ipykernel/kernelbase.py
--- old/ipykernel-4.8.2/ipykernel/kernelbase.py 2018-01-16 19:24:31.000000000 
+0100
+++ new/ipykernel-4.9.0/ipykernel/kernelbase.py 2018-08-29 20:43:01.000000000 
+0200
@@ -225,7 +225,7 @@
 
         handler = self.shell_handlers.get(msg_type, None)
         if handler is None:
-            self.log.warn("Unknown message type: %r", msg_type)
+            self.log.warning("Unknown message type: %r", msg_type)
         else:
             self.log.debug("%s: %s", msg_type, msg)
             self.pre_handler_hook()
@@ -563,7 +563,7 @@
     
#---------------------------------------------------------------------------
 
     def apply_request(self, stream, ident, parent):
-        self.log.warn("""apply_request is deprecated in kernel_base, moving to 
ipyparallel.""")
+        self.log.warning("apply_request is deprecated in kernel_base, moving 
to ipyparallel.")
         try:
             content = parent[u'content']
             bufs = parent[u'buffers']
@@ -595,7 +595,7 @@
 
     def abort_request(self, stream, ident, parent):
         """abort a specific msg by id"""
-        self.log.warn("abort_request is deprecated in kernel_base. It os only 
part of IPython parallel")
+        self.log.warning("abort_request is deprecated in kernel_base. It os 
only part of IPython parallel")
         msg_ids = parent['content'].get('msg_ids', None)
         if isinstance(msg_ids, string_types):
             msg_ids = [msg_ids]
@@ -611,7 +611,7 @@
 
     def clear_request(self, stream, idents, parent):
         """Clear our namespace."""
-        self.log.warn("clear_request is deprecated in kernel_base. It os only 
part of IPython parallel")
+        self.log.warning("clear_request is deprecated in kernel_base. It os 
only part of IPython parallel")
         content = self.do_clear()
         self.session.send(stream, 'clear_reply', ident=idents, parent=parent,
                 content = content)
@@ -728,7 +728,7 @@
             try:
                 ident, reply = self.session.recv(self.stdin_socket, 0)
             except Exception:
-                self.log.warn("Invalid Message:", exc_info=True)
+                self.log.warning("Invalid Message:", exc_info=True)
             except KeyboardInterrupt:
                 # re-raise KeyboardInterrupt, to truncate traceback
                 raise KeyboardInterrupt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/ipykernel/pylab/backend_inline.py 
new/ipykernel-4.9.0/ipykernel/pylab/backend_inline.py
--- old/ipykernel-4.8.2/ipykernel/pylab/backend_inline.py       2017-10-30 
14:30:42.000000000 +0100
+++ new/ipykernel-4.9.0/ipykernel/pylab/backend_inline.py       2018-08-29 
20:43:03.000000000 +0200
@@ -7,6 +7,7 @@
 
 import matplotlib
 from matplotlib.backends.backend_agg import new_figure_manager, 
FigureCanvasAgg # analysis: ignore
+from matplotlib import colors
 from matplotlib._pylab_helpers import Gcf
 
 from IPython.core.getipython import get_ipython
@@ -33,7 +34,10 @@
         close = InlineBackend.instance().close_figures
     try:
         for figure_manager in Gcf.get_all_fig_managers():
-            display(figure_manager.canvas.figure)
+            display(
+                figure_manager.canvas.figure,
+                metadata=_fetch_figure_metadata(figure_manager.canvas.figure)
+            )
     finally:
         show._to_draw = []
         # only call close('all') if any to close
@@ -72,7 +76,7 @@
 
     if not hasattr(fig, 'show'):
         # Queue up `fig` for display
-        fig.show = lambda *a: display(fig)
+        fig.show = lambda *a: display(fig, 
metadata=_fetch_figure_metadata(fig))
 
     # If matplotlib was manually set to non-interactive mode, this function
     # should be a no-op (otherwise we'll generate duplicate plots, since a user
@@ -124,7 +128,7 @@
         active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()])
         for fig in [ fig for fig in show._to_draw if fig in active ]:
             try:
-                display(fig)
+                display(fig, metadata=_fetch_figure_metadata(fig))
             except Exception as e:
                 # safely show traceback if in IPython, else raise
                 ip = get_ipython()
@@ -163,3 +167,30 @@
             ip.events.register('post_run_cell', configure_once)
 
 _enable_matplotlib_integration()
+
+def _fetch_figure_metadata(fig):
+    """Get some metadata to help with displaying a figure."""
+    # determine if a background is needed for legibility
+    if _is_transparent(fig.get_facecolor()):
+        # the background is transparent
+        ticksLight = _is_light([label.get_color()
+                                for axes in fig.axes
+                                for axis in (axes.xaxis, axes.yaxis)
+                                for label in axis.get_ticklabels()])
+        if ticksLight.size and (ticksLight == ticksLight[0]).all():
+            # there are one or more tick labels, all with the same lightness
+            return {'needs_background': 'dark' if ticksLight[0] else 'light'}
+
+    return None
+
+def _is_light(color):
+    """Determines if a color (or each of a sequence of colors) is light (as
+    opposed to dark). Based on ITU BT.601 luminance formula (see
+    https://stackoverflow.com/a/596241)."""
+    rgbaArr = colors.to_rgba_array(color)
+    return rgbaArr[:,:3].dot((.299, .587, .114)) > .5
+
+def _is_transparent(color):
+    """Determine transparency from alpha."""
+    rgba = colors.to_rgba(color)
+    return rgba[3] < .5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/setup.cfg 
new/ipykernel-4.9.0/setup.cfg
--- old/ipykernel-4.8.2/setup.cfg       2017-12-06 11:41:42.000000000 +0100
+++ new/ipykernel-4.9.0/setup.cfg       2018-08-29 20:43:01.000000000 +0200
@@ -1,6 +1,9 @@
 [bdist_wheel]
 universal=0
 
+[metadata]
+license_file = COPYING.md
+
 [nosetests]
 warningfilters= default   |.*             |DeprecationWarning |ipykernel.*
                 error     |.*invalid.*    |DeprecationWarning |matplotlib.*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-4.8.2/setup.py new/ipykernel-4.9.0/setup.py
--- old/ipykernel-4.8.2/setup.py        2018-02-08 17:54:43.000000000 +0100
+++ new/ipykernel-4.9.0/setup.py        2018-08-29 20:43:03.000000000 +0200
@@ -16,8 +16,8 @@
 import sys
 
 v = sys.version_info
-if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
-    error = "ERROR: %s requires Python version 2.7 or 3.3 or above." % name
+if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,4)):
+    error = "ERROR: %s requires Python version 2.7 or 3.4 or above." % name
     print(error, file=sys.stderr)
     sys.exit(1)
 
@@ -101,12 +101,13 @@
          glob(pjoin('data_kernelspec', '*'))),
     ]
 
+
+setuptools_args['python_requires'] = '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, 
!=3.3.*'
+
 extras_require = setuptools_args['extras_require'] = {
     'test:python_version=="2.7"': ['mock'],
-    # pytest 3.3 doesn't work on Python 3.3
-    'test:python_version=="3.3"': ['pytest==3.2.*'],
-    'test:python_version!="3.3"': ['pytest>=3.2'],
     'test': [
+        'pytest',
         'pytest-cov',
         'nose', # nose because there are still a few nose.tools imports 
hanging around
     ],


Reply via email to