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