1"""Implementation of magic functions that control various automatic behaviors.
2"""
3#-----------------------------------------------------------------------------
4#  Copyright (c) 2012 The IPython Development Team.
5#
6#  Distributed under the terms of the Modified BSD License.
7#
8#  The full license is in the file COPYING.txt, distributed with this software.
9#-----------------------------------------------------------------------------
10
11#-----------------------------------------------------------------------------
12# Imports
13#-----------------------------------------------------------------------------
14
15# Our own packages
16from IPython.core.magic import Bunch, Magics, magics_class, line_magic
17from IPython.testing.skipdoctest import skip_doctest
18from logging import error
19
20#-----------------------------------------------------------------------------
21# Magic implementation classes
22#-----------------------------------------------------------------------------
23
24@magics_class
25class AutoMagics(Magics):
26    """Magics that control various autoX behaviors."""
27
28    def __init__(self, shell):
29        super(AutoMagics, self).__init__(shell)
30        # namespace for holding state we may need
31        self._magic_state = Bunch()
32
33    @line_magic
34    def automagic(self, parameter_s=''):
35        """Make magic functions callable without having to type the initial %.
36
37        Without arguments toggles on/off (when off, you must call it as
38        %automagic, of course).  With arguments it sets the value, and you can
39        use any of (case insensitive):
40
41         - on, 1, True: to activate
42
43         - off, 0, False: to deactivate.
44
45        Note that magic functions have lowest priority, so if there's a
46        variable whose name collides with that of a magic fn, automagic won't
47        work for that function (you get the variable instead). However, if you
48        delete the variable (del var), the previously shadowed magic function
49        becomes visible to automagic again."""
50
51        arg = parameter_s.lower()
52        mman = self.shell.magics_manager
53        if arg in ('on', '1', 'true'):
54            val = True
55        elif arg in ('off', '0', 'false'):
56            val = False
57        else:
58            val = not mman.auto_magic
59        mman.auto_magic = val
60        print('\n' + self.shell.magics_manager.auto_status())
61
62    @skip_doctest
63    @line_magic
64    def autocall(self, parameter_s=''):
65        """Make functions callable without having to type parentheses.
66
67        Usage:
68
69           %autocall [mode]
70
71        The mode can be one of: 0->Off, 1->Smart, 2->Full.  If not given, the
72        value is toggled on and off (remembering the previous state).
73
74        In more detail, these values mean:
75
76        0 -> fully disabled
77
78        1 -> active, but do not apply if there are no arguments on the line.
79
80        In this mode, you get::
81
82          In [1]: callable
83          Out[1]: <built-in function callable>
84
85          In [2]: callable 'hello'
86          ------> callable('hello')
87          Out[2]: False
88
89        2 -> Active always.  Even if no arguments are present, the callable
90        object is called::
91
92          In [2]: float
93          ------> float()
94          Out[2]: 0.0
95
96        Note that even with autocall off, you can still use '/' at the start of
97        a line to treat the first argument on the command line as a function
98        and add parentheses to it::
99
100          In [8]: /str 43
101          ------> str(43)
102          Out[8]: '43'
103
104        # all-random (note for auto-testing)
105        """
106
107        if parameter_s:
108            arg = int(parameter_s)
109        else:
110            arg = 'toggle'
111
112        if not arg in (0, 1, 2, 'toggle'):
113            error('Valid modes: (0->Off, 1->Smart, 2->Full')
114            return
115
116        if arg in (0, 1, 2):
117            self.shell.autocall = arg
118        else: # toggle
119            if self.shell.autocall:
120                self._magic_state.autocall_save = self.shell.autocall
121                self.shell.autocall = 0
122            else:
123                try:
124                    self.shell.autocall = self._magic_state.autocall_save
125                except AttributeError:
126                    self.shell.autocall = self._magic_state.autocall_save = 1
127
128        print("Automatic calling is:",['OFF','Smart','Full'][self.shell.autocall])
129