diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 65a04fe..8a9d70d 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -477,7 +477,8 @@ class MagicsManager(Configurable): # Key base class that provides the central functionality for magics. -class Magics(object): + +class Magics(Configurable): """Base class for implementing magic functions. Shell functions which can be reached as %function_name. All magic @@ -506,10 +507,23 @@ class Magics(object): # Instance of IPython shell shell = None - def __init__(self, shell): + def __init__(self, shell=None, **kwargs): + if shell is not None: + kwargs['shell'] = shell + kwargs.setdefault('parent', shell) + super(Magics, self).__init__(**kwargs) + + def __init__(self, shell=None, **kwargs): if not(self.__class__.registered): raise ValueError('Magics subclass without registration - ' 'did you forget to apply @magics_class?') + if shell is not None: + if hasattr( shell, 'configurables'): + shell.configurables.append(self) + if hasattr( shell, 'config'): + kwargs.setdefault('parent', shell) + kwargs['shell'] = shell + self.shell = shell self.options_table = {} # The method decorators are run when the instance doesn't exist yet, so @@ -530,6 +544,9 @@ class Magics(object): else: # it's the real thing tab[magic_name] = meth_name + # Configurable **need** to be initiated at the end or the config + # magics get screwed up. + super(Magics, self).__init__(**kwargs) def arg_err(self,func): """Print docstring if incorrect arguments were passed""" @@ -639,6 +656,7 @@ class Magics(object): error("%s is not a magic function" % fn) self.options_table[fn] = optstr + class MagicAlias(object): """An alias to another magic function. diff --git a/IPython/core/magics/script.py b/IPython/core/magics/script.py index ef595e1..2300876 100644 --- a/IPython/core/magics/script.py +++ b/IPython/core/magics/script.py @@ -71,7 +71,7 @@ def script_args(f): return f @magics_class -class ScriptMagics(Magics, Configurable): +class ScriptMagics(Magics): """Magics for talking to scripts This defines a base `%%script` cell magic for running a cell @@ -116,9 +116,8 @@ class ScriptMagics(Magics, Configurable): ) def __init__(self, shell=None): - Configurable.__init__(self, config=shell.config) + super(ScriptMagics, self).__init__(shell=shell) self._generate_script_magics() - Magics.__init__(self, shell=shell) self.job_manager = BackgroundJobManager() self.bg_processes = [] atexit.register(self.kill_bg_processes) diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index 77c9808..c00fec1 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -60,7 +60,6 @@ def test_extract_code_ranges(): actual = list(code.extract_code_ranges(instr)) nt.assert_equal(actual, expected) - def test_extract_symbols(): source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n""" symbols_args = ["a", "b", "A", "A,b", "A,a", "z"] @@ -82,6 +81,14 @@ def test_extract_symbols_raises_exception_with_non_python_code(): with nt.assert_raises(SyntaxError): code.extract_symbols(source, "hello") +def test_config(): + """ test that config magic does not raise + can happen if Configurable init is moved too early into + Magics.__init__ as then a Config object will be registerd as a + magic. + """ + ## should not raise. + _ip.magic('config') def test_rehashx(): # clear up everything diff --git a/IPython/extensions/storemagic.py b/IPython/extensions/storemagic.py index aa7a7c1..6659783 100644 --- a/IPython/extensions/storemagic.py +++ b/IPython/extensions/storemagic.py @@ -25,7 +25,6 @@ To automatically restore stored variables at startup, add this to your import inspect, os, sys, textwrap # Our own -from IPython.config.configurable import Configurable from IPython.core.error import UsageError from IPython.core.magic import Magics, magics_class, line_magic from IPython.testing.skipdoctest import skip_doctest @@ -69,7 +68,7 @@ def restore_data(ip): @magics_class -class StoreMagics(Magics, Configurable): +class StoreMagics(Magics): """Lightweight persistence for python variables. Provides the %store magic.""" @@ -81,8 +80,7 @@ class StoreMagics(Magics, Configurable): ) def __init__(self, shell): - Configurable.__init__(self, config=shell.config) - Magics.__init__(self, shell=shell) + super(StoreMagics, self).__init__(shell=shell) self.shell.configurables.append(self) if self.autorestore: restore_data(self.shell) diff --git a/IPython/extensions/tests/test_autoreload.py b/IPython/extensions/tests/test_autoreload.py index 6178171..7e68570 100644 --- a/IPython/extensions/tests/test_autoreload.py +++ b/IPython/extensions/tests/test_autoreload.py @@ -33,6 +33,7 @@ from IPython.core.hooks import TryNext noop = lambda *a, **kw: None class FakeShell(object): + def __init__(self): self.ns = {} self.auto_magics = AutoreloadMagics(shell=self)