Skip to content

Commit

Permalink
Backport fixes from master for 4.7.2 release (#150)
Browse files Browse the repository at this point in the history
* FIX : update broken imports and usage

	modified:   envisage/developer/charm/charm.py
	modified:   envisage/developer/ui/view/plugin_browser.py
	modified:   envisage/ui/single_project/view/project_view.py

(cherry picked from commit 227d959)

* Add eggs (as test data) to support running tests on Python 3.7

(cherry picked from commit 872c668)

* bugfix for #143

(cherry picked from commit 8d8d459)

* Restore original streams at kernel shutdown time.

(cherry picked from commit 717997b)

* Fix ResourceWarnings from unclosed pipes.

(cherry picked from commit 7e61d83)

* Update changelog for backported fixes

* Bump version number, set IS_RELEASED to False
  • Loading branch information
mdickinson authored May 3, 2019
1 parent 24c6ad6 commit db2e9df
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 12 deletions.
22 changes: 21 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@
Envisage CHANGELOG
====================

Version 4.7.2
=============

Released: 03 May 2019

Fixes
-----

* Fix some broken imports and name errors in the ``envisage.developer``
package. (#130)
* Add missing test data to support running tests on Python 3.7. (#136)
* Fix reversed interpretation of the
``TasksApplication.always_use_default_layout`` when creating task windows.
(#144)
* In the ``InternalIPKernel`` plugin, restore original standard streams
(``stdout``, ``stdin``, ``stderr``) at plugin stop time. (#146)
* In the ``InternalIPKernel`` plugin, fix ``ResourceWarnings`` from
unclosed pipes attached to qt consoles. (#147)


Version 4.7.1
=============

Expand Down Expand Up @@ -62,7 +82,7 @@ Fixes

* Fixes for tests under Python 3.5 (#86)
* Work around for issue with Traits in Python 3 (#78)
* Replace uses of ‘file’ and ‘execfile’ (#75)
* Replace uses of ‘file’ and ‘execfile’ (#75)
* Fix MOTD_Using_Eggs example (#66)
* Fix broken and outdated links in documentation (#72)
* Fix link to docs from README (#70)
Expand Down
2 changes: 1 addition & 1 deletion envisage/developer/charm/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


# Enthought library imports.
from envisage.developer.api import CodeBrowser, Module
from envisage.developer.code_browser.api import CodeBrowser, Module
from traits.api import Event, HasTraits, Instance, Str


Expand Down
6 changes: 3 additions & 3 deletions envisage/developer/ui/view/plugin_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@


# Enthought library imports.
from envisage.api import ExtensionPoint, IPlugin
from envisage.api import ExtensionPoint, IApplication, IExtensionPoint, IPlugin
from traits.api import Delegate, HasTraits, Instance, List, Property
from traits.api import Code, Str
from traitsui.api import Item, TableEditor, View, VGroup
from traitsui.table_column import ObjectColumn # fixme: non-api!

class ExtensionPointModel(Hastraits):
class ExtensionPointModel(HasTraits):
""" A model for browsing an extension point. """

# The plugin that offered the extension point.
Expand All @@ -21,7 +21,7 @@ class ExtensionPointModel(Hastraits):



class ExtensionModel(Hastraits):
class ExtensionModel(HasTraits):
""" A model for browsing a contribution to an extension point. """

# The plugin that made the contribution.
Expand Down
32 changes: 31 additions & 1 deletion envisage/plugins/ipython_kernel/internal_ipkernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""
from distutils.version import StrictVersion as Version
import sys

import ipykernel
from ipykernel.connect import connect_qtconsole
Expand Down Expand Up @@ -55,6 +56,12 @@ class InternalIPKernel(HasStrictTraits):
#: This is a list of tuples (name, value).
initial_namespace = List()

#: sys.stdout value at time kernel was started
_original_stdout = Any()

#: sys.stderr value at time kernel was started
_original_stderr = Any()

def init_ipkernel(self, gui_backend):
""" Initialize the IPython kernel.
Expand All @@ -64,6 +71,12 @@ def init_ipkernel(self, gui_backend):
The GUI mode used to initialize the GUI mode. For options, see
the `ipython --gui` help pages.
"""
# The IPython kernel modifies sys.stdout and sys.stderr when started,
# and doesn't currently provide a way to restore them. So we restore
# them ourselves at shutdown.
self._original_stdout = sys.stdout
self._original_stderr = sys.stderr

# Start IPython kernel with GUI event loop support
self.ipkernel = gui_kernel(gui_backend)

Expand All @@ -73,7 +86,7 @@ def init_ipkernel(self, gui_backend):
# Workaround: Retrieve the kernel on the IPykernelApp and set the
# io_loop without starting it!
if NEEDS_IOLOOP_PATCH and not hasattr(self.ipkernel.kernel, 'io_loop'):
self.ipkernel.kernel.io_loop = ioloop.IOLoop.instance()
self.ipkernel.kernel.io_loop = ioloop.IOLoop.instance()

# This application will also act on the shell user namespace
self.namespace = self.ipkernel.shell.user_ns
Expand All @@ -90,6 +103,8 @@ def cleanup_consoles(self):
""" Kill all existing consoles. """
for c in self.consoles:
c.kill()
c.stdout.close()
c.stderr.close()
self.consoles = []

def shutdown(self):
Expand All @@ -101,5 +116,20 @@ def shutdown(self):
self.cleanup_consoles()
self.ipkernel.shell.exit_now = True
self.ipkernel.cleanup_connection_file()

# The stdout and stderr streams created by the kernel use the
# IOPubThread, so we need to close them and restore the originals
# before we shut down the thread. Without this, we get obscure
# errors of the form "TypeError: heap argument must be a list".
kernel_stdout = sys.stdout
if kernel_stdout is not self._original_stdout:
sys.stdout = self._original_stdout
kernel_stdout.close()

kernel_stderr = sys.stderr
if kernel_stderr is not self._original_stderr:
sys.stderr = self._original_stderr
kernel_stderr.close()

self.ipkernel.iopub_thread.stop()
self.ipkernel = None
22 changes: 22 additions & 0 deletions envisage/plugins/ipython_kernel/tests/test_internal_ipkernel.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import gc
import sys
import unittest

try:
Expand Down Expand Up @@ -47,6 +48,27 @@ def test_initial_namespace(self):
self.assertEqual(kernel.namespace['x'], 42.1)
kernel.shutdown()

def test_shutdown_restores_output_streams(self):
original_stdout = sys.stdout
original_stderr = sys.stderr

kernel = InternalIPKernel(initial_namespace=[('x', 42.1)])
kernel.init_ipkernel(gui_backend=None)
kernel.shutdown()

self.assertIs(sys.stdout, original_stdout)
self.assertIs(sys.stderr, original_stderr)

def test_shutdown_closes_console_pipes(self):
kernel = InternalIPKernel(initial_namespace=[('x', 42.1)])
kernel.init_ipkernel(gui_backend=None)
console = kernel.new_qt_console()
self.assertFalse(console.stdout.closed)
self.assertFalse(console.stderr.closed)
kernel.shutdown()
self.assertTrue(console.stdout.closed)
self.assertTrue(console.stderr.closed)

def test_io_pub_thread_stopped(self):
kernel = InternalIPKernel()
kernel.init_ipkernel(gui_backend=None)
Expand Down
Binary file added envisage/tests/bad_eggs/acme.bad-0.1a1-py3.7.egg
Binary file not shown.
12 changes: 12 additions & 0 deletions envisage/tests/eggs/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
This directory contains eggs used by the test suite, along with the packages
that were used to generate those eggs.

To generate eggs for a new version of Python:

- Change to the acme.bar directory
- Run "python setup.py bdist_egg" using the desired version of Python. This
will create a new egg under the "dist/" directory.
- Copy that egg to this directory.

Now repeat for acme.baz and acme.foo, as well as acme.bad in the bad_eggs
directory adjacent to this one.
Binary file added envisage/tests/eggs/acme.bar-0.1a1-py3.7.egg
Binary file not shown.
Binary file added envisage/tests/eggs/acme.baz-0.1a1-py3.7.egg
Binary file not shown.
Binary file added envisage/tests/eggs/acme.foo-0.1a1-py3.7.egg
Binary file not shown.
3 changes: 1 addition & 2 deletions envisage/ui/single_project/view/project_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

# Standard library imports.
import logging
from string import rfind

# Enthought library imports
from apptools.naming.api import Binding
Expand Down Expand Up @@ -262,7 +261,7 @@ def _name_suffix_changed(self, old, new):
# on the new suffix, if any.
name = self.name
if old is not None and len(old) > 0:
index = rfind(name, " " + old)
index = (" " + old).rfind(name)
if index > -1:
name = name[0:index]
if new is not None and len(new) > 0:
Expand Down
6 changes: 4 additions & 2 deletions envisage/ui/tasks/tasks_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,10 @@ def _create_windows(self):

# Create a TaskWindow for each TaskWindowLayout.
for window_layout in window_layouts:
window = self.create_window(window_layout,
restore=self.always_use_default_layout)
if self.always_use_default_layout:
window = self.create_window(window_layout, restore=False)
else:
window = self.create_window(window_layout, restore=True)
window.open()

def _get_task_factory(self, id):
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

MAJOR = 4
MINOR = 7
MICRO = 1
MICRO = 2

IS_RELEASED = True
IS_RELEASED = False

VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)

Expand Down

0 comments on commit db2e9df

Please sign in to comment.