Show More
@@ -232,3 +232,9 b' class SingletonConfigurable(Configurable):' | |||||
232 | 'Multiple incompatible subclass instances of ' |
|
232 | 'Multiple incompatible subclass instances of ' | |
233 | '%s are being created.' % cls.__name__ |
|
233 | '%s are being created.' % cls.__name__ | |
234 | ) |
|
234 | ) | |
|
235 | ||||
|
236 | @classmethod | |||
|
237 | def initialized(cls): | |||
|
238 | """Has an instance been created?""" | |||
|
239 | return hasattr(cls, "_instance") and cls._instance is not None | |||
|
240 |
@@ -152,17 +152,21 b' class TestSingletonConfigurable(TestCase):' | |||||
152 | def test_instance(self): |
|
152 | def test_instance(self): | |
153 | from IPython.config.configurable import SingletonConfigurable |
|
153 | from IPython.config.configurable import SingletonConfigurable | |
154 | class Foo(SingletonConfigurable): pass |
|
154 | class Foo(SingletonConfigurable): pass | |
|
155 | self.assertEquals(Foo.initialized(), False) | |||
155 | foo = Foo.instance() |
|
156 | foo = Foo.instance() | |
|
157 | self.assertEquals(Foo.initialized(), True) | |||
156 | self.assertEquals(foo, Foo.instance()) |
|
158 | self.assertEquals(foo, Foo.instance()) | |
157 | self.assertEquals(SingletonConfigurable._instance, None) |
|
159 | self.assertEquals(SingletonConfigurable._instance, None) | |
158 |
|
160 | |||
159 | def test_inheritance(self): |
|
161 | def test_inheritance(self): | |
160 |
|
||||
161 | class Bar(SingletonConfigurable): pass |
|
162 | class Bar(SingletonConfigurable): pass | |
162 | class Bam(Bar): pass |
|
163 | class Bam(Bar): pass | |
|
164 | self.assertEquals(Bar.initialized(), False) | |||
|
165 | self.assertEquals(Bam.initialized(), False) | |||
163 | bam = Bam.instance() |
|
166 | bam = Bam.instance() | |
164 | bam == Bar.instance() |
|
167 | bam == Bar.instance() | |
|
168 | self.assertEquals(Bar.initialized(), True) | |||
|
169 | self.assertEquals(Bam.initialized(), True) | |||
165 | self.assertEquals(bam, Bam._instance) |
|
170 | self.assertEquals(bam, Bam._instance) | |
166 | self.assertEquals(bam, Bar._instance) |
|
171 | self.assertEquals(bam, Bar._instance) | |
167 | self.assertEquals(SingletonConfigurable._instance, None) |
|
172 | self.assertEquals(SingletonConfigurable._instance, None) | |
168 | No newline at end of file |
|
@@ -31,7 +31,7 b' import tempfile' | |||||
31 | import types |
|
31 | import types | |
32 | from contextlib import nested |
|
32 | from contextlib import nested | |
33 |
|
33 | |||
34 | from IPython.config.configurable import Configurable |
|
34 | from IPython.config.configurable import SingletonConfigurable | |
35 | from IPython.core import debugger, oinspect |
|
35 | from IPython.core import debugger, oinspect | |
36 | from IPython.core import history as ipcorehist |
|
36 | from IPython.core import history as ipcorehist | |
37 | from IPython.core import page |
|
37 | from IPython.core import page | |
@@ -132,9 +132,7 b' class SeparateStr(Str):' | |||||
132 | value = value.replace('\\n','\n') |
|
132 | value = value.replace('\\n','\n') | |
133 | return super(SeparateStr, self).validate(obj, value) |
|
133 | return super(SeparateStr, self).validate(obj, value) | |
134 |
|
134 | |||
135 | class MultipleInstanceError(Exception): |
|
135 | ||
136 | pass |
|
|||
137 |
|
||||
138 | class ReadlineNoRecord(object): |
|
136 | class ReadlineNoRecord(object): | |
139 | """Context manager to execute some code, then reload readline history |
|
137 | """Context manager to execute some code, then reload readline history | |
140 | so that interactive input to the code doesn't appear when pressing up.""" |
|
138 | so that interactive input to the code doesn't appear when pressing up.""" | |
@@ -194,7 +192,7 b" called (even if no arguments are present). The default is '1'." | |||||
194 | # Main IPython class |
|
192 | # Main IPython class | |
195 | #----------------------------------------------------------------------------- |
|
193 | #----------------------------------------------------------------------------- | |
196 |
|
194 | |||
197 | class InteractiveShell(Configurable, Magic): |
|
195 | class InteractiveShell(SingletonConfigurable, Magic): | |
198 | """An enhanced, interactive shell for Python.""" |
|
196 | """An enhanced, interactive shell for Python.""" | |
199 |
|
197 | |||
200 | _instance = None |
|
198 | _instance = None | |
@@ -427,31 +425,6 b' class InteractiveShell(Configurable, Magic):' | |||||
427 | self.hooks.late_startup_hook() |
|
425 | self.hooks.late_startup_hook() | |
428 | atexit.register(self.atexit_operations) |
|
426 | atexit.register(self.atexit_operations) | |
429 |
|
427 | |||
430 | @classmethod |
|
|||
431 | def instance(cls, *args, **kwargs): |
|
|||
432 | """Returns a global InteractiveShell instance.""" |
|
|||
433 | if cls._instance is None: |
|
|||
434 | inst = cls(*args, **kwargs) |
|
|||
435 | # Now make sure that the instance will also be returned by |
|
|||
436 | # the subclasses instance attribute. |
|
|||
437 | for subclass in cls.mro(): |
|
|||
438 | if issubclass(cls, subclass) and \ |
|
|||
439 | issubclass(subclass, InteractiveShell): |
|
|||
440 | subclass._instance = inst |
|
|||
441 | else: |
|
|||
442 | break |
|
|||
443 | if isinstance(cls._instance, cls): |
|
|||
444 | return cls._instance |
|
|||
445 | else: |
|
|||
446 | raise MultipleInstanceError( |
|
|||
447 | 'Multiple incompatible subclass instances of ' |
|
|||
448 | 'InteractiveShell are being created.' |
|
|||
449 | ) |
|
|||
450 |
|
||||
451 | @classmethod |
|
|||
452 | def initialized(cls): |
|
|||
453 | return hasattr(cls, "_instance") |
|
|||
454 |
|
||||
455 | def get_ipython(self): |
|
428 | def get_ipython(self): | |
456 | """Return the currently running IPython instance.""" |
|
429 | """Return the currently running IPython instance.""" | |
457 | return self |
|
430 | return self |
General Comments 0
You need to be logged in to leave comments.
Login now