diff --git a/IPython/config/configurable.py b/IPython/config/configurable.py index 1d63107..a0dae9f 100755 --- a/IPython/config/configurable.py +++ b/IPython/config/configurable.py @@ -232,3 +232,9 @@ class SingletonConfigurable(Configurable): 'Multiple incompatible subclass instances of ' '%s are being created.' % cls.__name__ ) + + @classmethod + def initialized(cls): + """Has an instance been created?""" + return hasattr(cls, "_instance") and cls._instance is not None + diff --git a/IPython/config/tests/test_configurable.py b/IPython/config/tests/test_configurable.py index 2a5a4ac..7fc63ff 100644 --- a/IPython/config/tests/test_configurable.py +++ b/IPython/config/tests/test_configurable.py @@ -152,17 +152,21 @@ class TestSingletonConfigurable(TestCase): def test_instance(self): from IPython.config.configurable import SingletonConfigurable class Foo(SingletonConfigurable): pass + self.assertEquals(Foo.initialized(), False) foo = Foo.instance() + self.assertEquals(Foo.initialized(), True) self.assertEquals(foo, Foo.instance()) self.assertEquals(SingletonConfigurable._instance, None) def test_inheritance(self): - class Bar(SingletonConfigurable): pass class Bam(Bar): pass + self.assertEquals(Bar.initialized(), False) + self.assertEquals(Bam.initialized(), False) bam = Bam.instance() bam == Bar.instance() + self.assertEquals(Bar.initialized(), True) + self.assertEquals(Bam.initialized(), True) self.assertEquals(bam, Bam._instance) self.assertEquals(bam, Bar._instance) self.assertEquals(SingletonConfigurable._instance, None) - \ No newline at end of file diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 3ba7de4..c0e75f7 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -31,7 +31,7 @@ import tempfile import types from contextlib import nested -from IPython.config.configurable import Configurable +from IPython.config.configurable import SingletonConfigurable from IPython.core import debugger, oinspect from IPython.core import history as ipcorehist from IPython.core import page @@ -132,9 +132,7 @@ class SeparateStr(Str): value = value.replace('\\n','\n') return super(SeparateStr, self).validate(obj, value) -class MultipleInstanceError(Exception): - pass - + class ReadlineNoRecord(object): """Context manager to execute some code, then reload readline history so that interactive input to the code doesn't appear when pressing up.""" @@ -194,7 +192,7 @@ called (even if no arguments are present). The default is '1'. # Main IPython class #----------------------------------------------------------------------------- -class InteractiveShell(Configurable, Magic): +class InteractiveShell(SingletonConfigurable, Magic): """An enhanced, interactive shell for Python.""" _instance = None @@ -427,31 +425,6 @@ class InteractiveShell(Configurable, Magic): self.hooks.late_startup_hook() atexit.register(self.atexit_operations) - @classmethod - def instance(cls, *args, **kwargs): - """Returns a global InteractiveShell instance.""" - if cls._instance is None: - inst = cls(*args, **kwargs) - # Now make sure that the instance will also be returned by - # the subclasses instance attribute. - for subclass in cls.mro(): - if issubclass(cls, subclass) and \ - issubclass(subclass, InteractiveShell): - subclass._instance = inst - else: - break - if isinstance(cls._instance, cls): - return cls._instance - else: - raise MultipleInstanceError( - 'Multiple incompatible subclass instances of ' - 'InteractiveShell are being created.' - ) - - @classmethod - def initialized(cls): - return hasattr(cls, "_instance") - def get_ipython(self): """Return the currently running IPython instance.""" return self