Show More
@@ -0,0 +1,117 b'' | |||||
|
1 | .. _editors: | |||
|
2 | ||||
|
3 | ==================== | |||
|
4 | Editor configuration | |||
|
5 | ==================== | |||
|
6 | ||||
|
7 | IPython can integrate with text editors in a number of different ways: | |||
|
8 | ||||
|
9 | * Editors (such as (X)Emacs [Emacs]_, vim [vim]_ and TextMate [TextMate]_) can | |||
|
10 | send code to IPython for execution. | |||
|
11 | ||||
|
12 | * IPython's ``%edit`` magic command can open an editor of choice to edit | |||
|
13 | a code block. | |||
|
14 | ||||
|
15 | The %edit command (and its alias %ed) will invoke the editor set in your | |||
|
16 | environment as :envvar:`EDITOR`. If this variable is not set, it will default | |||
|
17 | to vi under Linux/Unix and to notepad under Windows. You may want to set this | |||
|
18 | variable properly and to a lightweight editor which doesn't take too long to | |||
|
19 | start (that is, something other than a new instance of Emacs). This way you | |||
|
20 | can edit multi-line code quickly and with the power of a real editor right | |||
|
21 | inside IPython. | |||
|
22 | ||||
|
23 | You can also control the editor via the commmand-line option '-editor' or in | |||
|
24 | your configuration file, by setting the :attr:`InteractiveShell.editor` | |||
|
25 | configuration attribute. | |||
|
26 | ||||
|
27 | TextMate | |||
|
28 | ======== | |||
|
29 | ||||
|
30 | Currently, TextMate support in IPython is broken. It used to work well, | |||
|
31 | but the code has been moved to :mod:`IPython.quarantine` until it is updated. | |||
|
32 | ||||
|
33 | vim configuration | |||
|
34 | ================= | |||
|
35 | ||||
|
36 | Currently, vim support in IPython is broken. Like the TextMate code, | |||
|
37 | the vim support code has been moved to :mod:`IPython.quarantine` until it | |||
|
38 | is updated. | |||
|
39 | ||||
|
40 | .. _emacs: | |||
|
41 | ||||
|
42 | (X)Emacs | |||
|
43 | ======== | |||
|
44 | ||||
|
45 | Editor | |||
|
46 | ====== | |||
|
47 | ||||
|
48 | If you are a dedicated Emacs user, and want to use Emacs when IPython's | |||
|
49 | ``%edit`` magic command is called you should set up the Emacs server so that | |||
|
50 | new requests are handled by the original process. This means that almost no | |||
|
51 | time is spent in handling the request (assuming an Emacs process is already | |||
|
52 | running). For this to work, you need to set your EDITOR environment variable | |||
|
53 | to 'emacsclient'. The code below, supplied by Francois Pinard, can then be | |||
|
54 | used in your :file:`.emacs` file to enable the server:: | |||
|
55 | ||||
|
56 | (defvar server-buffer-clients) | |||
|
57 | (when (and (fboundp 'server-start) (string-equal (getenv "TERM") 'xterm)) | |||
|
58 | (server-start) | |||
|
59 | (defun fp-kill-server-with-buffer-routine () | |||
|
60 | (and server-buffer-clients (server-done))) | |||
|
61 | (add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine)) | |||
|
62 | ||||
|
63 | Thanks to the work of Alexander Schmolck and Prabhu Ramachandran, | |||
|
64 | currently (X)Emacs and IPython get along very well in other ways. | |||
|
65 | ||||
|
66 | .. note:: | |||
|
67 | ||||
|
68 | You will need to use a recent enough version of :file:`python-mode.el`, | |||
|
69 | along with the file :file:`ipython.el`. You can check that the version you | |||
|
70 | have of :file:`python-mode.el` is new enough by either looking at the | |||
|
71 | revision number in the file itself, or asking for it in (X)Emacs via ``M-x | |||
|
72 | py-version``. Versions 4.68 and newer contain the necessary fixes for | |||
|
73 | proper IPython support. | |||
|
74 | ||||
|
75 | The file :file:`ipython.el` is included with the IPython distribution, in the | |||
|
76 | directory :file:`docs/emacs`. Once you put these files in your Emacs path, all | |||
|
77 | you need in your :file:`.emacs` file is:: | |||
|
78 | ||||
|
79 | (require 'ipython) | |||
|
80 | ||||
|
81 | This should give you full support for executing code snippets via | |||
|
82 | IPython, opening IPython as your Python shell via ``C-c !``, etc. | |||
|
83 | ||||
|
84 | You can customize the arguments passed to the IPython instance at startup by | |||
|
85 | setting the ``py-python-command-args`` variable. For example, to start always | |||
|
86 | in ``pylab`` mode with hardcoded light-background colors, you can use:: | |||
|
87 | ||||
|
88 | (setq py-python-command-args '("-pylab" "-colors" "LightBG")) | |||
|
89 | ||||
|
90 | If you happen to get garbage instead of colored prompts as described in | |||
|
91 | the previous section, you may need to set also in your :file:`.emacs` file:: | |||
|
92 | ||||
|
93 | (setq ansi-color-for-comint-mode t) | |||
|
94 | ||||
|
95 | Notes on emacs support: | |||
|
96 | ||||
|
97 | * There is one caveat you should be aware of: you must start the IPython shell | |||
|
98 | before attempting to execute any code regions via ``C-c |``. Simply type | |||
|
99 | ``C-c !`` to start IPython before passing any code regions to the | |||
|
100 | interpreter, and you shouldn't experience any problems. This is due to a bug | |||
|
101 | in Python itself, which has been fixed for Python 2.3, but exists as of | |||
|
102 | Python 2.2.2 (reported as SF bug [ 737947 ]). | |||
|
103 | ||||
|
104 | * The (X)Emacs support is maintained by Alexander Schmolck, so all | |||
|
105 | comments/requests should be directed to him through the IPython mailing | |||
|
106 | lists. | |||
|
107 | ||||
|
108 | * This code is still somewhat experimental so it's a bit rough around the | |||
|
109 | edges (although in practice, it works quite well). | |||
|
110 | ||||
|
111 | * Be aware that if you customized ``py-python-command`` previously, this value | |||
|
112 | will override what :file:`ipython.el` does (because loading the customization | |||
|
113 | variables comes later). | |||
|
114 | ||||
|
115 | .. [Emacs] Emacs. http://www.gnu.org/software/emacs/ | |||
|
116 | .. [TextMate] TextMate: the missing editor. http://macromates.com/ | |||
|
117 | .. [vim] vim. http://www.vim.org/ |
@@ -0,0 +1,134 b'' | |||||
|
1 | .. _configuring_ipython: | |||
|
2 | ||||
|
3 | =========================================================== | |||
|
4 | Configuring the :command:`ipython` command line application | |||
|
5 | =========================================================== | |||
|
6 | ||||
|
7 | This section contains information about how to configure the | |||
|
8 | :command:`ipython` command line application. See the :ref:`configuration | |||
|
9 | overview <config_overview>` for a more general description of the | |||
|
10 | configuration system and configuration file format. | |||
|
11 | ||||
|
12 | The default configuration file for the :command:`ipython` command line application | |||
|
13 | is :file:`ipython_config.py`. By setting the attributes in this file, you | |||
|
14 | can configure the application. A sample is provided in | |||
|
15 | :mod:`IPython.config.default.ipython_config`. Simply copy this file to your | |||
|
16 | IPython directory to start using it. | |||
|
17 | ||||
|
18 | Most configuration attributes that this file accepts are associated with | |||
|
19 | classes that are subclasses of :class:`~IPython.core.component.Component`. | |||
|
20 | ||||
|
21 | A few configuration attributes are not associated with a particular | |||
|
22 | :class:`~IPython.core.component.Component` subclass. These are application | |||
|
23 | wide configuration attributes and are stored in the ``Global`` | |||
|
24 | sub-configuration section. We begin with a description of these | |||
|
25 | attributes. | |||
|
26 | ||||
|
27 | Global configuration | |||
|
28 | ==================== | |||
|
29 | ||||
|
30 | Assuming that your configuration file has the following at the top:: | |||
|
31 | ||||
|
32 | c = get_config() | |||
|
33 | ||||
|
34 | the following attributes can be set in the ``Global`` section. | |||
|
35 | ||||
|
36 | :attr:`c.Global.display_banner` | |||
|
37 | A boolean that determined if the banner is printer when :command:`ipython` | |||
|
38 | is started. | |||
|
39 | ||||
|
40 | :attr:`c.Global.classic` | |||
|
41 | A boolean that determines if IPython starts in "classic" mode. In this | |||
|
42 | mode, the prompts and everything mimic that of the normal :command:`python` | |||
|
43 | shell | |||
|
44 | ||||
|
45 | :attr:`c.Global.nosep` | |||
|
46 | A boolean that determines if there should be no blank lines between | |||
|
47 | prompts. | |||
|
48 | ||||
|
49 | :attr:`c.Global.log_level` | |||
|
50 | An integer that sets the detail of the logging level during the startup | |||
|
51 | of :command:`ipython`. The default is 30 and the possible values are | |||
|
52 | (0, 10, 20, 30, 40, 50). Higher is quieter and lower is more verbose. | |||
|
53 | ||||
|
54 | :attr:`c.Global.extensions` | |||
|
55 | A list of strings, each of which is an importable IPython extension. An | |||
|
56 | IPython extension is a regular Python module or package that has a | |||
|
57 | :func:`load_in_ipython(ip)` method. This method gets called when the | |||
|
58 | extension is loaded with the currently running | |||
|
59 | :class:`~IPython.core.iplib.InteractiveShell` as its only argument. You | |||
|
60 | can put your extensions anywhere they can be imported but we add the | |||
|
61 | :file:`extensions` subdirectory of the ipython directory to ``sys.path`` | |||
|
62 | during extension loading, so you can put them there as well. Extensions | |||
|
63 | are not executed in the user's interactive namespace and they must | |||
|
64 | be pure Python code. Extensions are the recommended way of customizing | |||
|
65 | :command:`ipython`. | |||
|
66 | ||||
|
67 | :attr:`c.Global.exec_lines` | |||
|
68 | A list of strings, each of which is Python code that is run in the user's | |||
|
69 | namespace after IPython start. These lines can contain full IPython syntax | |||
|
70 | with magics, etc. | |||
|
71 | ||||
|
72 | :attr:`c.Global.exec_files` | |||
|
73 | A list of strings, each of which is the full pathname of a ``.py`` or | |||
|
74 | ``.ipy`` file that will be executed as IPython starts. These files are run | |||
|
75 | in IPython in the user's namespace. Files with a ``.py`` extension need to | |||
|
76 | be pure Python. Files with a ``.ipy`` extension can have custom IPython | |||
|
77 | syntax (magics, etc.). These files need to be in the cwd, the ipythondir | |||
|
78 | or be absolute paths. | |||
|
79 | ||||
|
80 | Classes that can be configured | |||
|
81 | ============================== | |||
|
82 | ||||
|
83 | The following classes can also be configured in the configuration file for | |||
|
84 | :command:`ipython`: | |||
|
85 | ||||
|
86 | * :class:`~IPython.core.iplib.InteractiveShell` | |||
|
87 | ||||
|
88 | * :class:`~IPython.core.prefilter.PrefilterManager` | |||
|
89 | ||||
|
90 | * :class:`~IPython.core.alias.AliasManager` | |||
|
91 | ||||
|
92 | To see which attributes of these classes are configurable, please see the | |||
|
93 | source code for these classes, the class docstrings or the sample | |||
|
94 | configuration file :mod:`IPython.config.default.ipython_config`. | |||
|
95 | ||||
|
96 | Example | |||
|
97 | ======= | |||
|
98 | ||||
|
99 | For those who want to get a quick start, here is a sample | |||
|
100 | :file:`ipython_config.py` that sets some of the common configuration | |||
|
101 | attributes:: | |||
|
102 | ||||
|
103 | # sample ipython_config.py | |||
|
104 | c = get_config() | |||
|
105 | ||||
|
106 | c.Global.display_banner = True | |||
|
107 | c.Global.log_level = 20 | |||
|
108 | c.Global.extensions = [ | |||
|
109 | 'myextension' | |||
|
110 | ] | |||
|
111 | c.Global.exec_lines = [ | |||
|
112 | 'import numpy', | |||
|
113 | 'import scipy' | |||
|
114 | ] | |||
|
115 | c.Global.exec_files = [ | |||
|
116 | 'mycode.py', | |||
|
117 | 'fancy.ipy' | |||
|
118 | ] | |||
|
119 | c.InteractiveShell.autoindent = True | |||
|
120 | c.InteractiveShell.colors = 'LightBG' | |||
|
121 | c.InteractiveShell.confirm_exit = False | |||
|
122 | c.InteractiveShell.deep_reload = True | |||
|
123 | c.InteractiveShell.editor = 'nano' | |||
|
124 | c.InteractiveShell.prompt_in1 = 'In [\#]: ' | |||
|
125 | c.InteractiveShell.prompt_in2 = ' .\D.: ' | |||
|
126 | c.InteractiveShell.prompt_out = 'Out[\#]: ' | |||
|
127 | c.InteractiveShell.prompts_pad_left = True | |||
|
128 | c.InteractiveShell.xmode = 'Context' | |||
|
129 | ||||
|
130 | c.PrefilterManager.multi_line_specials = True | |||
|
131 | ||||
|
132 | c.AliasManager.user_aliases = [ | |||
|
133 | ('la', 'ls -al') | |||
|
134 | ] No newline at end of file |
@@ -0,0 +1,331 b'' | |||||
|
1 | .. _config_overview: | |||
|
2 | ||||
|
3 | ============================================ | |||
|
4 | Overview of the IPython configuration system | |||
|
5 | ============================================ | |||
|
6 | ||||
|
7 | This section describes the IPython configuration system. Starting with version | |||
|
8 | 0.11, IPython has a completely new configuration system that is quite | |||
|
9 | different from the older :file:`ipythonrc` or :file:`ipy_user_conf.py` | |||
|
10 | approaches. The new configuration system was designed from scratch to address | |||
|
11 | the particular configuration needs of IPython. While there are many | |||
|
12 | other excellent configuration systems out there, we found that none of them | |||
|
13 | met our requirements. | |||
|
14 | ||||
|
15 | .. warning:: | |||
|
16 | ||||
|
17 | If you are upgrading to version 0.11 of IPython, you will need to migrate | |||
|
18 | your old :file:`ipythonrc` or :file:`ipy_user_conf.py` configuration files | |||
|
19 | to the new system. Read on for information on how to do this. | |||
|
20 | ||||
|
21 | The discussion that follows is focused on teaching user's how to configure | |||
|
22 | IPython to their liking. Developer's who want to know more about how they | |||
|
23 | can enable their objects to take advantage of the configuration system | |||
|
24 | should consult our :ref:`developer guide <developer_guide>` | |||
|
25 | ||||
|
26 | The main concepts | |||
|
27 | ================= | |||
|
28 | ||||
|
29 | There are a number of abstractions that the IPython configuration system uses. | |||
|
30 | Each of these abstractions is represented by a Python class. | |||
|
31 | ||||
|
32 | Configuration object: :class:`~IPython.config.loader.Config` | |||
|
33 | A configuration object is a simple dictionary-like class that holds | |||
|
34 | configuration attributes and sub-configuration objects. These classes | |||
|
35 | support dotted attribute style access (``Foo.bar``) in addition to the | |||
|
36 | regular dictionary style access (``Foo['bar']``). Configuration objects | |||
|
37 | are smart. They know how to merge themselves with other configuration | |||
|
38 | objects and they automatically create sub-configuration objects. | |||
|
39 | ||||
|
40 | Application: :class:`~IPython.core.application.Application` | |||
|
41 | An application is a process that does a specific job. The most obvious | |||
|
42 | application is the :command:`ipython` command line program. Each | |||
|
43 | application reads a *single* configuration file and command line options | |||
|
44 | and then produces a master configuration object for the application. This | |||
|
45 | configuration object is then passed to the components that the application | |||
|
46 | creates. Components implement the actual logic of the application and know | |||
|
47 | how to configure themselves given the configuration object. | |||
|
48 | ||||
|
49 | Component: :class:`~IPython.core.component.Component` | |||
|
50 | A component is a regular Python class that serves as a base class for all | |||
|
51 | main classes in an application. The | |||
|
52 | :class:`~IPython.core.component.Component` base class is lightweight and | |||
|
53 | only does two main things. | |||
|
54 | ||||
|
55 | First, it keeps track of all instances of itself and provides an | |||
|
56 | interfaces for querying those instances. This enables components to get | |||
|
57 | references to other components, even though they are not "nearby" in the | |||
|
58 | runtime object graph. | |||
|
59 | ||||
|
60 | Second, it declares what class attributes are configurable and specifies | |||
|
61 | the default types and values of those attributes. This information is used | |||
|
62 | to automatically configure instances given the applications configuration | |||
|
63 | object. | |||
|
64 | ||||
|
65 | Developers create :class:`~IPython.core.component.Component` subclasses | |||
|
66 | that implement all of the logic in the application. Each of these | |||
|
67 | subclasses has its own configuration information that controls how | |||
|
68 | instances are created. | |||
|
69 | ||||
|
70 | Having described these main concepts, we can now state the main idea in our | |||
|
71 | configuration system: *"configuration" allows the default values of class | |||
|
72 | attributes to be controlled on a class by class basis*. Thus all instances of | |||
|
73 | a given class are configured in the same way. Furthermore, if two instances | |||
|
74 | need to be configured differently, they need to be instances of two different | |||
|
75 | classes. While this model may seem a bit restrictive, we have found that it | |||
|
76 | expresses most things that need to be configured extremely well. | |||
|
77 | ||||
|
78 | Now, we show what our configuration objects and files look like. | |||
|
79 | ||||
|
80 | Configuration objects and files | |||
|
81 | =============================== | |||
|
82 | ||||
|
83 | A configuration file is simply a pure Python file that sets the attributes | |||
|
84 | of a global, pre-created configuration object. This configuration object is a | |||
|
85 | :class:`~IPython.config.loader.Config` instance. While in a configuration | |||
|
86 | file, to get a reference to this object, simply call the :func:`get_config` | |||
|
87 | function. We inject this function into the global namespace that the | |||
|
88 | configuration file is executed in. | |||
|
89 | ||||
|
90 | Here is an example of a super simple configuration file that does nothing:: | |||
|
91 | ||||
|
92 | c = get_config() | |||
|
93 | ||||
|
94 | Once you get a reference to the configuration object, you simply set | |||
|
95 | attributes on it. All you have to know is: | |||
|
96 | ||||
|
97 | * The name of each attribute. | |||
|
98 | * The type of each attribute. | |||
|
99 | ||||
|
100 | The answers to these two questions are provided by the various | |||
|
101 | :class:`~IPython.core.component.Component` subclasses that an application | |||
|
102 | uses. Let's look at how this would work for a simple component subclass:: | |||
|
103 | ||||
|
104 | # Sample component that can be configured. | |||
|
105 | from IPython.core.component import Component | |||
|
106 | from IPython.utils.traitlets import Int, Float, Str, Bool | |||
|
107 | ||||
|
108 | class MyComponent(Component): | |||
|
109 | name = Str('defaultname', config=True) | |||
|
110 | ranking = Int(0, config=True) | |||
|
111 | value = Float(99.0) | |||
|
112 | # The rest of the class implementation would go here.. | |||
|
113 | ||||
|
114 | In this example, we see that :class:`MyComponent` has three attributes, two | |||
|
115 | of whom (``name``, ``ranking``) can be configured. All of the attributes | |||
|
116 | are given types and default values. If a :class:`MyComponent` is instantiated, | |||
|
117 | but not configured, these default values will be used. But let's see how | |||
|
118 | to configure this class in a configuration file:: | |||
|
119 | ||||
|
120 | # Sample config file | |||
|
121 | c = get_config() | |||
|
122 | ||||
|
123 | c.MyComponent.name = 'coolname' | |||
|
124 | c.MyComponent.ranking = 10 | |||
|
125 | ||||
|
126 | After this configuration file is loaded, the values set in it will override | |||
|
127 | the class defaults anytime a :class:`MyComponent` is created. Furthermore, | |||
|
128 | these attributes will be type checked and validated anytime they are set. | |||
|
129 | This type checking is handled by the :mod:`IPython.utils.traitlets` module, | |||
|
130 | which provides the :class:`Str`, :class:`Int` and :class:`Float` types. In | |||
|
131 | addition to these traitlets, the :mod:`IPython.utils.traitlets` provides | |||
|
132 | traitlets for a number of other types. | |||
|
133 | ||||
|
134 | .. note:: | |||
|
135 | ||||
|
136 | Underneath the hood, the :class:`Component` base class is a subclass of | |||
|
137 | :class:`IPython.utils.traitlets.HasTraitlets`. The | |||
|
138 | :mod:`IPython.utils.traitlets` module is a lightweight version of | |||
|
139 | :mod:`enthought.traits`. Our implementation is a pure Python subset | |||
|
140 | (mostly API compatible) of :mod:`enthought.traits` that does not have any | |||
|
141 | of the automatic GUI generation capabilities. Our plan is to achieve 100% | |||
|
142 | API compatibility to enable the actual :mod:`enthought.traits` to | |||
|
143 | eventually be used instead. Currently, we cannot use | |||
|
144 | :mod:`enthought.traits` as we are committed to the core of IPython being | |||
|
145 | pure Python. | |||
|
146 | ||||
|
147 | It should be very clear at this point what the naming convention is for | |||
|
148 | configuration attributes:: | |||
|
149 | ||||
|
150 | c.ClassName.attribute_name = attribute_value | |||
|
151 | ||||
|
152 | Here, ``ClassName`` is the name of the class whose configuration attribute you | |||
|
153 | want to set, ``attribute_name`` is the name of the attribute you want to set | |||
|
154 | and ``attribute_value`` the the value you want it to have. The ``ClassName`` | |||
|
155 | attribute of ``c`` is not the actual class, but instead is another | |||
|
156 | :class:`~IPython.config.loader.Config` instance. | |||
|
157 | ||||
|
158 | .. note:: | |||
|
159 | ||||
|
160 | The careful reader may wonder how the ``ClassName`` (``MyComponent`` in | |||
|
161 | the above example) attribute of the configuration object ``c`` gets | |||
|
162 | created. These attributes are created on the fly by the | |||
|
163 | :class:`~IPython.config.loader.Config` instance, using a simple naming | |||
|
164 | convention. Any attribute of a :class:`~IPython.config.loader.Config` | |||
|
165 | instance whose name begins with an uppercase character is assumed to be a | |||
|
166 | sub-configuration and a new empty :class:`~IPython.config.loader.Config` | |||
|
167 | instance is dynamically created for that attribute. This allows deeply | |||
|
168 | hierarchical information created easily (``c.Foo.Bar.value``) on the | |||
|
169 | fly. | |||
|
170 | ||||
|
171 | Configuration files inheritance | |||
|
172 | =============================== | |||
|
173 | ||||
|
174 | Let's say you want to have different configuration files for various purposes. | |||
|
175 | Our configuration system makes it easy for one configuration file to inherit | |||
|
176 | the information in another configuration file. The :func:`load_subconfig` | |||
|
177 | command can be used in a configuration file for this purpose. Here is a simple | |||
|
178 | example that loads all of the values from the file :file:`base_config.py`:: | |||
|
179 | ||||
|
180 | # base_config.py | |||
|
181 | c = get_config() | |||
|
182 | c.MyComponent.name = 'coolname' | |||
|
183 | c.MyComponent.ranking = 100 | |||
|
184 | ||||
|
185 | into the configuration file :file:`main_config.py`:: | |||
|
186 | ||||
|
187 | # main_config.py | |||
|
188 | c = get_config() | |||
|
189 | ||||
|
190 | # Load everything from base_config.py | |||
|
191 | load_subconfig('base_config.py') | |||
|
192 | ||||
|
193 | # Now override one of the values | |||
|
194 | c.MyComponent.name = 'bettername' | |||
|
195 | ||||
|
196 | In a situation like this the :func:`load_subconfig` makes sure that the | |||
|
197 | search path for sub-configuration files is inherited from that of the parent. | |||
|
198 | Thus, you can typically put the two in the same directory and everything will | |||
|
199 | just work. | |||
|
200 | ||||
|
201 | Class based configuration inheritance | |||
|
202 | ===================================== | |||
|
203 | ||||
|
204 | There is another aspect of configuration where inheritance comes into play. | |||
|
205 | Sometimes, your classes will have an inheritance hierarchy that you want | |||
|
206 | to be reflected in the configuration system. Here is a simple example:: | |||
|
207 | ||||
|
208 | from IPython.core.component import Component | |||
|
209 | from IPython.utils.traitlets import Int, Float, Str, Bool | |||
|
210 | ||||
|
211 | class Foo(Component): | |||
|
212 | name = Str('fooname', config=True) | |||
|
213 | value = Float(100.0, config=True) | |||
|
214 | ||||
|
215 | class Bar(Foo): | |||
|
216 | name = Str('barname', config=True) | |||
|
217 | othervalue = Int(0, config=True) | |||
|
218 | ||||
|
219 | Now, we can create a configuration file to configure instances of :class:`Foo` | |||
|
220 | and :class:`Bar`:: | |||
|
221 | ||||
|
222 | # config file | |||
|
223 | c = get_config() | |||
|
224 | ||||
|
225 | c.Foo.name = 'bestname' | |||
|
226 | c.Bar.othervalue = 10 | |||
|
227 | ||||
|
228 | This class hierarchy and configuration file accomplishes the following: | |||
|
229 | ||||
|
230 | * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be | |||
|
231 | 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also | |||
|
232 | picks up the configuration information for :class:`Foo`. | |||
|
233 | * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be | |||
|
234 | ``100.0``, which is the value specified as the class default. | |||
|
235 | * The default value for :attr:`Bar.othervalue` will be 10 as set in the | |||
|
236 | configuration file. Because :class:`Foo` is the parent of :class:`Bar` | |||
|
237 | it doesn't know anything about the :attr:`othervalue` attribute. | |||
|
238 | ||||
|
239 | Configuration file location | |||
|
240 | =========================== | |||
|
241 | ||||
|
242 | So where should you put your configuration files? By default, all IPython | |||
|
243 | applications look in the so called "IPython directory". The location of | |||
|
244 | this directory is determined by the following algorithm: | |||
|
245 | ||||
|
246 | * If the ``-ipythondir`` command line flag is given, its value is used. | |||
|
247 | ||||
|
248 | * If not, the value returned by :func:`IPython.utils.genutils.get_ipython_dir` | |||
|
249 | is used. This function will first look at the :envvar:`IPYTHONDIR` | |||
|
250 | environment variable and then default to the directory | |||
|
251 | :file:`$HOME/.ipythondir`. | |||
|
252 | ||||
|
253 | For most users, the default value will simply be something like | |||
|
254 | :file:`$HOME/.ipythondir`. | |||
|
255 | ||||
|
256 | Once the location of the IPython directory has been determined, you need to | |||
|
257 | know what filename to use for the configuration file. The basic idea is that | |||
|
258 | each application has its own default configuration filename. The default named | |||
|
259 | used by the :command:`ipython` command line program is | |||
|
260 | :file:`ipython_config.py`. This value can be overriden by the ``-config_file`` | |||
|
261 | command line flag. A sample :file:`ipython_config.py` file can be found | |||
|
262 | in :mod:`IPython.config.default.ipython_config.py`. Simple copy it to your | |||
|
263 | IPython directory to begin using it. | |||
|
264 | ||||
|
265 | .. _Profiles: | |||
|
266 | ||||
|
267 | Profiles | |||
|
268 | ======== | |||
|
269 | ||||
|
270 | A profile is simply a configuration file that follows a simple naming | |||
|
271 | convention and can be loaded using a simplified syntax. The idea is | |||
|
272 | that users often want to maintain a set of configuration files for different | |||
|
273 | purposes: one for doing numerical computing with NumPy and SciPy and | |||
|
274 | another for doing symbolic computing with SymPy. Profiles make it easy | |||
|
275 | to keep a separate configuration file for each of these purposes. | |||
|
276 | ||||
|
277 | Let's start by showing how a profile is used: | |||
|
278 | ||||
|
279 | .. code-block:: bash | |||
|
280 | ||||
|
281 | $ ipython -p sympy | |||
|
282 | ||||
|
283 | This tells the :command:`ipython` command line program to get its | |||
|
284 | configuration from the "sympy" profile. The search path for profiles is the | |||
|
285 | same as that of regular configuration files. The only difference is that | |||
|
286 | profiles are named in a special way. In the case above, the "sympy" profile | |||
|
287 | would need to have the name :file:`ipython_config_sympy.py`. | |||
|
288 | ||||
|
289 | The general pattern is this: simply add ``_profilename`` to the end of the | |||
|
290 | normal configuration file name. Then load the profile by adding ``-p | |||
|
291 | profilename`` to your command line options. | |||
|
292 | ||||
|
293 | IPython ships with some sample profiles in :mod:`IPython.config.profile`. | |||
|
294 | Simply copy these to your IPython directory to begin using them. | |||
|
295 | ||||
|
296 | Design requirements | |||
|
297 | =================== | |||
|
298 | ||||
|
299 | Here are the main requirements we wanted our configuration system to have: | |||
|
300 | ||||
|
301 | * Support for hierarchical configuration information. | |||
|
302 | ||||
|
303 | * Full integration with command line option parsers. Often, you want to read | |||
|
304 | a configuration file, but then override some of the values with command line | |||
|
305 | options. Our configuration system automates this process and allows each | |||
|
306 | command line option to be linked to a particular attribute in the | |||
|
307 | configuration hierarchy that it will override. | |||
|
308 | ||||
|
309 | * Configuration files that are themselves valid Python code. This accomplishes | |||
|
310 | many things. First, it becomes possible to put logic in your configuration | |||
|
311 | files that sets attributes based on your operating system, network setup, | |||
|
312 | Python version, etc. Second, Python has a super simple syntax for accessing | |||
|
313 | hierarchical data structures, namely regular attribute access | |||
|
314 | (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to | |||
|
315 | import configuration attributes from one configuration file to another. | |||
|
316 | Forth, even though Python is dynamically typed, it does have types that can | |||
|
317 | be checked at runtime. Thus, a ``1`` in a config file is the integer '1', | |||
|
318 | while a ``'1'`` is a string. | |||
|
319 | ||||
|
320 | * A fully automated method for getting the configuration information to the | |||
|
321 | classes that need it at runtime. Writing code that walks a configuration | |||
|
322 | hierarchy to extract a particular attribute is painful. When you have | |||
|
323 | complex configuration information with hundreds of attributes, this makes | |||
|
324 | you want to cry. | |||
|
325 | ||||
|
326 | * Type checking and validation that doesn't require the entire configuration | |||
|
327 | hierarchy to be specified statically before runtime. Python is a very | |||
|
328 | dynamic language and you don't always know everything that needs to be | |||
|
329 | configured when a program starts. | |||
|
330 | ||||
|
331 |
@@ -1,148 +1,148 b'' | |||||
1 | # Get the config being loaded so we can set attributes on it |
|
1 | # Get the config being loaded so we can set attributes on it | |
2 | c = get_config() |
|
2 | c = get_config() | |
3 |
|
3 | |||
4 | #----------------------------------------------------------------------------- |
|
4 | #----------------------------------------------------------------------------- | |
5 | # Global options |
|
5 | # Global options | |
6 | #----------------------------------------------------------------------------- |
|
6 | #----------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | # c.Global.display_banner = True |
|
8 | # c.Global.display_banner = True | |
9 |
|
9 | |||
10 | # c.Global.classic = False |
|
10 | # c.Global.classic = False | |
11 |
|
11 | |||
12 | # c.Global.nosep = True |
|
12 | # c.Global.nosep = True | |
13 |
|
13 | |||
14 | # Set this to determine the detail of what is logged at startup. |
|
14 | # Set this to determine the detail of what is logged at startup. | |
15 | # The default is 30 and possible values are 0,10,20,30,40,50. |
|
15 | # The default is 30 and possible values are 0,10,20,30,40,50. | |
16 | c.Global.log_level = 20 |
|
16 | c.Global.log_level = 20 | |
17 |
|
17 | |||
18 | # This should be a list of importable Python modules that have an |
|
18 | # This should be a list of importable Python modules that have an | |
19 | # load_in_ipython(ip) method. This method gets called when the extension |
|
19 | # load_in_ipython(ip) method. This method gets called when the extension | |
20 | # is loaded. You can put your extensions anywhere they can be imported |
|
20 | # is loaded. You can put your extensions anywhere they can be imported | |
21 | # but we add the extensions subdir of the ipython directory to sys.path |
|
21 | # but we add the extensions subdir of the ipython directory to sys.path | |
22 | # during extension loading, so you can put them there as well. |
|
22 | # during extension loading, so you can put them there as well. | |
23 | # c.Global.extensions = [ |
|
23 | # c.Global.extensions = [ | |
24 | # 'myextension' |
|
24 | # 'myextension' | |
25 | # ] |
|
25 | # ] | |
26 |
|
26 | |||
27 | # These lines are run in IPython in the user's namespace after extensions |
|
27 | # These lines are run in IPython in the user's namespace after extensions | |
28 | # are loaded. They can contain full IPython syntax with magics etc. |
|
28 | # are loaded. They can contain full IPython syntax with magics etc. | |
29 | # c.Global.exec_lines = [ |
|
29 | # c.Global.exec_lines = [ | |
30 | # 'import numpy', |
|
30 | # 'import numpy', | |
31 | # 'a = 10; b = 20', |
|
31 | # 'a = 10; b = 20', | |
32 | # '1/0' |
|
32 | # '1/0' | |
33 | # ] |
|
33 | # ] | |
34 |
|
34 | |||
35 | # These files are run in IPython in the user's namespace. Files with a .py |
|
35 | # These files are run in IPython in the user's namespace. Files with a .py | |
36 | # extension need to be pure Python. Files with a .ipy extension can have |
|
36 | # extension need to be pure Python. Files with a .ipy extension can have | |
37 | # custom IPython syntax (like magics, etc.). |
|
37 | # custom IPython syntax (like magics, etc.). | |
38 | # These files need to be in the cwd, the ipythondir or be absolute paths. |
|
38 | # These files need to be in the cwd, the ipythondir or be absolute paths. | |
39 | # c.Global.exec_files = [ |
|
39 | # c.Global.exec_files = [ | |
40 | # 'mycode.py', |
|
40 | # 'mycode.py', | |
41 | # 'fancy.ipy' |
|
41 | # 'fancy.ipy' | |
42 | # ] |
|
42 | # ] | |
43 |
|
43 | |||
44 | #----------------------------------------------------------------------------- |
|
44 | #----------------------------------------------------------------------------- | |
45 | # InteractiveShell options |
|
45 | # InteractiveShell options | |
46 | #----------------------------------------------------------------------------- |
|
46 | #----------------------------------------------------------------------------- | |
47 |
|
47 | |||
48 | # c.InteractiveShell.autocall = 1 |
|
48 | # c.InteractiveShell.autocall = 1 | |
49 |
|
49 | |||
50 | # c.InteractiveShell.autoedit_syntax = False |
|
50 | # c.InteractiveShell.autoedit_syntax = False | |
51 |
|
51 | |||
52 | # c.InteractiveShell.autoindent = True |
|
52 | # c.InteractiveShell.autoindent = True | |
53 |
|
53 | |||
54 | # c.InteractiveShell.automagic = False |
|
54 | # c.InteractiveShell.automagic = False | |
55 |
|
55 | |||
56 | # c.InteractiveShell.banner1 = 'This if for overriding the default IPython banner' |
|
56 | # c.InteractiveShell.banner1 = 'This if for overriding the default IPython banner' | |
57 |
|
57 | |||
58 | # c.InteractiveShell.banner2 = "This is for extra banner text" |
|
58 | # c.InteractiveShell.banner2 = "This is for extra banner text" | |
59 |
|
59 | |||
60 | # c.InteractiveShell.cache_size = 1000 |
|
60 | # c.InteractiveShell.cache_size = 1000 | |
61 |
|
61 | |||
62 | # c.InteractiveShell.colors = 'LightBG' |
|
62 | # c.InteractiveShell.colors = 'LightBG' | |
63 |
|
63 | |||
64 | # c.InteractiveShell.color_info = True |
|
64 | # c.InteractiveShell.color_info = True | |
65 |
|
65 | |||
66 | # c.InteractiveShell.confirm_exit = True |
|
66 | # c.InteractiveShell.confirm_exit = True | |
67 |
|
67 | |||
68 | # c.InteractiveShell.deep_reload = False |
|
68 | # c.InteractiveShell.deep_reload = False | |
69 |
|
69 | |||
70 | # c.InteractiveShell.editor = 'nano' |
|
70 | # c.InteractiveShell.editor = 'nano' | |
71 |
|
71 | |||
72 | # c.InteractiveShell.logstart = True |
|
72 | # c.InteractiveShell.logstart = True | |
73 |
|
73 | |||
74 | # c.InteractiveShell.logfile = 'ipython_log.py' |
|
74 | # c.InteractiveShell.logfile = 'ipython_log.py' | |
75 |
|
75 | |||
76 | # c.InteractiveShell.logappend = 'mylog.py' |
|
76 | # c.InteractiveShell.logappend = 'mylog.py' | |
77 |
|
77 | |||
78 | # c.InteractiveShell.object_info_string_level = 0 |
|
78 | # c.InteractiveShell.object_info_string_level = 0 | |
79 |
|
79 | |||
80 | # c.InteractiveShell.pager = 'less' |
|
80 | # c.InteractiveShell.pager = 'less' | |
81 |
|
81 | |||
82 | # c.InteractiveShell.pdb = False |
|
82 | # c.InteractiveShell.pdb = False | |
83 |
|
83 | |||
84 | # c.InteractiveShell.pprint = True |
|
84 | # c.InteractiveShell.pprint = True | |
85 |
|
85 | |||
86 | # c.InteractiveShell.prompt_in1 = 'In [\#]: ' |
|
86 | # c.InteractiveShell.prompt_in1 = 'In [\#]: ' | |
87 | # c.InteractiveShell.prompt_in2 = ' .\D.: ' |
|
87 | # c.InteractiveShell.prompt_in2 = ' .\D.: ' | |
88 | # c.InteractiveShell.prompt_out = 'Out[\#]: ' |
|
88 | # c.InteractiveShell.prompt_out = 'Out[\#]: ' | |
89 | # c.InteractiveShell.prompts_pad_left = True |
|
89 | # c.InteractiveShell.prompts_pad_left = True | |
90 |
|
90 | |||
91 | # c.InteractiveShell.quiet = False |
|
91 | # c.InteractiveShell.quiet = False | |
92 |
|
92 | |||
93 | # Readline |
|
93 | # Readline | |
94 | # c.InteractiveShell.readline_use = True |
|
94 | # c.InteractiveShell.readline_use = True | |
95 |
|
95 | |||
96 | # c.InteractiveShell.readline_parse_and_bind = [ |
|
96 | # c.InteractiveShell.readline_parse_and_bind = [ | |
97 | # 'tab: complete', |
|
97 | # 'tab: complete', | |
98 | # '"\C-l": possible-completions', |
|
98 | # '"\C-l": possible-completions', | |
99 | # 'set show-all-if-ambiguous on', |
|
99 | # 'set show-all-if-ambiguous on', | |
100 | # '"\C-o": tab-insert', |
|
100 | # '"\C-o": tab-insert', | |
101 | # '"\M-i": " "', |
|
101 | # '"\M-i": " "', | |
102 | # '"\M-o": "\d\d\d\d"', |
|
102 | # '"\M-o": "\d\d\d\d"', | |
103 | # '"\M-I": "\d\d\d\d"', |
|
103 | # '"\M-I": "\d\d\d\d"', | |
104 | # '"\C-r": reverse-search-history', |
|
104 | # '"\C-r": reverse-search-history', | |
105 | # '"\C-s": forward-search-history', |
|
105 | # '"\C-s": forward-search-history', | |
106 | # '"\C-p": history-search-backward', |
|
106 | # '"\C-p": history-search-backward', | |
107 | # '"\C-n": history-search-forward', |
|
107 | # '"\C-n": history-search-forward', | |
108 | # '"\e[A": history-search-backward', |
|
108 | # '"\e[A": history-search-backward', | |
109 | # '"\e[B": history-search-forward', |
|
109 | # '"\e[B": history-search-forward', | |
110 | # '"\C-k": kill-line', |
|
110 | # '"\C-k": kill-line', | |
111 | # '"\C-u": unix-line-discard', |
|
111 | # '"\C-u": unix-line-discard', | |
112 | # ] |
|
112 | # ] | |
113 | # c.InteractiveShell.readline_remove_delims = '-/~' |
|
113 | # c.InteractiveShell.readline_remove_delims = '-/~' | |
114 | # c.InteractiveShell.readline_merge_completions = True |
|
114 | # c.InteractiveShell.readline_merge_completions = True | |
115 | # c.InteractiveShell.readline_omit_names = 0 |
|
115 | # c.InteractiveShell.readline_omit_names = 0 | |
116 |
|
116 | |||
117 | # c.InteractiveShell.screen_length = 0 |
|
117 | # c.InteractiveShell.screen_length = 0 | |
118 |
|
118 | |||
119 | # c.InteractiveShell.separate_in = '\n' |
|
119 | # c.InteractiveShell.separate_in = '\n' | |
120 | # c.InteractiveShell.separate_out = '' |
|
120 | # c.InteractiveShell.separate_out = '' | |
121 | # c.InteractiveShell.separate_out2 = '' |
|
121 | # c.InteractiveShell.separate_out2 = '' | |
122 |
|
122 | |||
123 | # c.InteractiveShell.system_header = "IPython system call: " |
|
123 | # c.InteractiveShell.system_header = "IPython system call: " | |
124 |
|
124 | |||
125 | # c.InteractiveShell.system_verbose = True |
|
125 | # c.InteractiveShell.system_verbose = True | |
126 |
|
126 | |||
127 | # c.InteractiveShell.term_title = False |
|
127 | # c.InteractiveShell.term_title = False | |
128 |
|
128 | |||
129 | # c.InteractiveShell.wildcards_case_sensitive = True |
|
129 | # c.InteractiveShell.wildcards_case_sensitive = True | |
130 |
|
130 | |||
131 | # c.InteractiveShell.xmode = 'Context' |
|
131 | # c.InteractiveShell.xmode = 'Context' | |
132 |
|
132 | |||
133 | #----------------------------------------------------------------------------- |
|
133 | #----------------------------------------------------------------------------- | |
134 | # PrefilterManager options |
|
134 | # PrefilterManager options | |
135 | #----------------------------------------------------------------------------- |
|
135 | #----------------------------------------------------------------------------- | |
136 |
|
136 | |||
137 | # c.PrefilterManager.multi_line_specials = True |
|
137 | # c.PrefilterManager.multi_line_specials = True | |
138 |
|
138 | |||
139 | #----------------------------------------------------------------------------- |
|
139 | #----------------------------------------------------------------------------- | |
140 | # AliasManager options |
|
140 | # AliasManager options | |
141 | #----------------------------------------------------------------------------- |
|
141 | #----------------------------------------------------------------------------- | |
142 |
|
142 | |||
143 |
# Do this to |
|
143 | # Do this to disable all defaults | |
144 | # c.AliasManager.default_aliases = [] |
|
144 | # c.AliasManager.default_aliases = [] | |
145 |
|
145 | |||
146 | # c.AliasManager.user_aliases = [ |
|
146 | # c.AliasManager.user_aliases = [ | |
147 | # ('foo', 'echo Hi') |
|
147 | # ('foo', 'echo Hi') | |
148 | # ] No newline at end of file |
|
148 | # ] |
@@ -1,325 +1,325 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """ |
|
3 | """ | |
4 | A lightweight component system for IPython. |
|
4 | A lightweight component system for IPython. | |
5 |
|
5 | |||
6 | Authors: |
|
6 | Authors: | |
7 |
|
7 | |||
8 | * Brian Granger |
|
8 | * Brian Granger | |
9 | * Fernando Perez |
|
9 | * Fernando Perez | |
10 | """ |
|
10 | """ | |
11 |
|
11 | |||
12 | #----------------------------------------------------------------------------- |
|
12 | #----------------------------------------------------------------------------- | |
13 | # Copyright (C) 2008-2009 The IPython Development Team |
|
13 | # Copyright (C) 2008-2009 The IPython Development Team | |
14 | # |
|
14 | # | |
15 | # Distributed under the terms of the BSD License. The full license is in |
|
15 | # Distributed under the terms of the BSD License. The full license is in | |
16 | # the file COPYING, distributed as part of this software. |
|
16 | # the file COPYING, distributed as part of this software. | |
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Imports |
|
20 | # Imports | |
21 | #----------------------------------------------------------------------------- |
|
21 | #----------------------------------------------------------------------------- | |
22 |
|
22 | |||
23 | from copy import deepcopy |
|
23 | from copy import deepcopy | |
24 | import datetime |
|
24 | import datetime | |
25 | from weakref import WeakValueDictionary |
|
25 | from weakref import WeakValueDictionary | |
26 |
|
26 | |||
27 | from IPython.utils.importstring import import_item |
|
27 | from IPython.utils.importstring import import_item | |
28 | from IPython.config.loader import Config |
|
28 | from IPython.config.loader import Config | |
29 | from IPython.utils.traitlets import ( |
|
29 | from IPython.utils.traitlets import ( | |
30 | HasTraitlets, TraitletError, MetaHasTraitlets, Instance, This |
|
30 | HasTraitlets, TraitletError, MetaHasTraitlets, Instance, This | |
31 | ) |
|
31 | ) | |
32 |
|
32 | |||
33 |
|
33 | |||
34 | #----------------------------------------------------------------------------- |
|
34 | #----------------------------------------------------------------------------- | |
35 | # Helper classes for Components |
|
35 | # Helper classes for Components | |
36 | #----------------------------------------------------------------------------- |
|
36 | #----------------------------------------------------------------------------- | |
37 |
|
37 | |||
38 |
|
38 | |||
39 | class ComponentError(Exception): |
|
39 | class ComponentError(Exception): | |
40 | pass |
|
40 | pass | |
41 |
|
41 | |||
42 | class MetaComponentTracker(type): |
|
42 | class MetaComponentTracker(type): | |
43 | """A metaclass that tracks instances of Components and its subclasses.""" |
|
43 | """A metaclass that tracks instances of Components and its subclasses.""" | |
44 |
|
44 | |||
45 | def __init__(cls, name, bases, d): |
|
45 | def __init__(cls, name, bases, d): | |
46 | super(MetaComponentTracker, cls).__init__(name, bases, d) |
|
46 | super(MetaComponentTracker, cls).__init__(name, bases, d) | |
47 | cls.__instance_refs = WeakValueDictionary() |
|
47 | cls.__instance_refs = WeakValueDictionary() | |
48 | cls.__numcreated = 0 |
|
48 | cls.__numcreated = 0 | |
49 |
|
49 | |||
50 | def __call__(cls, *args, **kw): |
|
50 | def __call__(cls, *args, **kw): | |
51 | """Called when a class is called (instantiated)!!! |
|
51 | """Called when a class is called (instantiated)!!! | |
52 |
|
52 | |||
53 | When a Component or subclass is instantiated, this is called and |
|
53 | When a Component or subclass is instantiated, this is called and | |
54 | the instance is saved in a WeakValueDictionary for tracking. |
|
54 | the instance is saved in a WeakValueDictionary for tracking. | |
55 | """ |
|
55 | """ | |
56 | instance = cls.__new__(cls, *args, **kw) |
|
56 | instance = cls.__new__(cls, *args, **kw) | |
57 |
|
57 | |||
58 | # Register the instance before __init__ is called so get_instances |
|
58 | # Register the instance before __init__ is called so get_instances | |
59 | # works inside __init__ methods! |
|
59 | # works inside __init__ methods! | |
60 | indices = cls.register_instance(instance) |
|
60 | indices = cls.register_instance(instance) | |
61 |
|
61 | |||
62 | # This is in a try/except because of the __init__ method fails, the |
|
62 | # This is in a try/except because of the __init__ method fails, the | |
63 | # instance is discarded and shouldn't be tracked. |
|
63 | # instance is discarded and shouldn't be tracked. | |
64 | try: |
|
64 | try: | |
65 | if isinstance(instance, cls): |
|
65 | if isinstance(instance, cls): | |
66 | cls.__init__(instance, *args, **kw) |
|
66 | cls.__init__(instance, *args, **kw) | |
67 | except: |
|
67 | except: | |
68 | # Unregister the instance because __init__ failed! |
|
68 | # Unregister the instance because __init__ failed! | |
69 | cls.unregister_instances(indices) |
|
69 | cls.unregister_instances(indices) | |
70 | raise |
|
70 | raise | |
71 | else: |
|
71 | else: | |
72 | return instance |
|
72 | return instance | |
73 |
|
73 | |||
74 | def register_instance(cls, instance): |
|
74 | def register_instance(cls, instance): | |
75 | """Register instance with cls and its subclasses.""" |
|
75 | """Register instance with cls and its subclasses.""" | |
76 | # indices is a list of the keys used to register the instance |
|
76 | # indices is a list of the keys used to register the instance | |
77 | # with. This list is needed if the instance needs to be unregistered. |
|
77 | # with. This list is needed if the instance needs to be unregistered. | |
78 | indices = [] |
|
78 | indices = [] | |
79 | for c in cls.__mro__: |
|
79 | for c in cls.__mro__: | |
80 | if issubclass(cls, c) and issubclass(c, Component): |
|
80 | if issubclass(cls, c) and issubclass(c, Component): | |
81 | c.__numcreated += 1 |
|
81 | c.__numcreated += 1 | |
82 | indices.append(c.__numcreated) |
|
82 | indices.append(c.__numcreated) | |
83 | c.__instance_refs[c.__numcreated] = instance |
|
83 | c.__instance_refs[c.__numcreated] = instance | |
84 | else: |
|
84 | else: | |
85 | break |
|
85 | break | |
86 | return indices |
|
86 | return indices | |
87 |
|
87 | |||
88 | def unregister_instances(cls, indices): |
|
88 | def unregister_instances(cls, indices): | |
89 | """Unregister instance with cls and its subclasses.""" |
|
89 | """Unregister instance with cls and its subclasses.""" | |
90 | for c, index in zip(cls.__mro__, indices): |
|
90 | for c, index in zip(cls.__mro__, indices): | |
91 | try: |
|
91 | try: | |
92 | del c.__instance_refs[index] |
|
92 | del c.__instance_refs[index] | |
93 | except KeyError: |
|
93 | except KeyError: | |
94 | pass |
|
94 | pass | |
95 |
|
95 | |||
96 | def clear_instances(cls): |
|
96 | def clear_instances(cls): | |
97 | """Clear all instances tracked by cls.""" |
|
97 | """Clear all instances tracked by cls.""" | |
98 | cls.__instance_refs.clear() |
|
98 | cls.__instance_refs.clear() | |
99 | cls.__numcreated = 0 |
|
99 | cls.__numcreated = 0 | |
100 |
|
100 | |||
101 | def get_instances(cls, name=None, root=None, klass=None): |
|
101 | def get_instances(cls, name=None, root=None, klass=None): | |
102 | """Get all instances of cls and its subclasses. |
|
102 | """Get all instances of cls and its subclasses. | |
103 |
|
103 | |||
104 | Parameters |
|
104 | Parameters | |
105 | ---------- |
|
105 | ---------- | |
106 | name : str |
|
106 | name : str | |
107 | Limit to components with this name. |
|
107 | Limit to components with this name. | |
108 | root : Component or subclass |
|
108 | root : Component or subclass | |
109 | Limit to components having this root. |
|
109 | Limit to components having this root. | |
110 | klass : class or str |
|
110 | klass : class or str | |
111 | Limits to instances of the class or its subclasses. If a str |
|
111 | Limits to instances of the class or its subclasses. If a str | |
112 | is given ut must be in the form 'foo.bar.MyClass'. The str |
|
112 | is given ut must be in the form 'foo.bar.MyClass'. The str | |
113 | form of this argument is useful for forward declarations. |
|
113 | form of this argument is useful for forward declarations. | |
114 | """ |
|
114 | """ | |
115 | if klass is not None: |
|
115 | if klass is not None: | |
116 | if isinstance(klass, basestring): |
|
116 | if isinstance(klass, basestring): | |
117 | klass = import_item(klass) |
|
117 | klass = import_item(klass) | |
118 | # Limit search to instances of klass for performance |
|
118 | # Limit search to instances of klass for performance | |
119 | if issubclass(klass, Component): |
|
119 | if issubclass(klass, Component): | |
120 | return klass.get_instances(name=name, root=root) |
|
120 | return klass.get_instances(name=name, root=root) | |
121 | instances = cls.__instance_refs.values() |
|
121 | instances = cls.__instance_refs.values() | |
122 | if name is not None: |
|
122 | if name is not None: | |
123 | instances = [i for i in instances if i.name == name] |
|
123 | instances = [i for i in instances if i.name == name] | |
124 | if klass is not None: |
|
124 | if klass is not None: | |
125 | instances = [i for i in instances if isinstance(i, klass)] |
|
125 | instances = [i for i in instances if isinstance(i, klass)] | |
126 | if root is not None: |
|
126 | if root is not None: | |
127 | instances = [i for i in instances if i.root == root] |
|
127 | instances = [i for i in instances if i.root == root] | |
128 | return instances |
|
128 | return instances | |
129 |
|
129 | |||
130 | def get_instances_by_condition(cls, call, name=None, root=None, |
|
130 | def get_instances_by_condition(cls, call, name=None, root=None, | |
131 | klass=None): |
|
131 | klass=None): | |
132 | """Get all instances of cls, i such that call(i)==True. |
|
132 | """Get all instances of cls, i such that call(i)==True. | |
133 |
|
133 | |||
134 | This also takes the ``name`` and ``root`` and ``classname`` |
|
134 | This also takes the ``name`` and ``root`` and ``classname`` | |
135 | arguments of :meth:`get_instance` |
|
135 | arguments of :meth:`get_instance` | |
136 | """ |
|
136 | """ | |
137 | return [i for i in cls.get_instances(name, root, klass) if call(i)] |
|
137 | return [i for i in cls.get_instances(name, root, klass) if call(i)] | |
138 |
|
138 | |||
139 |
|
139 | |||
140 | def masquerade_as(instance, cls): |
|
140 | def masquerade_as(instance, cls): | |
141 | """Let instance masquerade as an instance of cls. |
|
141 | """Let instance masquerade as an instance of cls. | |
142 |
|
142 | |||
143 | Sometimes, such as in testing code, it is useful to let a class |
|
143 | Sometimes, such as in testing code, it is useful to let a class | |
144 | masquerade as another. Python, being duck typed, allows this by |
|
144 | masquerade as another. Python, being duck typed, allows this by | |
145 | default. But, instances of components are tracked by their class type. |
|
145 | default. But, instances of components are tracked by their class type. | |
146 |
|
146 | |||
147 |
After calling this, cls.get_instances() will return ``instance``. |
|
147 | After calling this, ``cls.get_instances()`` will return ``instance``. This | |
148 | does not, however, cause isinstance(instance, cls) to return ``True``. |
|
148 | does not, however, cause ``isinstance(instance, cls)`` to return ``True``. | |
149 |
|
149 | |||
150 | Parameters |
|
150 | Parameters | |
151 | ---------- |
|
151 | ---------- | |
152 | instance : an instance of a Component or Component subclass |
|
152 | instance : an instance of a Component or Component subclass | |
153 | The instance that will pretend to be a cls. |
|
153 | The instance that will pretend to be a cls. | |
154 | cls : subclass of Component |
|
154 | cls : subclass of Component | |
155 | The Component subclass that instance will pretend to be. |
|
155 | The Component subclass that instance will pretend to be. | |
156 | """ |
|
156 | """ | |
157 | cls.register_instance(instance) |
|
157 | cls.register_instance(instance) | |
158 |
|
158 | |||
159 |
|
159 | |||
160 | class ComponentNameGenerator(object): |
|
160 | class ComponentNameGenerator(object): | |
161 | """A Singleton to generate unique component names.""" |
|
161 | """A Singleton to generate unique component names.""" | |
162 |
|
162 | |||
163 | def __init__(self, prefix): |
|
163 | def __init__(self, prefix): | |
164 | self.prefix = prefix |
|
164 | self.prefix = prefix | |
165 | self.i = 0 |
|
165 | self.i = 0 | |
166 |
|
166 | |||
167 | def __call__(self): |
|
167 | def __call__(self): | |
168 | count = self.i |
|
168 | count = self.i | |
169 | self.i += 1 |
|
169 | self.i += 1 | |
170 | return "%s%s" % (self.prefix, count) |
|
170 | return "%s%s" % (self.prefix, count) | |
171 |
|
171 | |||
172 |
|
172 | |||
173 | ComponentNameGenerator = ComponentNameGenerator('ipython.component') |
|
173 | ComponentNameGenerator = ComponentNameGenerator('ipython.component') | |
174 |
|
174 | |||
175 |
|
175 | |||
176 | class MetaComponent(MetaHasTraitlets, MetaComponentTracker): |
|
176 | class MetaComponent(MetaHasTraitlets, MetaComponentTracker): | |
177 | pass |
|
177 | pass | |
178 |
|
178 | |||
179 |
|
179 | |||
180 | #----------------------------------------------------------------------------- |
|
180 | #----------------------------------------------------------------------------- | |
181 | # Component implementation |
|
181 | # Component implementation | |
182 | #----------------------------------------------------------------------------- |
|
182 | #----------------------------------------------------------------------------- | |
183 |
|
183 | |||
184 |
|
184 | |||
185 | class Component(HasTraitlets): |
|
185 | class Component(HasTraitlets): | |
186 |
|
186 | |||
187 | __metaclass__ = MetaComponent |
|
187 | __metaclass__ = MetaComponent | |
188 |
|
188 | |||
189 | # Traitlets are fun! |
|
189 | # Traitlets are fun! | |
190 | config = Instance(Config,(),{}) |
|
190 | config = Instance(Config,(),{}) | |
191 | parent = This() |
|
191 | parent = This() | |
192 | root = This() |
|
192 | root = This() | |
193 | created = None |
|
193 | created = None | |
194 |
|
194 | |||
195 | def __init__(self, parent, name=None, config=None): |
|
195 | def __init__(self, parent, name=None, config=None): | |
196 | """Create a component given a parent and possibly and name and config. |
|
196 | """Create a component given a parent and possibly and name and config. | |
197 |
|
197 | |||
198 | Parameters |
|
198 | Parameters | |
199 | ---------- |
|
199 | ---------- | |
200 | parent : Component subclass |
|
200 | parent : Component subclass | |
201 | The parent in the component graph. The parent is used |
|
201 | The parent in the component graph. The parent is used | |
202 | to get the root of the component graph. |
|
202 | to get the root of the component graph. | |
203 | name : str |
|
203 | name : str | |
204 | The unique name of the component. If empty, then a unique |
|
204 | The unique name of the component. If empty, then a unique | |
205 | one will be autogenerated. |
|
205 | one will be autogenerated. | |
206 | config : Config |
|
206 | config : Config | |
207 | If this is empty, self.config = parent.config, otherwise |
|
207 | If this is empty, self.config = parent.config, otherwise | |
208 | self.config = config and root.config is ignored. This argument |
|
208 | self.config = config and root.config is ignored. This argument | |
209 | should only be used to *override* the automatic inheritance of |
|
209 | should only be used to *override* the automatic inheritance of | |
210 | parent.config. If a caller wants to modify parent.config |
|
210 | parent.config. If a caller wants to modify parent.config | |
211 | (not override), the caller should make a copy and change |
|
211 | (not override), the caller should make a copy and change | |
212 | attributes and then pass the copy to this argument. |
|
212 | attributes and then pass the copy to this argument. | |
213 |
|
213 | |||
214 | Notes |
|
214 | Notes | |
215 | ----- |
|
215 | ----- | |
216 | Subclasses of Component must call the :meth:`__init__` method of |
|
216 | Subclasses of Component must call the :meth:`__init__` method of | |
217 | :class:`Component` *before* doing anything else and using |
|
217 | :class:`Component` *before* doing anything else and using | |
218 | :func:`super`:: |
|
218 | :func:`super`:: | |
219 |
|
219 | |||
220 | class MyComponent(Component): |
|
220 | class MyComponent(Component): | |
221 | def __init__(self, parent, name=None, config=None): |
|
221 | def __init__(self, parent, name=None, config=None): | |
222 | super(MyComponent, self).__init__(parent, name, config) |
|
222 | super(MyComponent, self).__init__(parent, name, config) | |
223 | # Then any other code you need to finish initialization. |
|
223 | # Then any other code you need to finish initialization. | |
224 |
|
224 | |||
225 | This ensures that the :attr:`parent`, :attr:`name` and :attr:`config` |
|
225 | This ensures that the :attr:`parent`, :attr:`name` and :attr:`config` | |
226 | attributes are handled properly. |
|
226 | attributes are handled properly. | |
227 | """ |
|
227 | """ | |
228 | super(Component, self).__init__() |
|
228 | super(Component, self).__init__() | |
229 | self._children = [] |
|
229 | self._children = [] | |
230 | if name is None: |
|
230 | if name is None: | |
231 | self.name = ComponentNameGenerator() |
|
231 | self.name = ComponentNameGenerator() | |
232 | else: |
|
232 | else: | |
233 | self.name = name |
|
233 | self.name = name | |
234 | self.root = self # This is the default, it is set when parent is set |
|
234 | self.root = self # This is the default, it is set when parent is set | |
235 | self.parent = parent |
|
235 | self.parent = parent | |
236 | if config is not None: |
|
236 | if config is not None: | |
237 | self.config = config |
|
237 | self.config = config | |
238 | # We used to deepcopy, but for now we are trying to just save |
|
238 | # We used to deepcopy, but for now we are trying to just save | |
239 | # by reference. This *could* have side effects as all components |
|
239 | # by reference. This *could* have side effects as all components | |
240 | # will share config. |
|
240 | # will share config. | |
241 | # self.config = deepcopy(config) |
|
241 | # self.config = deepcopy(config) | |
242 | else: |
|
242 | else: | |
243 | if self.parent is not None: |
|
243 | if self.parent is not None: | |
244 | self.config = self.parent.config |
|
244 | self.config = self.parent.config | |
245 | # We used to deepcopy, but for now we are trying to just save |
|
245 | # We used to deepcopy, but for now we are trying to just save | |
246 | # by reference. This *could* have side effects as all components |
|
246 | # by reference. This *could* have side effects as all components | |
247 | # will share config. |
|
247 | # will share config. | |
248 | # self.config = deepcopy(self.parent.config) |
|
248 | # self.config = deepcopy(self.parent.config) | |
249 |
|
249 | |||
250 | self.created = datetime.datetime.now() |
|
250 | self.created = datetime.datetime.now() | |
251 |
|
251 | |||
252 | #------------------------------------------------------------------------- |
|
252 | #------------------------------------------------------------------------- | |
253 | # Static traitlet notifiations |
|
253 | # Static traitlet notifiations | |
254 | #------------------------------------------------------------------------- |
|
254 | #------------------------------------------------------------------------- | |
255 |
|
255 | |||
256 | def _parent_changed(self, name, old, new): |
|
256 | def _parent_changed(self, name, old, new): | |
257 | if old is not None: |
|
257 | if old is not None: | |
258 | old._remove_child(self) |
|
258 | old._remove_child(self) | |
259 | if new is not None: |
|
259 | if new is not None: | |
260 | new._add_child(self) |
|
260 | new._add_child(self) | |
261 |
|
261 | |||
262 | if new is None: |
|
262 | if new is None: | |
263 | self.root = self |
|
263 | self.root = self | |
264 | else: |
|
264 | else: | |
265 | self.root = new.root |
|
265 | self.root = new.root | |
266 |
|
266 | |||
267 | def _root_changed(self, name, old, new): |
|
267 | def _root_changed(self, name, old, new): | |
268 | if self.parent is None: |
|
268 | if self.parent is None: | |
269 | if not (new is self): |
|
269 | if not (new is self): | |
270 | raise ComponentError("Root not self, but parent is None.") |
|
270 | raise ComponentError("Root not self, but parent is None.") | |
271 | else: |
|
271 | else: | |
272 | if not self.parent.root is new: |
|
272 | if not self.parent.root is new: | |
273 | raise ComponentError("Error in setting the root attribute: " |
|
273 | raise ComponentError("Error in setting the root attribute: " | |
274 | "root != parent.root") |
|
274 | "root != parent.root") | |
275 |
|
275 | |||
276 | def _config_changed(self, name, old, new): |
|
276 | def _config_changed(self, name, old, new): | |
277 | """Update all the class traits having ``config=True`` as metadata. |
|
277 | """Update all the class traits having ``config=True`` as metadata. | |
278 |
|
278 | |||
279 | For any class traitlet with a ``config`` metadata attribute that is |
|
279 | For any class traitlet with a ``config`` metadata attribute that is | |
280 | ``True``, we update the traitlet with the value of the corresponding |
|
280 | ``True``, we update the traitlet with the value of the corresponding | |
281 | config entry. |
|
281 | config entry. | |
282 | """ |
|
282 | """ | |
283 | # Get all traitlets with a config metadata entry that is True |
|
283 | # Get all traitlets with a config metadata entry that is True | |
284 | traitlets = self.traitlets(config=True) |
|
284 | traitlets = self.traitlets(config=True) | |
285 |
|
285 | |||
286 | # We auto-load config section for this class as well as any parent |
|
286 | # We auto-load config section for this class as well as any parent | |
287 | # classes that are Component subclasses. This starts with Component |
|
287 | # classes that are Component subclasses. This starts with Component | |
288 | # and works down the mro loading the config for each section. |
|
288 | # and works down the mro loading the config for each section. | |
289 | section_names = [cls.__name__ for cls in \ |
|
289 | section_names = [cls.__name__ for cls in \ | |
290 | reversed(self.__class__.__mro__) if |
|
290 | reversed(self.__class__.__mro__) if | |
291 | issubclass(cls, Component) and issubclass(self.__class__, cls)] |
|
291 | issubclass(cls, Component) and issubclass(self.__class__, cls)] | |
292 |
|
292 | |||
293 | for sname in section_names: |
|
293 | for sname in section_names: | |
294 | # Don't do a blind getattr as that would cause the config to |
|
294 | # Don't do a blind getattr as that would cause the config to | |
295 | # dynamically create the section with name self.__class__.__name__. |
|
295 | # dynamically create the section with name self.__class__.__name__. | |
296 | if new._has_section(sname): |
|
296 | if new._has_section(sname): | |
297 | my_config = new[sname] |
|
297 | my_config = new[sname] | |
298 | for k, v in traitlets.items(): |
|
298 | for k, v in traitlets.items(): | |
299 | try: |
|
299 | try: | |
300 | config_value = my_config[k] |
|
300 | config_value = my_config[k] | |
301 | except KeyError: |
|
301 | except KeyError: | |
302 | pass |
|
302 | pass | |
303 | else: |
|
303 | else: | |
304 | # print "Setting %s.%s from %s.%s=%r" % \ |
|
304 | # print "Setting %s.%s from %s.%s=%r" % \ | |
305 | # (self.__class__.__name__,k,sname,k,config_value) |
|
305 | # (self.__class__.__name__,k,sname,k,config_value) | |
306 | setattr(self, k, config_value) |
|
306 | setattr(self, k, config_value) | |
307 |
|
307 | |||
308 | @property |
|
308 | @property | |
309 | def children(self): |
|
309 | def children(self): | |
310 | """A list of all my child components.""" |
|
310 | """A list of all my child components.""" | |
311 | return self._children |
|
311 | return self._children | |
312 |
|
312 | |||
313 | def _remove_child(self, child): |
|
313 | def _remove_child(self, child): | |
314 | """A private method for removing children components.""" |
|
314 | """A private method for removing children components.""" | |
315 | if child in self._children: |
|
315 | if child in self._children: | |
316 | index = self._children.index(child) |
|
316 | index = self._children.index(child) | |
317 | del self._children[index] |
|
317 | del self._children[index] | |
318 |
|
318 | |||
319 | def _add_child(self, child): |
|
319 | def _add_child(self, child): | |
320 | """A private method for adding children components.""" |
|
320 | """A private method for adding children components.""" | |
321 | if child not in self._children: |
|
321 | if child not in self._children: | |
322 | self._children.append(child) |
|
322 | self._children.append(child) | |
323 |
|
323 | |||
324 | def __repr__(self): |
|
324 | def __repr__(self): | |
325 | return "<%s('%s')>" % (self.__class__.__name__, self.name) |
|
325 | return "<%s('%s')>" % (self.__class__.__name__, self.name) |
@@ -1,995 +1,995 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """ |
|
3 | """ | |
4 | Prefiltering components. |
|
4 | Prefiltering components. | |
5 |
|
5 | |||
6 | Prefilters transform user input before it is exec'd by Python. These |
|
6 | Prefilters transform user input before it is exec'd by Python. These | |
7 | transforms are used to implement additional syntax such as !ls and %magic. |
|
7 | transforms are used to implement additional syntax such as !ls and %magic. | |
8 |
|
8 | |||
9 | Authors: |
|
9 | Authors: | |
10 |
|
10 | |||
11 | * Brian Granger |
|
11 | * Brian Granger | |
12 | * Fernando Perez |
|
12 | * Fernando Perez | |
13 | * Dan Milstein |
|
13 | * Dan Milstein | |
14 | * Ville Vainio |
|
14 | * Ville Vainio | |
15 | """ |
|
15 | """ | |
16 |
|
16 | |||
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 | # Copyright (C) 2008-2009 The IPython Development Team |
|
18 | # Copyright (C) 2008-2009 The IPython Development Team | |
19 | # |
|
19 | # | |
20 | # Distributed under the terms of the BSD License. The full license is in |
|
20 | # Distributed under the terms of the BSD License. The full license is in | |
21 | # the file COPYING, distributed as part of this software. |
|
21 | # the file COPYING, distributed as part of this software. | |
22 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
23 |
|
23 | |||
24 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
25 | # Imports |
|
25 | # Imports | |
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 |
|
27 | |||
28 | import __builtin__ |
|
28 | import __builtin__ | |
29 | import codeop |
|
29 | import codeop | |
30 | import keyword |
|
30 | import keyword | |
31 | import os |
|
31 | import os | |
32 | import re |
|
32 | import re | |
33 | import sys |
|
33 | import sys | |
34 |
|
34 | |||
35 | from IPython.core.alias import AliasManager |
|
35 | from IPython.core.alias import AliasManager | |
36 | from IPython.core.autocall import IPyAutocall |
|
36 | from IPython.core.autocall import IPyAutocall | |
37 | from IPython.core.component import Component |
|
37 | from IPython.core.component import Component | |
38 | from IPython.core.splitinput import split_user_input |
|
38 | from IPython.core.splitinput import split_user_input | |
39 | from IPython.core.page import page |
|
39 | from IPython.core.page import page | |
40 |
|
40 | |||
41 | from IPython.utils.traitlets import List, Int, Any, Str, CBool, Bool |
|
41 | from IPython.utils.traitlets import List, Int, Any, Str, CBool, Bool | |
42 | from IPython.utils.genutils import make_quoted_expr |
|
42 | from IPython.utils.genutils import make_quoted_expr | |
43 | from IPython.utils.autoattr import auto_attr |
|
43 | from IPython.utils.autoattr import auto_attr | |
44 |
|
44 | |||
45 | #----------------------------------------------------------------------------- |
|
45 | #----------------------------------------------------------------------------- | |
46 | # Global utilities, errors and constants |
|
46 | # Global utilities, errors and constants | |
47 | #----------------------------------------------------------------------------- |
|
47 | #----------------------------------------------------------------------------- | |
48 |
|
48 | |||
49 | # Warning, these cannot be changed unless various regular expressions |
|
49 | # Warning, these cannot be changed unless various regular expressions | |
50 | # are updated in a number of places. Not great, but at least we told you. |
|
50 | # are updated in a number of places. Not great, but at least we told you. | |
51 | ESC_SHELL = '!' |
|
51 | ESC_SHELL = '!' | |
52 | ESC_SH_CAP = '!!' |
|
52 | ESC_SH_CAP = '!!' | |
53 | ESC_HELP = '?' |
|
53 | ESC_HELP = '?' | |
54 | ESC_MAGIC = '%' |
|
54 | ESC_MAGIC = '%' | |
55 | ESC_QUOTE = ',' |
|
55 | ESC_QUOTE = ',' | |
56 | ESC_QUOTE2 = ';' |
|
56 | ESC_QUOTE2 = ';' | |
57 | ESC_PAREN = '/' |
|
57 | ESC_PAREN = '/' | |
58 |
|
58 | |||
59 |
|
59 | |||
60 | class PrefilterError(Exception): |
|
60 | class PrefilterError(Exception): | |
61 | pass |
|
61 | pass | |
62 |
|
62 | |||
63 |
|
63 | |||
64 | # RegExp to identify potential function names |
|
64 | # RegExp to identify potential function names | |
65 | re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') |
|
65 | re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') | |
66 |
|
66 | |||
67 | # RegExp to exclude strings with this start from autocalling. In |
|
67 | # RegExp to exclude strings with this start from autocalling. In | |
68 | # particular, all binary operators should be excluded, so that if foo is |
|
68 | # particular, all binary operators should be excluded, so that if foo is | |
69 | # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The |
|
69 | # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The | |
70 | # characters '!=()' don't need to be checked for, as the checkPythonChars |
|
70 | # characters '!=()' don't need to be checked for, as the checkPythonChars | |
71 | # routine explicitely does so, to catch direct calls and rebindings of |
|
71 | # routine explicitely does so, to catch direct calls and rebindings of | |
72 | # existing names. |
|
72 | # existing names. | |
73 |
|
73 | |||
74 | # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise |
|
74 | # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise | |
75 | # it affects the rest of the group in square brackets. |
|
75 | # it affects the rest of the group in square brackets. | |
76 | re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' |
|
76 | re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' | |
77 | r'|^is |^not |^in |^and |^or ') |
|
77 | r'|^is |^not |^in |^and |^or ') | |
78 |
|
78 | |||
79 | # try to catch also methods for stuff in lists/tuples/dicts: off |
|
79 | # try to catch also methods for stuff in lists/tuples/dicts: off | |
80 | # (experimental). For this to work, the line_split regexp would need |
|
80 | # (experimental). For this to work, the line_split regexp would need | |
81 | # to be modified so it wouldn't break things at '['. That line is |
|
81 | # to be modified so it wouldn't break things at '['. That line is | |
82 | # nasty enough that I shouldn't change it until I can test it _well_. |
|
82 | # nasty enough that I shouldn't change it until I can test it _well_. | |
83 | #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') |
|
83 | #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') | |
84 |
|
84 | |||
85 |
|
85 | |||
86 | # Handler Check Utilities |
|
86 | # Handler Check Utilities | |
87 | def is_shadowed(identifier, ip): |
|
87 | def is_shadowed(identifier, ip): | |
88 | """Is the given identifier defined in one of the namespaces which shadow |
|
88 | """Is the given identifier defined in one of the namespaces which shadow | |
89 | the alias and magic namespaces? Note that an identifier is different |
|
89 | the alias and magic namespaces? Note that an identifier is different | |
90 | than ifun, because it can not contain a '.' character.""" |
|
90 | than ifun, because it can not contain a '.' character.""" | |
91 | # This is much safer than calling ofind, which can change state |
|
91 | # This is much safer than calling ofind, which can change state | |
92 | return (identifier in ip.user_ns \ |
|
92 | return (identifier in ip.user_ns \ | |
93 | or identifier in ip.internal_ns \ |
|
93 | or identifier in ip.internal_ns \ | |
94 | or identifier in ip.ns_table['builtin']) |
|
94 | or identifier in ip.ns_table['builtin']) | |
95 |
|
95 | |||
96 |
|
96 | |||
97 | #----------------------------------------------------------------------------- |
|
97 | #----------------------------------------------------------------------------- | |
98 | # The LineInfo class used throughout |
|
98 | # The LineInfo class used throughout | |
99 | #----------------------------------------------------------------------------- |
|
99 | #----------------------------------------------------------------------------- | |
100 |
|
100 | |||
101 |
|
101 | |||
102 | class LineInfo(object): |
|
102 | class LineInfo(object): | |
103 | """A single line of input and associated info. |
|
103 | """A single line of input and associated info. | |
104 |
|
104 | |||
105 | Includes the following as properties: |
|
105 | Includes the following as properties: | |
106 |
|
106 | |||
107 | line |
|
107 | line | |
108 | The original, raw line |
|
108 | The original, raw line | |
109 |
|
109 | |||
110 | continue_prompt |
|
110 | continue_prompt | |
111 | Is this line a continuation in a sequence of multiline input? |
|
111 | Is this line a continuation in a sequence of multiline input? | |
112 |
|
112 | |||
113 | pre |
|
113 | pre | |
114 | The initial esc character or whitespace. |
|
114 | The initial esc character or whitespace. | |
115 |
|
115 | |||
116 | pre_char |
|
116 | pre_char | |
117 | The escape character(s) in pre or the empty string if there isn't one. |
|
117 | The escape character(s) in pre or the empty string if there isn't one. | |
118 | Note that '!!' is a possible value for pre_char. Otherwise it will |
|
118 | Note that '!!' is a possible value for pre_char. Otherwise it will | |
119 | always be a single character. |
|
119 | always be a single character. | |
120 |
|
120 | |||
121 | pre_whitespace |
|
121 | pre_whitespace | |
122 | The leading whitespace from pre if it exists. If there is a pre_char, |
|
122 | The leading whitespace from pre if it exists. If there is a pre_char, | |
123 | this is just ''. |
|
123 | this is just ''. | |
124 |
|
124 | |||
125 | ifun |
|
125 | ifun | |
126 | The 'function part', which is basically the maximal initial sequence |
|
126 | The 'function part', which is basically the maximal initial sequence | |
127 | of valid python identifiers and the '.' character. This is what is |
|
127 | of valid python identifiers and the '.' character. This is what is | |
128 | checked for alias and magic transformations, used for auto-calling, |
|
128 | checked for alias and magic transformations, used for auto-calling, | |
129 | etc. |
|
129 | etc. | |
130 |
|
130 | |||
131 | the_rest |
|
131 | the_rest | |
132 | Everything else on the line. |
|
132 | Everything else on the line. | |
133 | """ |
|
133 | """ | |
134 | def __init__(self, line, continue_prompt): |
|
134 | def __init__(self, line, continue_prompt): | |
135 | self.line = line |
|
135 | self.line = line | |
136 | self.continue_prompt = continue_prompt |
|
136 | self.continue_prompt = continue_prompt | |
137 | self.pre, self.ifun, self.the_rest = split_user_input(line) |
|
137 | self.pre, self.ifun, self.the_rest = split_user_input(line) | |
138 |
|
138 | |||
139 | self.pre_char = self.pre.strip() |
|
139 | self.pre_char = self.pre.strip() | |
140 | if self.pre_char: |
|
140 | if self.pre_char: | |
141 | self.pre_whitespace = '' # No whitespace allowd before esc chars |
|
141 | self.pre_whitespace = '' # No whitespace allowd before esc chars | |
142 | else: |
|
142 | else: | |
143 | self.pre_whitespace = self.pre |
|
143 | self.pre_whitespace = self.pre | |
144 |
|
144 | |||
145 | self._oinfo = None |
|
145 | self._oinfo = None | |
146 |
|
146 | |||
147 | def ofind(self, ip): |
|
147 | def ofind(self, ip): | |
148 | """Do a full, attribute-walking lookup of the ifun in the various |
|
148 | """Do a full, attribute-walking lookup of the ifun in the various | |
149 | namespaces for the given IPython InteractiveShell instance. |
|
149 | namespaces for the given IPython InteractiveShell instance. | |
150 |
|
150 | |||
151 | Return a dict with keys: found,obj,ospace,ismagic |
|
151 | Return a dict with keys: found,obj,ospace,ismagic | |
152 |
|
152 | |||
153 | Note: can cause state changes because of calling getattr, but should |
|
153 | Note: can cause state changes because of calling getattr, but should | |
154 | only be run if autocall is on and if the line hasn't matched any |
|
154 | only be run if autocall is on and if the line hasn't matched any | |
155 | other, less dangerous handlers. |
|
155 | other, less dangerous handlers. | |
156 |
|
156 | |||
157 | Does cache the results of the call, so can be called multiple times |
|
157 | Does cache the results of the call, so can be called multiple times | |
158 | without worrying about *further* damaging state. |
|
158 | without worrying about *further* damaging state. | |
159 | """ |
|
159 | """ | |
160 | if not self._oinfo: |
|
160 | if not self._oinfo: | |
161 | self._oinfo = ip._ofind(self.ifun) |
|
161 | self._oinfo = ip._ofind(self.ifun) | |
162 | return self._oinfo |
|
162 | return self._oinfo | |
163 |
|
163 | |||
164 | def __str__(self): |
|
164 | def __str__(self): | |
165 | return "Lineinfo [%s|%s|%s]" %(self.pre,self.ifun,self.the_rest) |
|
165 | return "Lineinfo [%s|%s|%s]" %(self.pre,self.ifun,self.the_rest) | |
166 |
|
166 | |||
167 |
|
167 | |||
168 | #----------------------------------------------------------------------------- |
|
168 | #----------------------------------------------------------------------------- | |
169 | # Main Prefilter manager |
|
169 | # Main Prefilter manager | |
170 | #----------------------------------------------------------------------------- |
|
170 | #----------------------------------------------------------------------------- | |
171 |
|
171 | |||
172 |
|
172 | |||
173 | class PrefilterManager(Component): |
|
173 | class PrefilterManager(Component): | |
174 | """Main prefilter component. |
|
174 | """Main prefilter component. | |
175 |
|
175 | |||
176 | The IPython prefilter is run on all user input before it is run. The |
|
176 | The IPython prefilter is run on all user input before it is run. The | |
177 | prefilter consumes lines of input and produces transformed lines of |
|
177 | prefilter consumes lines of input and produces transformed lines of | |
178 | input. |
|
178 | input. | |
179 |
|
179 | |||
180 | The iplementation consists of two phases: |
|
180 | The iplementation consists of two phases: | |
181 |
|
181 | |||
182 | 1. Transformers |
|
182 | 1. Transformers | |
183 | 2. Checkers and handlers |
|
183 | 2. Checkers and handlers | |
184 |
|
184 | |||
185 | Over time, we plan on deprecating the checkers and handlers and doing |
|
185 | Over time, we plan on deprecating the checkers and handlers and doing | |
186 | everything in the transformers. |
|
186 | everything in the transformers. | |
187 |
|
187 | |||
188 | The transformers are instances of :class:`PrefilterTransformer` and have |
|
188 | The transformers are instances of :class:`PrefilterTransformer` and have | |
189 | a single method :meth:`transform` that takes a line and returns a |
|
189 | a single method :meth:`transform` that takes a line and returns a | |
190 | transformed line. The transformation can be accomplished using any |
|
190 | transformed line. The transformation can be accomplished using any | |
191 | tool, but our current ones use regular expressions for speed. We also |
|
191 | tool, but our current ones use regular expressions for speed. We also | |
192 | ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers. |
|
192 | ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers. | |
193 |
|
193 | |||
194 | After all the transformers have been run, the line is fed to the checkers, |
|
194 | After all the transformers have been run, the line is fed to the checkers, | |
195 | which are instances of :class:`PrefilterChecker`. The line is passed to |
|
195 | which are instances of :class:`PrefilterChecker`. The line is passed to | |
196 | the :meth:`check` method, which either returns `None` or a |
|
196 | the :meth:`check` method, which either returns `None` or a | |
197 | :class:`PrefilterHandler` instance. If `None` is returned, the other |
|
197 | :class:`PrefilterHandler` instance. If `None` is returned, the other | |
198 | checkers are tried. If an :class:`PrefilterHandler` instance is returned, |
|
198 | checkers are tried. If an :class:`PrefilterHandler` instance is returned, | |
199 | the line is passed to the :meth:`handle` method of the returned |
|
199 | the line is passed to the :meth:`handle` method of the returned | |
200 | handler and no further checkers are tried. |
|
200 | handler and no further checkers are tried. | |
201 |
|
201 | |||
202 | Both transformers and checkers have a `priority` attribute, that determines |
|
202 | Both transformers and checkers have a `priority` attribute, that determines | |
203 | the order in which they are called. Smaller priorities are tried first. |
|
203 | the order in which they are called. Smaller priorities are tried first. | |
204 |
|
204 | |||
205 | Both transformers and checkers also have `enabled` attribute, which is |
|
205 | Both transformers and checkers also have `enabled` attribute, which is | |
206 | a boolean that determines if the instance is used. |
|
206 | a boolean that determines if the instance is used. | |
207 |
|
207 | |||
208 | Users or developers can change the priority or enabled attribute of |
|
208 | Users or developers can change the priority or enabled attribute of | |
209 | transformers or checkers, but they must call the :meth:`sort_checkers` |
|
209 | transformers or checkers, but they must call the :meth:`sort_checkers` | |
210 | or :meth`sort_transformers` method after changing the priority. |
|
210 | or :meth:`sort_transformers` method after changing the priority. | |
211 | """ |
|
211 | """ | |
212 |
|
212 | |||
213 | multi_line_specials = CBool(True, config=True) |
|
213 | multi_line_specials = CBool(True, config=True) | |
214 |
|
214 | |||
215 | def __init__(self, parent, config=None): |
|
215 | def __init__(self, parent, config=None): | |
216 | super(PrefilterManager, self).__init__(parent, config=config) |
|
216 | super(PrefilterManager, self).__init__(parent, config=config) | |
217 | self.init_transformers() |
|
217 | self.init_transformers() | |
218 | self.init_handlers() |
|
218 | self.init_handlers() | |
219 | self.init_checkers() |
|
219 | self.init_checkers() | |
220 |
|
220 | |||
221 | @auto_attr |
|
221 | @auto_attr | |
222 | def shell(self): |
|
222 | def shell(self): | |
223 | return Component.get_instances( |
|
223 | return Component.get_instances( | |
224 | root=self.root, |
|
224 | root=self.root, | |
225 | klass='IPython.core.iplib.InteractiveShell')[0] |
|
225 | klass='IPython.core.iplib.InteractiveShell')[0] | |
226 |
|
226 | |||
227 | #------------------------------------------------------------------------- |
|
227 | #------------------------------------------------------------------------- | |
228 | # API for managing transformers |
|
228 | # API for managing transformers | |
229 | #------------------------------------------------------------------------- |
|
229 | #------------------------------------------------------------------------- | |
230 |
|
230 | |||
231 | def init_transformers(self): |
|
231 | def init_transformers(self): | |
232 | """Create the default transformers.""" |
|
232 | """Create the default transformers.""" | |
233 | self._transformers = [] |
|
233 | self._transformers = [] | |
234 | for transformer_cls in _default_transformers: |
|
234 | for transformer_cls in _default_transformers: | |
235 | transformer_cls(self, config=self.config) |
|
235 | transformer_cls(self, config=self.config) | |
236 |
|
236 | |||
237 | def sort_transformers(self): |
|
237 | def sort_transformers(self): | |
238 | """Sort the transformers by priority. |
|
238 | """Sort the transformers by priority. | |
239 |
|
239 | |||
240 | This must be called after the priority of a transformer is changed. |
|
240 | This must be called after the priority of a transformer is changed. | |
241 | The :meth:`register_transformer` method calls this automatically. |
|
241 | The :meth:`register_transformer` method calls this automatically. | |
242 | """ |
|
242 | """ | |
243 | self._transformers.sort(cmp=lambda x,y: x.priority-y.priority) |
|
243 | self._transformers.sort(cmp=lambda x,y: x.priority-y.priority) | |
244 |
|
244 | |||
245 | @property |
|
245 | @property | |
246 | def transformers(self): |
|
246 | def transformers(self): | |
247 | """Return a list of checkers, sorted by priority.""" |
|
247 | """Return a list of checkers, sorted by priority.""" | |
248 | return self._transformers |
|
248 | return self._transformers | |
249 |
|
249 | |||
250 | def register_transformer(self, transformer): |
|
250 | def register_transformer(self, transformer): | |
251 | """Register a transformer instance.""" |
|
251 | """Register a transformer instance.""" | |
252 | if transformer not in self._transformers: |
|
252 | if transformer not in self._transformers: | |
253 | self._transformers.append(transformer) |
|
253 | self._transformers.append(transformer) | |
254 | self.sort_transformers() |
|
254 | self.sort_transformers() | |
255 |
|
255 | |||
256 | def unregister_transformer(self, transformer): |
|
256 | def unregister_transformer(self, transformer): | |
257 | """Unregister a transformer instance.""" |
|
257 | """Unregister a transformer instance.""" | |
258 | if transformer in self._transformers: |
|
258 | if transformer in self._transformers: | |
259 | self._transformers.remove(transformer) |
|
259 | self._transformers.remove(transformer) | |
260 |
|
260 | |||
261 | #------------------------------------------------------------------------- |
|
261 | #------------------------------------------------------------------------- | |
262 | # API for managing checkers |
|
262 | # API for managing checkers | |
263 | #------------------------------------------------------------------------- |
|
263 | #------------------------------------------------------------------------- | |
264 |
|
264 | |||
265 | def init_checkers(self): |
|
265 | def init_checkers(self): | |
266 | """Create the default checkers.""" |
|
266 | """Create the default checkers.""" | |
267 | self._checkers = [] |
|
267 | self._checkers = [] | |
268 | for checker in _default_checkers: |
|
268 | for checker in _default_checkers: | |
269 | checker(self, config=self.config) |
|
269 | checker(self, config=self.config) | |
270 |
|
270 | |||
271 | def sort_checkers(self): |
|
271 | def sort_checkers(self): | |
272 | """Sort the checkers by priority. |
|
272 | """Sort the checkers by priority. | |
273 |
|
273 | |||
274 | This must be called after the priority of a checker is changed. |
|
274 | This must be called after the priority of a checker is changed. | |
275 | The :meth:`register_checker` method calls this automatically. |
|
275 | The :meth:`register_checker` method calls this automatically. | |
276 | """ |
|
276 | """ | |
277 | self._checkers.sort(cmp=lambda x,y: x.priority-y.priority) |
|
277 | self._checkers.sort(cmp=lambda x,y: x.priority-y.priority) | |
278 |
|
278 | |||
279 | @property |
|
279 | @property | |
280 | def checkers(self): |
|
280 | def checkers(self): | |
281 | """Return a list of checkers, sorted by priority.""" |
|
281 | """Return a list of checkers, sorted by priority.""" | |
282 | return self._checkers |
|
282 | return self._checkers | |
283 |
|
283 | |||
284 | def register_checker(self, checker): |
|
284 | def register_checker(self, checker): | |
285 | """Register a checker instance.""" |
|
285 | """Register a checker instance.""" | |
286 | if checker not in self._checkers: |
|
286 | if checker not in self._checkers: | |
287 | self._checkers.append(checker) |
|
287 | self._checkers.append(checker) | |
288 | self.sort_checkers() |
|
288 | self.sort_checkers() | |
289 |
|
289 | |||
290 | def unregister_checker(self, checker): |
|
290 | def unregister_checker(self, checker): | |
291 | """Unregister a checker instance.""" |
|
291 | """Unregister a checker instance.""" | |
292 | if checker in self._checkers: |
|
292 | if checker in self._checkers: | |
293 | self._checkers.remove(checker) |
|
293 | self._checkers.remove(checker) | |
294 |
|
294 | |||
295 | #------------------------------------------------------------------------- |
|
295 | #------------------------------------------------------------------------- | |
296 | # API for managing checkers |
|
296 | # API for managing checkers | |
297 | #------------------------------------------------------------------------- |
|
297 | #------------------------------------------------------------------------- | |
298 |
|
298 | |||
299 | def init_handlers(self): |
|
299 | def init_handlers(self): | |
300 | """Create the default handlers.""" |
|
300 | """Create the default handlers.""" | |
301 | self._handlers = {} |
|
301 | self._handlers = {} | |
302 | self._esc_handlers = {} |
|
302 | self._esc_handlers = {} | |
303 | for handler in _default_handlers: |
|
303 | for handler in _default_handlers: | |
304 | handler(self, config=self.config) |
|
304 | handler(self, config=self.config) | |
305 |
|
305 | |||
306 | @property |
|
306 | @property | |
307 | def handlers(self): |
|
307 | def handlers(self): | |
308 | """Return a dict of all the handlers.""" |
|
308 | """Return a dict of all the handlers.""" | |
309 | return self._handlers |
|
309 | return self._handlers | |
310 |
|
310 | |||
311 | def register_handler(self, name, handler, esc_strings): |
|
311 | def register_handler(self, name, handler, esc_strings): | |
312 | """Register a handler instance by name with esc_strings.""" |
|
312 | """Register a handler instance by name with esc_strings.""" | |
313 | self._handlers[name] = handler |
|
313 | self._handlers[name] = handler | |
314 | for esc_str in esc_strings: |
|
314 | for esc_str in esc_strings: | |
315 | self._esc_handlers[esc_str] = handler |
|
315 | self._esc_handlers[esc_str] = handler | |
316 |
|
316 | |||
317 | def unregister_handler(self, name, handler, esc_strings): |
|
317 | def unregister_handler(self, name, handler, esc_strings): | |
318 | """Unregister a handler instance by name with esc_strings.""" |
|
318 | """Unregister a handler instance by name with esc_strings.""" | |
319 | try: |
|
319 | try: | |
320 | del self._handlers[name] |
|
320 | del self._handlers[name] | |
321 | except KeyError: |
|
321 | except KeyError: | |
322 | pass |
|
322 | pass | |
323 | for esc_str in esc_strings: |
|
323 | for esc_str in esc_strings: | |
324 | h = self._esc_handlers.get(esc_str) |
|
324 | h = self._esc_handlers.get(esc_str) | |
325 | if h is handler: |
|
325 | if h is handler: | |
326 | del self._esc_handlers[esc_str] |
|
326 | del self._esc_handlers[esc_str] | |
327 |
|
327 | |||
328 | def get_handler_by_name(self, name): |
|
328 | def get_handler_by_name(self, name): | |
329 | """Get a handler by its name.""" |
|
329 | """Get a handler by its name.""" | |
330 | return self._handlers.get(name) |
|
330 | return self._handlers.get(name) | |
331 |
|
331 | |||
332 | def get_handler_by_esc(self, esc_str): |
|
332 | def get_handler_by_esc(self, esc_str): | |
333 | """Get a handler by its escape string.""" |
|
333 | """Get a handler by its escape string.""" | |
334 | return self._esc_handlers.get(esc_str) |
|
334 | return self._esc_handlers.get(esc_str) | |
335 |
|
335 | |||
336 | #------------------------------------------------------------------------- |
|
336 | #------------------------------------------------------------------------- | |
337 | # Main prefiltering API |
|
337 | # Main prefiltering API | |
338 | #------------------------------------------------------------------------- |
|
338 | #------------------------------------------------------------------------- | |
339 |
|
339 | |||
340 | def prefilter_line_info(self, line_info): |
|
340 | def prefilter_line_info(self, line_info): | |
341 | """Prefilter a line that has been converted to a LineInfo object. |
|
341 | """Prefilter a line that has been converted to a LineInfo object. | |
342 |
|
342 | |||
343 | This implements the checker/handler part of the prefilter pipe. |
|
343 | This implements the checker/handler part of the prefilter pipe. | |
344 | """ |
|
344 | """ | |
345 | # print "prefilter_line_info: ", line_info |
|
345 | # print "prefilter_line_info: ", line_info | |
346 | handler = self.find_handler(line_info) |
|
346 | handler = self.find_handler(line_info) | |
347 | return handler.handle(line_info) |
|
347 | return handler.handle(line_info) | |
348 |
|
348 | |||
349 | def find_handler(self, line_info): |
|
349 | def find_handler(self, line_info): | |
350 | """Find a handler for the line_info by trying checkers.""" |
|
350 | """Find a handler for the line_info by trying checkers.""" | |
351 | for checker in self.checkers: |
|
351 | for checker in self.checkers: | |
352 | if checker.enabled: |
|
352 | if checker.enabled: | |
353 | handler = checker.check(line_info) |
|
353 | handler = checker.check(line_info) | |
354 | if handler: |
|
354 | if handler: | |
355 | return handler |
|
355 | return handler | |
356 | return self.get_handler_by_name('normal') |
|
356 | return self.get_handler_by_name('normal') | |
357 |
|
357 | |||
358 | def transform_line(self, line, continue_prompt): |
|
358 | def transform_line(self, line, continue_prompt): | |
359 | """Calls the enabled transformers in order of increasing priority.""" |
|
359 | """Calls the enabled transformers in order of increasing priority.""" | |
360 | for transformer in self.transformers: |
|
360 | for transformer in self.transformers: | |
361 | if transformer.enabled: |
|
361 | if transformer.enabled: | |
362 | line = transformer.transform(line, continue_prompt) |
|
362 | line = transformer.transform(line, continue_prompt) | |
363 | return line |
|
363 | return line | |
364 |
|
364 | |||
365 | def prefilter_line(self, line, continue_prompt): |
|
365 | def prefilter_line(self, line, continue_prompt): | |
366 | """Prefilter a single input line as text. |
|
366 | """Prefilter a single input line as text. | |
367 |
|
367 | |||
368 | This method prefilters a single line of text by calling the |
|
368 | This method prefilters a single line of text by calling the | |
369 | transformers and then the checkers/handlers. |
|
369 | transformers and then the checkers/handlers. | |
370 | """ |
|
370 | """ | |
371 |
|
371 | |||
372 | # print "prefilter_line: ", line, continue_prompt |
|
372 | # print "prefilter_line: ", line, continue_prompt | |
373 | # All handlers *must* return a value, even if it's blank (''). |
|
373 | # All handlers *must* return a value, even if it's blank (''). | |
374 |
|
374 | |||
375 | # Lines are NOT logged here. Handlers should process the line as |
|
375 | # Lines are NOT logged here. Handlers should process the line as | |
376 | # needed, update the cache AND log it (so that the input cache array |
|
376 | # needed, update the cache AND log it (so that the input cache array | |
377 | # stays synced). |
|
377 | # stays synced). | |
378 |
|
378 | |||
379 | # save the line away in case we crash, so the post-mortem handler can |
|
379 | # save the line away in case we crash, so the post-mortem handler can | |
380 | # record it |
|
380 | # record it | |
381 | self.shell._last_input_line = line |
|
381 | self.shell._last_input_line = line | |
382 |
|
382 | |||
383 | if not line: |
|
383 | if not line: | |
384 | # Return immediately on purely empty lines, so that if the user |
|
384 | # Return immediately on purely empty lines, so that if the user | |
385 | # previously typed some whitespace that started a continuation |
|
385 | # previously typed some whitespace that started a continuation | |
386 | # prompt, he can break out of that loop with just an empty line. |
|
386 | # prompt, he can break out of that loop with just an empty line. | |
387 | # This is how the default python prompt works. |
|
387 | # This is how the default python prompt works. | |
388 |
|
388 | |||
389 | # Only return if the accumulated input buffer was just whitespace! |
|
389 | # Only return if the accumulated input buffer was just whitespace! | |
390 | if ''.join(self.shell.buffer).isspace(): |
|
390 | if ''.join(self.shell.buffer).isspace(): | |
391 | self.shell.buffer[:] = [] |
|
391 | self.shell.buffer[:] = [] | |
392 | return '' |
|
392 | return '' | |
393 |
|
393 | |||
394 | # At this point, we invoke our transformers. |
|
394 | # At this point, we invoke our transformers. | |
395 | if not continue_prompt or (continue_prompt and self.multi_line_specials): |
|
395 | if not continue_prompt or (continue_prompt and self.multi_line_specials): | |
396 | line = self.transform_line(line, continue_prompt) |
|
396 | line = self.transform_line(line, continue_prompt) | |
397 |
|
397 | |||
398 | # Now we compute line_info for the checkers and handlers |
|
398 | # Now we compute line_info for the checkers and handlers | |
399 | line_info = LineInfo(line, continue_prompt) |
|
399 | line_info = LineInfo(line, continue_prompt) | |
400 |
|
400 | |||
401 | # the input history needs to track even empty lines |
|
401 | # the input history needs to track even empty lines | |
402 | stripped = line.strip() |
|
402 | stripped = line.strip() | |
403 |
|
403 | |||
404 | normal_handler = self.get_handler_by_name('normal') |
|
404 | normal_handler = self.get_handler_by_name('normal') | |
405 | if not stripped: |
|
405 | if not stripped: | |
406 | if not continue_prompt: |
|
406 | if not continue_prompt: | |
407 | self.shell.outputcache.prompt_count -= 1 |
|
407 | self.shell.outputcache.prompt_count -= 1 | |
408 |
|
408 | |||
409 | return normal_handler.handle(line_info) |
|
409 | return normal_handler.handle(line_info) | |
410 |
|
410 | |||
411 | # special handlers are only allowed for single line statements |
|
411 | # special handlers are only allowed for single line statements | |
412 | if continue_prompt and not self.multi_line_specials: |
|
412 | if continue_prompt and not self.multi_line_specials: | |
413 | return normal_handler.handle(line_info) |
|
413 | return normal_handler.handle(line_info) | |
414 |
|
414 | |||
415 | prefiltered = self.prefilter_line_info(line_info) |
|
415 | prefiltered = self.prefilter_line_info(line_info) | |
416 | # print "prefiltered line: %r" % prefiltered |
|
416 | # print "prefiltered line: %r" % prefiltered | |
417 | return prefiltered |
|
417 | return prefiltered | |
418 |
|
418 | |||
419 | def prefilter_lines(self, lines, continue_prompt): |
|
419 | def prefilter_lines(self, lines, continue_prompt): | |
420 | """Prefilter multiple input lines of text. |
|
420 | """Prefilter multiple input lines of text. | |
421 |
|
421 | |||
422 | This is the main entry point for prefiltering multiple lines of |
|
422 | This is the main entry point for prefiltering multiple lines of | |
423 | input. This simply calls :meth:`prefilter_line` for each line of |
|
423 | input. This simply calls :meth:`prefilter_line` for each line of | |
424 | input. |
|
424 | input. | |
425 |
|
425 | |||
426 | This covers cases where there are multiple lines in the user entry, |
|
426 | This covers cases where there are multiple lines in the user entry, | |
427 | which is the case when the user goes back to a multiline history |
|
427 | which is the case when the user goes back to a multiline history | |
428 | entry and presses enter. |
|
428 | entry and presses enter. | |
429 | """ |
|
429 | """ | |
430 | out = [] |
|
430 | out = [] | |
431 | for line in lines.rstrip('\n').split('\n'): |
|
431 | for line in lines.rstrip('\n').split('\n'): | |
432 | out.append(self.prefilter_line(line, continue_prompt)) |
|
432 | out.append(self.prefilter_line(line, continue_prompt)) | |
433 | return '\n'.join(out) |
|
433 | return '\n'.join(out) | |
434 |
|
434 | |||
435 |
|
435 | |||
436 | #----------------------------------------------------------------------------- |
|
436 | #----------------------------------------------------------------------------- | |
437 | # Prefilter transformers |
|
437 | # Prefilter transformers | |
438 | #----------------------------------------------------------------------------- |
|
438 | #----------------------------------------------------------------------------- | |
439 |
|
439 | |||
440 |
|
440 | |||
441 | class PrefilterTransformer(Component): |
|
441 | class PrefilterTransformer(Component): | |
442 | """Transform a line of user input.""" |
|
442 | """Transform a line of user input.""" | |
443 |
|
443 | |||
444 | priority = Int(100, config=True) |
|
444 | priority = Int(100, config=True) | |
445 | shell = Any |
|
445 | shell = Any | |
446 | prefilter_manager = Any |
|
446 | prefilter_manager = Any | |
447 | enabled = Bool(True, config=True) |
|
447 | enabled = Bool(True, config=True) | |
448 |
|
448 | |||
449 | def __init__(self, parent, config=None): |
|
449 | def __init__(self, parent, config=None): | |
450 | super(PrefilterTransformer, self).__init__(parent, config=config) |
|
450 | super(PrefilterTransformer, self).__init__(parent, config=config) | |
451 | self.prefilter_manager.register_transformer(self) |
|
451 | self.prefilter_manager.register_transformer(self) | |
452 |
|
452 | |||
453 | @auto_attr |
|
453 | @auto_attr | |
454 | def shell(self): |
|
454 | def shell(self): | |
455 | return Component.get_instances( |
|
455 | return Component.get_instances( | |
456 | root=self.root, |
|
456 | root=self.root, | |
457 | klass='IPython.core.iplib.InteractiveShell')[0] |
|
457 | klass='IPython.core.iplib.InteractiveShell')[0] | |
458 |
|
458 | |||
459 | @auto_attr |
|
459 | @auto_attr | |
460 | def prefilter_manager(self): |
|
460 | def prefilter_manager(self): | |
461 | return PrefilterManager.get_instances(root=self.root)[0] |
|
461 | return PrefilterManager.get_instances(root=self.root)[0] | |
462 |
|
462 | |||
463 | def transform(self, line, continue_prompt): |
|
463 | def transform(self, line, continue_prompt): | |
464 | """Transform a line, returning the new one.""" |
|
464 | """Transform a line, returning the new one.""" | |
465 | return None |
|
465 | return None | |
466 |
|
466 | |||
467 | def __repr__(self): |
|
467 | def __repr__(self): | |
468 | return "<%s(priority=%r, enabled=%r)>" % ( |
|
468 | return "<%s(priority=%r, enabled=%r)>" % ( | |
469 | self.__class__.__name__, self.priority, self.enabled) |
|
469 | self.__class__.__name__, self.priority, self.enabled) | |
470 |
|
470 | |||
471 |
|
471 | |||
472 | _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' |
|
472 | _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' | |
473 | r'\s*=\s*!(?P<cmd>.*)') |
|
473 | r'\s*=\s*!(?P<cmd>.*)') | |
474 |
|
474 | |||
475 |
|
475 | |||
476 | class AssignSystemTransformer(PrefilterTransformer): |
|
476 | class AssignSystemTransformer(PrefilterTransformer): | |
477 | """Handle the `files = !ls` syntax.""" |
|
477 | """Handle the `files = !ls` syntax.""" | |
478 |
|
478 | |||
479 | priority = Int(100, config=True) |
|
479 | priority = Int(100, config=True) | |
480 |
|
480 | |||
481 | def transform(self, line, continue_prompt): |
|
481 | def transform(self, line, continue_prompt): | |
482 | m = _assign_system_re.match(line) |
|
482 | m = _assign_system_re.match(line) | |
483 | if m is not None: |
|
483 | if m is not None: | |
484 | cmd = m.group('cmd') |
|
484 | cmd = m.group('cmd') | |
485 | lhs = m.group('lhs') |
|
485 | lhs = m.group('lhs') | |
486 | expr = make_quoted_expr("sc -l =%s" % cmd) |
|
486 | expr = make_quoted_expr("sc -l =%s" % cmd) | |
487 | new_line = '%s = get_ipython().magic(%s)' % (lhs, expr) |
|
487 | new_line = '%s = get_ipython().magic(%s)' % (lhs, expr) | |
488 | return new_line |
|
488 | return new_line | |
489 | return line |
|
489 | return line | |
490 |
|
490 | |||
491 |
|
491 | |||
492 | _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' |
|
492 | _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' | |
493 | r'\s*=\s*%(?P<cmd>.*)') |
|
493 | r'\s*=\s*%(?P<cmd>.*)') | |
494 |
|
494 | |||
495 | class AssignMagicTransformer(PrefilterTransformer): |
|
495 | class AssignMagicTransformer(PrefilterTransformer): | |
496 | """Handle the `a = %who` syntax.""" |
|
496 | """Handle the `a = %who` syntax.""" | |
497 |
|
497 | |||
498 | priority = Int(200, config=True) |
|
498 | priority = Int(200, config=True) | |
499 |
|
499 | |||
500 | def transform(self, line, continue_prompt): |
|
500 | def transform(self, line, continue_prompt): | |
501 | m = _assign_magic_re.match(line) |
|
501 | m = _assign_magic_re.match(line) | |
502 | if m is not None: |
|
502 | if m is not None: | |
503 | cmd = m.group('cmd') |
|
503 | cmd = m.group('cmd') | |
504 | lhs = m.group('lhs') |
|
504 | lhs = m.group('lhs') | |
505 | expr = make_quoted_expr(cmd) |
|
505 | expr = make_quoted_expr(cmd) | |
506 | new_line = '%s = get_ipython().magic(%s)' % (lhs, expr) |
|
506 | new_line = '%s = get_ipython().magic(%s)' % (lhs, expr) | |
507 | return new_line |
|
507 | return new_line | |
508 | return line |
|
508 | return line | |
509 |
|
509 | |||
510 |
|
510 | |||
511 | #----------------------------------------------------------------------------- |
|
511 | #----------------------------------------------------------------------------- | |
512 | # Prefilter checkers |
|
512 | # Prefilter checkers | |
513 | #----------------------------------------------------------------------------- |
|
513 | #----------------------------------------------------------------------------- | |
514 |
|
514 | |||
515 |
|
515 | |||
516 | class PrefilterChecker(Component): |
|
516 | class PrefilterChecker(Component): | |
517 | """Inspect an input line and return a handler for that line.""" |
|
517 | """Inspect an input line and return a handler for that line.""" | |
518 |
|
518 | |||
519 | priority = Int(100, config=True) |
|
519 | priority = Int(100, config=True) | |
520 | shell = Any |
|
520 | shell = Any | |
521 | prefilter_manager = Any |
|
521 | prefilter_manager = Any | |
522 | enabled = Bool(True, config=True) |
|
522 | enabled = Bool(True, config=True) | |
523 |
|
523 | |||
524 | def __init__(self, parent, config=None): |
|
524 | def __init__(self, parent, config=None): | |
525 | super(PrefilterChecker, self).__init__(parent, config=config) |
|
525 | super(PrefilterChecker, self).__init__(parent, config=config) | |
526 | self.prefilter_manager.register_checker(self) |
|
526 | self.prefilter_manager.register_checker(self) | |
527 |
|
527 | |||
528 | @auto_attr |
|
528 | @auto_attr | |
529 | def shell(self): |
|
529 | def shell(self): | |
530 | return Component.get_instances( |
|
530 | return Component.get_instances( | |
531 | root=self.root, |
|
531 | root=self.root, | |
532 | klass='IPython.core.iplib.InteractiveShell')[0] |
|
532 | klass='IPython.core.iplib.InteractiveShell')[0] | |
533 |
|
533 | |||
534 | @auto_attr |
|
534 | @auto_attr | |
535 | def prefilter_manager(self): |
|
535 | def prefilter_manager(self): | |
536 | return PrefilterManager.get_instances(root=self.root)[0] |
|
536 | return PrefilterManager.get_instances(root=self.root)[0] | |
537 |
|
537 | |||
538 | def check(self, line_info): |
|
538 | def check(self, line_info): | |
539 | """Inspect line_info and return a handler instance or None.""" |
|
539 | """Inspect line_info and return a handler instance or None.""" | |
540 | return None |
|
540 | return None | |
541 |
|
541 | |||
542 | def __repr__(self): |
|
542 | def __repr__(self): | |
543 | return "<%s(priority=%r, enabled=%r)>" % ( |
|
543 | return "<%s(priority=%r, enabled=%r)>" % ( | |
544 | self.__class__.__name__, self.priority, self.enabled) |
|
544 | self.__class__.__name__, self.priority, self.enabled) | |
545 |
|
545 | |||
546 |
|
546 | |||
547 | class EmacsChecker(PrefilterChecker): |
|
547 | class EmacsChecker(PrefilterChecker): | |
548 |
|
548 | |||
549 | priority = Int(100, config=True) |
|
549 | priority = Int(100, config=True) | |
550 | enabled = Bool(False, config=True) |
|
550 | enabled = Bool(False, config=True) | |
551 |
|
551 | |||
552 | def check(self, line_info): |
|
552 | def check(self, line_info): | |
553 | "Emacs ipython-mode tags certain input lines." |
|
553 | "Emacs ipython-mode tags certain input lines." | |
554 | if line_info.line.endswith('# PYTHON-MODE'): |
|
554 | if line_info.line.endswith('# PYTHON-MODE'): | |
555 | return self.prefilter_manager.get_handler_by_name('emacs') |
|
555 | return self.prefilter_manager.get_handler_by_name('emacs') | |
556 | else: |
|
556 | else: | |
557 | return None |
|
557 | return None | |
558 |
|
558 | |||
559 |
|
559 | |||
560 | class ShellEscapeChecker(PrefilterChecker): |
|
560 | class ShellEscapeChecker(PrefilterChecker): | |
561 |
|
561 | |||
562 | priority = Int(200, config=True) |
|
562 | priority = Int(200, config=True) | |
563 |
|
563 | |||
564 | def check(self, line_info): |
|
564 | def check(self, line_info): | |
565 | if line_info.line.lstrip().startswith(ESC_SHELL): |
|
565 | if line_info.line.lstrip().startswith(ESC_SHELL): | |
566 | return self.prefilter_manager.get_handler_by_name('shell') |
|
566 | return self.prefilter_manager.get_handler_by_name('shell') | |
567 |
|
567 | |||
568 |
|
568 | |||
569 | class IPyAutocallChecker(PrefilterChecker): |
|
569 | class IPyAutocallChecker(PrefilterChecker): | |
570 |
|
570 | |||
571 | priority = Int(300, config=True) |
|
571 | priority = Int(300, config=True) | |
572 |
|
572 | |||
573 | def check(self, line_info): |
|
573 | def check(self, line_info): | |
574 | "Instances of IPyAutocall in user_ns get autocalled immediately" |
|
574 | "Instances of IPyAutocall in user_ns get autocalled immediately" | |
575 | obj = self.shell.user_ns.get(line_info.ifun, None) |
|
575 | obj = self.shell.user_ns.get(line_info.ifun, None) | |
576 | if isinstance(obj, IPyAutocall): |
|
576 | if isinstance(obj, IPyAutocall): | |
577 | obj.set_ip(self.shell) |
|
577 | obj.set_ip(self.shell) | |
578 | return self.prefilter_manager.get_handler_by_name('auto') |
|
578 | return self.prefilter_manager.get_handler_by_name('auto') | |
579 | else: |
|
579 | else: | |
580 | return None |
|
580 | return None | |
581 |
|
581 | |||
582 |
|
582 | |||
583 | class MultiLineMagicChecker(PrefilterChecker): |
|
583 | class MultiLineMagicChecker(PrefilterChecker): | |
584 |
|
584 | |||
585 | priority = Int(400, config=True) |
|
585 | priority = Int(400, config=True) | |
586 |
|
586 | |||
587 | def check(self, line_info): |
|
587 | def check(self, line_info): | |
588 | "Allow ! and !! in multi-line statements if multi_line_specials is on" |
|
588 | "Allow ! and !! in multi-line statements if multi_line_specials is on" | |
589 | # Note that this one of the only places we check the first character of |
|
589 | # Note that this one of the only places we check the first character of | |
590 | # ifun and *not* the pre_char. Also note that the below test matches |
|
590 | # ifun and *not* the pre_char. Also note that the below test matches | |
591 | # both ! and !!. |
|
591 | # both ! and !!. | |
592 | if line_info.continue_prompt \ |
|
592 | if line_info.continue_prompt \ | |
593 | and self.prefilter_manager.multi_line_specials: |
|
593 | and self.prefilter_manager.multi_line_specials: | |
594 | if line_info.ifun.startswith(ESC_MAGIC): |
|
594 | if line_info.ifun.startswith(ESC_MAGIC): | |
595 | return self.prefilter_manager.get_handler_by_name('magic') |
|
595 | return self.prefilter_manager.get_handler_by_name('magic') | |
596 | else: |
|
596 | else: | |
597 | return None |
|
597 | return None | |
598 |
|
598 | |||
599 |
|
599 | |||
600 | class EscCharsChecker(PrefilterChecker): |
|
600 | class EscCharsChecker(PrefilterChecker): | |
601 |
|
601 | |||
602 | priority = Int(500, config=True) |
|
602 | priority = Int(500, config=True) | |
603 |
|
603 | |||
604 | def check(self, line_info): |
|
604 | def check(self, line_info): | |
605 | """Check for escape character and return either a handler to handle it, |
|
605 | """Check for escape character and return either a handler to handle it, | |
606 | or None if there is no escape char.""" |
|
606 | or None if there is no escape char.""" | |
607 | if line_info.line[-1] == ESC_HELP \ |
|
607 | if line_info.line[-1] == ESC_HELP \ | |
608 | and line_info.pre_char != ESC_SHELL \ |
|
608 | and line_info.pre_char != ESC_SHELL \ | |
609 | and line_info.pre_char != ESC_SH_CAP: |
|
609 | and line_info.pre_char != ESC_SH_CAP: | |
610 | # the ? can be at the end, but *not* for either kind of shell escape, |
|
610 | # the ? can be at the end, but *not* for either kind of shell escape, | |
611 | # because a ? can be a vaild final char in a shell cmd |
|
611 | # because a ? can be a vaild final char in a shell cmd | |
612 | return self.prefilter_manager.get_handler_by_name('help') |
|
612 | return self.prefilter_manager.get_handler_by_name('help') | |
613 | else: |
|
613 | else: | |
614 | # This returns None like it should if no handler exists |
|
614 | # This returns None like it should if no handler exists | |
615 | return self.prefilter_manager.get_handler_by_esc(line_info.pre_char) |
|
615 | return self.prefilter_manager.get_handler_by_esc(line_info.pre_char) | |
616 |
|
616 | |||
617 |
|
617 | |||
618 | class AssignmentChecker(PrefilterChecker): |
|
618 | class AssignmentChecker(PrefilterChecker): | |
619 |
|
619 | |||
620 | priority = Int(600, config=True) |
|
620 | priority = Int(600, config=True) | |
621 |
|
621 | |||
622 | def check(self, line_info): |
|
622 | def check(self, line_info): | |
623 | """Check to see if user is assigning to a var for the first time, in |
|
623 | """Check to see if user is assigning to a var for the first time, in | |
624 | which case we want to avoid any sort of automagic / autocall games. |
|
624 | which case we want to avoid any sort of automagic / autocall games. | |
625 |
|
625 | |||
626 | This allows users to assign to either alias or magic names true python |
|
626 | This allows users to assign to either alias or magic names true python | |
627 | variables (the magic/alias systems always take second seat to true |
|
627 | variables (the magic/alias systems always take second seat to true | |
628 | python code). E.g. ls='hi', or ls,that=1,2""" |
|
628 | python code). E.g. ls='hi', or ls,that=1,2""" | |
629 | if line_info.the_rest: |
|
629 | if line_info.the_rest: | |
630 | if line_info.the_rest[0] in '=,': |
|
630 | if line_info.the_rest[0] in '=,': | |
631 | return self.prefilter_manager.get_handler_by_name('normal') |
|
631 | return self.prefilter_manager.get_handler_by_name('normal') | |
632 | else: |
|
632 | else: | |
633 | return None |
|
633 | return None | |
634 |
|
634 | |||
635 |
|
635 | |||
636 | class AutoMagicChecker(PrefilterChecker): |
|
636 | class AutoMagicChecker(PrefilterChecker): | |
637 |
|
637 | |||
638 | priority = Int(700, config=True) |
|
638 | priority = Int(700, config=True) | |
639 |
|
639 | |||
640 | def check(self, line_info): |
|
640 | def check(self, line_info): | |
641 | """If the ifun is magic, and automagic is on, run it. Note: normal, |
|
641 | """If the ifun is magic, and automagic is on, run it. Note: normal, | |
642 | non-auto magic would already have been triggered via '%' in |
|
642 | non-auto magic would already have been triggered via '%' in | |
643 | check_esc_chars. This just checks for automagic. Also, before |
|
643 | check_esc_chars. This just checks for automagic. Also, before | |
644 | triggering the magic handler, make sure that there is nothing in the |
|
644 | triggering the magic handler, make sure that there is nothing in the | |
645 | user namespace which could shadow it.""" |
|
645 | user namespace which could shadow it.""" | |
646 | if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun): |
|
646 | if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun): | |
647 | return None |
|
647 | return None | |
648 |
|
648 | |||
649 | # We have a likely magic method. Make sure we should actually call it. |
|
649 | # We have a likely magic method. Make sure we should actually call it. | |
650 | if line_info.continue_prompt and not self.shell.multi_line_specials: |
|
650 | if line_info.continue_prompt and not self.shell.multi_line_specials: | |
651 | return None |
|
651 | return None | |
652 |
|
652 | |||
653 | head = line_info.ifun.split('.',1)[0] |
|
653 | head = line_info.ifun.split('.',1)[0] | |
654 | if is_shadowed(head, self.shell): |
|
654 | if is_shadowed(head, self.shell): | |
655 | return None |
|
655 | return None | |
656 |
|
656 | |||
657 | return self.prefilter_manager.get_handler_by_name('magic') |
|
657 | return self.prefilter_manager.get_handler_by_name('magic') | |
658 |
|
658 | |||
659 |
|
659 | |||
660 | class AliasChecker(PrefilterChecker): |
|
660 | class AliasChecker(PrefilterChecker): | |
661 |
|
661 | |||
662 | priority = Int(800, config=True) |
|
662 | priority = Int(800, config=True) | |
663 |
|
663 | |||
664 | @auto_attr |
|
664 | @auto_attr | |
665 | def alias_manager(self): |
|
665 | def alias_manager(self): | |
666 | return AliasManager.get_instances(root=self.root)[0] |
|
666 | return AliasManager.get_instances(root=self.root)[0] | |
667 |
|
667 | |||
668 | def check(self, line_info): |
|
668 | def check(self, line_info): | |
669 | "Check if the initital identifier on the line is an alias." |
|
669 | "Check if the initital identifier on the line is an alias." | |
670 | # Note: aliases can not contain '.' |
|
670 | # Note: aliases can not contain '.' | |
671 | head = line_info.ifun.split('.',1)[0] |
|
671 | head = line_info.ifun.split('.',1)[0] | |
672 | if line_info.ifun not in self.alias_manager \ |
|
672 | if line_info.ifun not in self.alias_manager \ | |
673 | or head not in self.alias_manager \ |
|
673 | or head not in self.alias_manager \ | |
674 | or is_shadowed(head, self.shell): |
|
674 | or is_shadowed(head, self.shell): | |
675 | return None |
|
675 | return None | |
676 |
|
676 | |||
677 | return self.prefilter_manager.get_handler_by_name('alias') |
|
677 | return self.prefilter_manager.get_handler_by_name('alias') | |
678 |
|
678 | |||
679 |
|
679 | |||
680 | class PythonOpsChecker(PrefilterChecker): |
|
680 | class PythonOpsChecker(PrefilterChecker): | |
681 |
|
681 | |||
682 | priority = Int(900, config=True) |
|
682 | priority = Int(900, config=True) | |
683 |
|
683 | |||
684 | def check(self, line_info): |
|
684 | def check(self, line_info): | |
685 | """If the 'rest' of the line begins with a function call or pretty much |
|
685 | """If the 'rest' of the line begins with a function call or pretty much | |
686 | any python operator, we should simply execute the line (regardless of |
|
686 | any python operator, we should simply execute the line (regardless of | |
687 | whether or not there's a possible autocall expansion). This avoids |
|
687 | whether or not there's a possible autocall expansion). This avoids | |
688 | spurious (and very confusing) geattr() accesses.""" |
|
688 | spurious (and very confusing) geattr() accesses.""" | |
689 | if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|': |
|
689 | if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|': | |
690 | return self.prefilter_manager.get_handler_by_name('normal') |
|
690 | return self.prefilter_manager.get_handler_by_name('normal') | |
691 | else: |
|
691 | else: | |
692 | return None |
|
692 | return None | |
693 |
|
693 | |||
694 |
|
694 | |||
695 | class AutocallChecker(PrefilterChecker): |
|
695 | class AutocallChecker(PrefilterChecker): | |
696 |
|
696 | |||
697 | priority = Int(1000, config=True) |
|
697 | priority = Int(1000, config=True) | |
698 |
|
698 | |||
699 | def check(self, line_info): |
|
699 | def check(self, line_info): | |
700 | "Check if the initial word/function is callable and autocall is on." |
|
700 | "Check if the initial word/function is callable and autocall is on." | |
701 | if not self.shell.autocall: |
|
701 | if not self.shell.autocall: | |
702 | return None |
|
702 | return None | |
703 |
|
703 | |||
704 | oinfo = line_info.ofind(self.shell) # This can mutate state via getattr |
|
704 | oinfo = line_info.ofind(self.shell) # This can mutate state via getattr | |
705 | if not oinfo['found']: |
|
705 | if not oinfo['found']: | |
706 | return None |
|
706 | return None | |
707 |
|
707 | |||
708 | if callable(oinfo['obj']) \ |
|
708 | if callable(oinfo['obj']) \ | |
709 | and (not re_exclude_auto.match(line_info.the_rest)) \ |
|
709 | and (not re_exclude_auto.match(line_info.the_rest)) \ | |
710 | and re_fun_name.match(line_info.ifun): |
|
710 | and re_fun_name.match(line_info.ifun): | |
711 | return self.prefilter_manager.get_handler_by_name('auto') |
|
711 | return self.prefilter_manager.get_handler_by_name('auto') | |
712 | else: |
|
712 | else: | |
713 | return None |
|
713 | return None | |
714 |
|
714 | |||
715 |
|
715 | |||
716 | #----------------------------------------------------------------------------- |
|
716 | #----------------------------------------------------------------------------- | |
717 | # Prefilter handlers |
|
717 | # Prefilter handlers | |
718 | #----------------------------------------------------------------------------- |
|
718 | #----------------------------------------------------------------------------- | |
719 |
|
719 | |||
720 |
|
720 | |||
721 | class PrefilterHandler(Component): |
|
721 | class PrefilterHandler(Component): | |
722 |
|
722 | |||
723 | handler_name = Str('normal') |
|
723 | handler_name = Str('normal') | |
724 | esc_strings = List([]) |
|
724 | esc_strings = List([]) | |
725 | shell = Any |
|
725 | shell = Any | |
726 | prefilter_manager = Any |
|
726 | prefilter_manager = Any | |
727 |
|
727 | |||
728 | def __init__(self, parent, config=None): |
|
728 | def __init__(self, parent, config=None): | |
729 | super(PrefilterHandler, self).__init__(parent, config=config) |
|
729 | super(PrefilterHandler, self).__init__(parent, config=config) | |
730 | self.prefilter_manager.register_handler( |
|
730 | self.prefilter_manager.register_handler( | |
731 | self.handler_name, |
|
731 | self.handler_name, | |
732 | self, |
|
732 | self, | |
733 | self.esc_strings |
|
733 | self.esc_strings | |
734 | ) |
|
734 | ) | |
735 |
|
735 | |||
736 | @auto_attr |
|
736 | @auto_attr | |
737 | def shell(self): |
|
737 | def shell(self): | |
738 | return Component.get_instances( |
|
738 | return Component.get_instances( | |
739 | root=self.root, |
|
739 | root=self.root, | |
740 | klass='IPython.core.iplib.InteractiveShell')[0] |
|
740 | klass='IPython.core.iplib.InteractiveShell')[0] | |
741 |
|
741 | |||
742 | @auto_attr |
|
742 | @auto_attr | |
743 | def prefilter_manager(self): |
|
743 | def prefilter_manager(self): | |
744 | return PrefilterManager.get_instances(root=self.root)[0] |
|
744 | return PrefilterManager.get_instances(root=self.root)[0] | |
745 |
|
745 | |||
746 | def handle(self, line_info): |
|
746 | def handle(self, line_info): | |
747 | # print "normal: ", line_info |
|
747 | # print "normal: ", line_info | |
748 | """Handle normal input lines. Use as a template for handlers.""" |
|
748 | """Handle normal input lines. Use as a template for handlers.""" | |
749 |
|
749 | |||
750 | # With autoindent on, we need some way to exit the input loop, and I |
|
750 | # With autoindent on, we need some way to exit the input loop, and I | |
751 | # don't want to force the user to have to backspace all the way to |
|
751 | # don't want to force the user to have to backspace all the way to | |
752 | # clear the line. The rule will be in this case, that either two |
|
752 | # clear the line. The rule will be in this case, that either two | |
753 | # lines of pure whitespace in a row, or a line of pure whitespace but |
|
753 | # lines of pure whitespace in a row, or a line of pure whitespace but | |
754 | # of a size different to the indent level, will exit the input loop. |
|
754 | # of a size different to the indent level, will exit the input loop. | |
755 | line = line_info.line |
|
755 | line = line_info.line | |
756 | continue_prompt = line_info.continue_prompt |
|
756 | continue_prompt = line_info.continue_prompt | |
757 |
|
757 | |||
758 | if (continue_prompt and self.shell.autoindent and line.isspace() and |
|
758 | if (continue_prompt and self.shell.autoindent and line.isspace() and | |
759 | (0 < abs(len(line) - self.shell.indent_current_nsp) <= 2 or |
|
759 | (0 < abs(len(line) - self.shell.indent_current_nsp) <= 2 or | |
760 | (self.shell.buffer[-1]).isspace() )): |
|
760 | (self.shell.buffer[-1]).isspace() )): | |
761 | line = '' |
|
761 | line = '' | |
762 |
|
762 | |||
763 | self.shell.log(line, line, continue_prompt) |
|
763 | self.shell.log(line, line, continue_prompt) | |
764 | return line |
|
764 | return line | |
765 |
|
765 | |||
766 | def __str__(self): |
|
766 | def __str__(self): | |
767 | return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name) |
|
767 | return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name) | |
768 |
|
768 | |||
769 |
|
769 | |||
770 | class AliasHandler(PrefilterHandler): |
|
770 | class AliasHandler(PrefilterHandler): | |
771 |
|
771 | |||
772 | handler_name = Str('alias') |
|
772 | handler_name = Str('alias') | |
773 |
|
773 | |||
774 | @auto_attr |
|
774 | @auto_attr | |
775 | def alias_manager(self): |
|
775 | def alias_manager(self): | |
776 | return AliasManager.get_instances(root=self.root)[0] |
|
776 | return AliasManager.get_instances(root=self.root)[0] | |
777 |
|
777 | |||
778 | def handle(self, line_info): |
|
778 | def handle(self, line_info): | |
779 | """Handle alias input lines. """ |
|
779 | """Handle alias input lines. """ | |
780 | transformed = self.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest) |
|
780 | transformed = self.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest) | |
781 | # pre is needed, because it carries the leading whitespace. Otherwise |
|
781 | # pre is needed, because it carries the leading whitespace. Otherwise | |
782 | # aliases won't work in indented sections. |
|
782 | # aliases won't work in indented sections. | |
783 | line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace, |
|
783 | line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace, | |
784 | make_quoted_expr(transformed)) |
|
784 | make_quoted_expr(transformed)) | |
785 |
|
785 | |||
786 | self.shell.log(line_info.line, line_out, line_info.continue_prompt) |
|
786 | self.shell.log(line_info.line, line_out, line_info.continue_prompt) | |
787 | return line_out |
|
787 | return line_out | |
788 |
|
788 | |||
789 |
|
789 | |||
790 | class ShellEscapeHandler(PrefilterHandler): |
|
790 | class ShellEscapeHandler(PrefilterHandler): | |
791 |
|
791 | |||
792 | handler_name = Str('shell') |
|
792 | handler_name = Str('shell') | |
793 | esc_strings = List([ESC_SHELL, ESC_SH_CAP]) |
|
793 | esc_strings = List([ESC_SHELL, ESC_SH_CAP]) | |
794 |
|
794 | |||
795 | def handle(self, line_info): |
|
795 | def handle(self, line_info): | |
796 | """Execute the line in a shell, empty return value""" |
|
796 | """Execute the line in a shell, empty return value""" | |
797 | magic_handler = self.prefilter_manager.get_handler_by_name('magic') |
|
797 | magic_handler = self.prefilter_manager.get_handler_by_name('magic') | |
798 |
|
798 | |||
799 | line = line_info.line |
|
799 | line = line_info.line | |
800 | if line.lstrip().startswith(ESC_SH_CAP): |
|
800 | if line.lstrip().startswith(ESC_SH_CAP): | |
801 | # rewrite LineInfo's line, ifun and the_rest to properly hold the |
|
801 | # rewrite LineInfo's line, ifun and the_rest to properly hold the | |
802 | # call to %sx and the actual command to be executed, so |
|
802 | # call to %sx and the actual command to be executed, so | |
803 | # handle_magic can work correctly. Note that this works even if |
|
803 | # handle_magic can work correctly. Note that this works even if | |
804 | # the line is indented, so it handles multi_line_specials |
|
804 | # the line is indented, so it handles multi_line_specials | |
805 | # properly. |
|
805 | # properly. | |
806 | new_rest = line.lstrip()[2:] |
|
806 | new_rest = line.lstrip()[2:] | |
807 | line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest) |
|
807 | line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest) | |
808 | line_info.ifun = 'sx' |
|
808 | line_info.ifun = 'sx' | |
809 | line_info.the_rest = new_rest |
|
809 | line_info.the_rest = new_rest | |
810 | return magic_handler.handle(line_info) |
|
810 | return magic_handler.handle(line_info) | |
811 | else: |
|
811 | else: | |
812 | cmd = line.lstrip().lstrip(ESC_SHELL) |
|
812 | cmd = line.lstrip().lstrip(ESC_SHELL) | |
813 | line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace, |
|
813 | line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace, | |
814 | make_quoted_expr(cmd)) |
|
814 | make_quoted_expr(cmd)) | |
815 | # update cache/log and return |
|
815 | # update cache/log and return | |
816 | self.shell.log(line, line_out, line_info.continue_prompt) |
|
816 | self.shell.log(line, line_out, line_info.continue_prompt) | |
817 | return line_out |
|
817 | return line_out | |
818 |
|
818 | |||
819 |
|
819 | |||
820 | class MagicHandler(PrefilterHandler): |
|
820 | class MagicHandler(PrefilterHandler): | |
821 |
|
821 | |||
822 | handler_name = Str('magic') |
|
822 | handler_name = Str('magic') | |
823 | esc_strings = List([ESC_MAGIC]) |
|
823 | esc_strings = List([ESC_MAGIC]) | |
824 |
|
824 | |||
825 | def handle(self, line_info): |
|
825 | def handle(self, line_info): | |
826 | """Execute magic functions.""" |
|
826 | """Execute magic functions.""" | |
827 | ifun = line_info.ifun |
|
827 | ifun = line_info.ifun | |
828 | the_rest = line_info.the_rest |
|
828 | the_rest = line_info.the_rest | |
829 | cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace, |
|
829 | cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace, | |
830 | make_quoted_expr(ifun + " " + the_rest)) |
|
830 | make_quoted_expr(ifun + " " + the_rest)) | |
831 | self.shell.log(line_info.line, cmd, line_info.continue_prompt) |
|
831 | self.shell.log(line_info.line, cmd, line_info.continue_prompt) | |
832 | return cmd |
|
832 | return cmd | |
833 |
|
833 | |||
834 |
|
834 | |||
835 | class AutoHandler(PrefilterHandler): |
|
835 | class AutoHandler(PrefilterHandler): | |
836 |
|
836 | |||
837 | handler_name = Str('auto') |
|
837 | handler_name = Str('auto') | |
838 | esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2]) |
|
838 | esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2]) | |
839 |
|
839 | |||
840 | def handle(self, line_info): |
|
840 | def handle(self, line_info): | |
841 | """Hande lines which can be auto-executed, quoting if requested.""" |
|
841 | """Hande lines which can be auto-executed, quoting if requested.""" | |
842 | line = line_info.line |
|
842 | line = line_info.line | |
843 | ifun = line_info.ifun |
|
843 | ifun = line_info.ifun | |
844 | the_rest = line_info.the_rest |
|
844 | the_rest = line_info.the_rest | |
845 | pre = line_info.pre |
|
845 | pre = line_info.pre | |
846 | continue_prompt = line_info.continue_prompt |
|
846 | continue_prompt = line_info.continue_prompt | |
847 | obj = line_info.ofind(self)['obj'] |
|
847 | obj = line_info.ofind(self)['obj'] | |
848 |
|
848 | |||
849 | #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg |
|
849 | #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg | |
850 |
|
850 | |||
851 | # This should only be active for single-line input! |
|
851 | # This should only be active for single-line input! | |
852 | if continue_prompt: |
|
852 | if continue_prompt: | |
853 | self.log(line,line,continue_prompt) |
|
853 | self.log(line,line,continue_prompt) | |
854 | return line |
|
854 | return line | |
855 |
|
855 | |||
856 | force_auto = isinstance(obj, IPyAutocall) |
|
856 | force_auto = isinstance(obj, IPyAutocall) | |
857 | auto_rewrite = True |
|
857 | auto_rewrite = True | |
858 |
|
858 | |||
859 | if pre == ESC_QUOTE: |
|
859 | if pre == ESC_QUOTE: | |
860 | # Auto-quote splitting on whitespace |
|
860 | # Auto-quote splitting on whitespace | |
861 | newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) ) |
|
861 | newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) ) | |
862 | elif pre == ESC_QUOTE2: |
|
862 | elif pre == ESC_QUOTE2: | |
863 | # Auto-quote whole string |
|
863 | # Auto-quote whole string | |
864 | newcmd = '%s("%s")' % (ifun,the_rest) |
|
864 | newcmd = '%s("%s")' % (ifun,the_rest) | |
865 | elif pre == ESC_PAREN: |
|
865 | elif pre == ESC_PAREN: | |
866 | newcmd = '%s(%s)' % (ifun,",".join(the_rest.split())) |
|
866 | newcmd = '%s(%s)' % (ifun,",".join(the_rest.split())) | |
867 | else: |
|
867 | else: | |
868 | # Auto-paren. |
|
868 | # Auto-paren. | |
869 | # We only apply it to argument-less calls if the autocall |
|
869 | # We only apply it to argument-less calls if the autocall | |
870 | # parameter is set to 2. We only need to check that autocall is < |
|
870 | # parameter is set to 2. We only need to check that autocall is < | |
871 | # 2, since this function isn't called unless it's at least 1. |
|
871 | # 2, since this function isn't called unless it's at least 1. | |
872 | if not the_rest and (self.shell.autocall < 2) and not force_auto: |
|
872 | if not the_rest and (self.shell.autocall < 2) and not force_auto: | |
873 | newcmd = '%s %s' % (ifun,the_rest) |
|
873 | newcmd = '%s %s' % (ifun,the_rest) | |
874 | auto_rewrite = False |
|
874 | auto_rewrite = False | |
875 | else: |
|
875 | else: | |
876 | if not force_auto and the_rest.startswith('['): |
|
876 | if not force_auto and the_rest.startswith('['): | |
877 | if hasattr(obj,'__getitem__'): |
|
877 | if hasattr(obj,'__getitem__'): | |
878 | # Don't autocall in this case: item access for an object |
|
878 | # Don't autocall in this case: item access for an object | |
879 | # which is BOTH callable and implements __getitem__. |
|
879 | # which is BOTH callable and implements __getitem__. | |
880 | newcmd = '%s %s' % (ifun,the_rest) |
|
880 | newcmd = '%s %s' % (ifun,the_rest) | |
881 | auto_rewrite = False |
|
881 | auto_rewrite = False | |
882 | else: |
|
882 | else: | |
883 | # if the object doesn't support [] access, go ahead and |
|
883 | # if the object doesn't support [] access, go ahead and | |
884 | # autocall |
|
884 | # autocall | |
885 | newcmd = '%s(%s)' % (ifun.rstrip(),the_rest) |
|
885 | newcmd = '%s(%s)' % (ifun.rstrip(),the_rest) | |
886 | elif the_rest.endswith(';'): |
|
886 | elif the_rest.endswith(';'): | |
887 | newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1]) |
|
887 | newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1]) | |
888 | else: |
|
888 | else: | |
889 | newcmd = '%s(%s)' % (ifun.rstrip(), the_rest) |
|
889 | newcmd = '%s(%s)' % (ifun.rstrip(), the_rest) | |
890 |
|
890 | |||
891 | if auto_rewrite: |
|
891 | if auto_rewrite: | |
892 | rw = self.shell.outputcache.prompt1.auto_rewrite() + newcmd |
|
892 | rw = self.shell.outputcache.prompt1.auto_rewrite() + newcmd | |
893 |
|
893 | |||
894 | try: |
|
894 | try: | |
895 | # plain ascii works better w/ pyreadline, on some machines, so |
|
895 | # plain ascii works better w/ pyreadline, on some machines, so | |
896 | # we use it and only print uncolored rewrite if we have unicode |
|
896 | # we use it and only print uncolored rewrite if we have unicode | |
897 | rw = str(rw) |
|
897 | rw = str(rw) | |
898 | print >>Term.cout, rw |
|
898 | print >>Term.cout, rw | |
899 | except UnicodeEncodeError: |
|
899 | except UnicodeEncodeError: | |
900 | print "-------------->" + newcmd |
|
900 | print "-------------->" + newcmd | |
901 |
|
901 | |||
902 | # log what is now valid Python, not the actual user input (without the |
|
902 | # log what is now valid Python, not the actual user input (without the | |
903 | # final newline) |
|
903 | # final newline) | |
904 | self.shell.log(line,newcmd,continue_prompt) |
|
904 | self.shell.log(line,newcmd,continue_prompt) | |
905 | return newcmd |
|
905 | return newcmd | |
906 |
|
906 | |||
907 |
|
907 | |||
908 | class HelpHandler(PrefilterHandler): |
|
908 | class HelpHandler(PrefilterHandler): | |
909 |
|
909 | |||
910 | handler_name = Str('help') |
|
910 | handler_name = Str('help') | |
911 | esc_strings = List([ESC_HELP]) |
|
911 | esc_strings = List([ESC_HELP]) | |
912 |
|
912 | |||
913 | def handle(self, line_info): |
|
913 | def handle(self, line_info): | |
914 | """Try to get some help for the object. |
|
914 | """Try to get some help for the object. | |
915 |
|
915 | |||
916 | obj? or ?obj -> basic information. |
|
916 | obj? or ?obj -> basic information. | |
917 | obj?? or ??obj -> more details. |
|
917 | obj?? or ??obj -> more details. | |
918 | """ |
|
918 | """ | |
919 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') |
|
919 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') | |
920 | line = line_info.line |
|
920 | line = line_info.line | |
921 | # We need to make sure that we don't process lines which would be |
|
921 | # We need to make sure that we don't process lines which would be | |
922 | # otherwise valid python, such as "x=1 # what?" |
|
922 | # otherwise valid python, such as "x=1 # what?" | |
923 | try: |
|
923 | try: | |
924 | codeop.compile_command(line) |
|
924 | codeop.compile_command(line) | |
925 | except SyntaxError: |
|
925 | except SyntaxError: | |
926 | # We should only handle as help stuff which is NOT valid syntax |
|
926 | # We should only handle as help stuff which is NOT valid syntax | |
927 | if line[0]==ESC_HELP: |
|
927 | if line[0]==ESC_HELP: | |
928 | line = line[1:] |
|
928 | line = line[1:] | |
929 | elif line[-1]==ESC_HELP: |
|
929 | elif line[-1]==ESC_HELP: | |
930 | line = line[:-1] |
|
930 | line = line[:-1] | |
931 | self.shell.log(line, '#?'+line, line_info.continue_prompt) |
|
931 | self.shell.log(line, '#?'+line, line_info.continue_prompt) | |
932 | if line: |
|
932 | if line: | |
933 | #print 'line:<%r>' % line # dbg |
|
933 | #print 'line:<%r>' % line # dbg | |
934 | self.shell.magic_pinfo(line) |
|
934 | self.shell.magic_pinfo(line) | |
935 | else: |
|
935 | else: | |
936 | page(self.shell.usage, screen_lines=self.shell.usable_screen_length) |
|
936 | page(self.shell.usage, screen_lines=self.shell.usable_screen_length) | |
937 | return '' # Empty string is needed here! |
|
937 | return '' # Empty string is needed here! | |
938 | except: |
|
938 | except: | |
939 | raise |
|
939 | raise | |
940 | # Pass any other exceptions through to the normal handler |
|
940 | # Pass any other exceptions through to the normal handler | |
941 | return normal_handler.handle(line_info) |
|
941 | return normal_handler.handle(line_info) | |
942 | else: |
|
942 | else: | |
943 | raise |
|
943 | raise | |
944 | # If the code compiles ok, we should handle it normally |
|
944 | # If the code compiles ok, we should handle it normally | |
945 | return normal_handler.handle(line_info) |
|
945 | return normal_handler.handle(line_info) | |
946 |
|
946 | |||
947 |
|
947 | |||
948 | class EmacsHandler(PrefilterHandler): |
|
948 | class EmacsHandler(PrefilterHandler): | |
949 |
|
949 | |||
950 | handler_name = Str('emacs') |
|
950 | handler_name = Str('emacs') | |
951 | esc_strings = List([]) |
|
951 | esc_strings = List([]) | |
952 |
|
952 | |||
953 | def handle(self, line_info): |
|
953 | def handle(self, line_info): | |
954 | """Handle input lines marked by python-mode.""" |
|
954 | """Handle input lines marked by python-mode.""" | |
955 |
|
955 | |||
956 | # Currently, nothing is done. Later more functionality can be added |
|
956 | # Currently, nothing is done. Later more functionality can be added | |
957 | # here if needed. |
|
957 | # here if needed. | |
958 |
|
958 | |||
959 | # The input cache shouldn't be updated |
|
959 | # The input cache shouldn't be updated | |
960 | return line_info.line |
|
960 | return line_info.line | |
961 |
|
961 | |||
962 |
|
962 | |||
963 | #----------------------------------------------------------------------------- |
|
963 | #----------------------------------------------------------------------------- | |
964 | # Defaults |
|
964 | # Defaults | |
965 | #----------------------------------------------------------------------------- |
|
965 | #----------------------------------------------------------------------------- | |
966 |
|
966 | |||
967 |
|
967 | |||
968 | _default_transformers = [ |
|
968 | _default_transformers = [ | |
969 | AssignSystemTransformer, |
|
969 | AssignSystemTransformer, | |
970 | AssignMagicTransformer |
|
970 | AssignMagicTransformer | |
971 | ] |
|
971 | ] | |
972 |
|
972 | |||
973 | _default_checkers = [ |
|
973 | _default_checkers = [ | |
974 | EmacsChecker, |
|
974 | EmacsChecker, | |
975 | ShellEscapeChecker, |
|
975 | ShellEscapeChecker, | |
976 | IPyAutocallChecker, |
|
976 | IPyAutocallChecker, | |
977 | MultiLineMagicChecker, |
|
977 | MultiLineMagicChecker, | |
978 | EscCharsChecker, |
|
978 | EscCharsChecker, | |
979 | AssignmentChecker, |
|
979 | AssignmentChecker, | |
980 | AutoMagicChecker, |
|
980 | AutoMagicChecker, | |
981 | AliasChecker, |
|
981 | AliasChecker, | |
982 | PythonOpsChecker, |
|
982 | PythonOpsChecker, | |
983 | AutocallChecker |
|
983 | AutocallChecker | |
984 | ] |
|
984 | ] | |
985 |
|
985 | |||
986 | _default_handlers = [ |
|
986 | _default_handlers = [ | |
987 | PrefilterHandler, |
|
987 | PrefilterHandler, | |
988 | AliasHandler, |
|
988 | AliasHandler, | |
989 | ShellEscapeHandler, |
|
989 | ShellEscapeHandler, | |
990 | MagicHandler, |
|
990 | MagicHandler, | |
991 | AutoHandler, |
|
991 | AutoHandler, | |
992 | HelpHandler, |
|
992 | HelpHandler, | |
993 | EmacsHandler |
|
993 | EmacsHandler | |
994 | ] |
|
994 | ] | |
995 |
|
995 |
@@ -1,983 +1,983 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """ |
|
3 | """ | |
4 | A lightweight Traits like module. |
|
4 | A lightweight Traits like module. | |
5 |
|
5 | |||
6 | This is designed to provide a lightweight, simple, pure Python version of |
|
6 | This is designed to provide a lightweight, simple, pure Python version of | |
7 | many of the capabilities of enthought.traits. This includes: |
|
7 | many of the capabilities of enthought.traits. This includes: | |
8 |
|
8 | |||
9 | * Validation |
|
9 | * Validation | |
10 | * Type specification with defaults |
|
10 | * Type specification with defaults | |
11 | * Static and dynamic notification |
|
11 | * Static and dynamic notification | |
12 | * Basic predefined types |
|
12 | * Basic predefined types | |
13 | * An API that is similar to enthought.traits |
|
13 | * An API that is similar to enthought.traits | |
14 |
|
14 | |||
15 | We don't support: |
|
15 | We don't support: | |
16 |
|
16 | |||
17 | * Delegation |
|
17 | * Delegation | |
18 | * Automatic GUI generation |
|
18 | * Automatic GUI generation | |
19 | * A full set of trait types. Most importantly, we don't provide container |
|
19 | * A full set of trait types. Most importantly, we don't provide container | |
20 | traitlets (list, dict, tuple) that can trigger notifications if their |
|
20 | traitlets (list, dict, tuple) that can trigger notifications if their | |
21 | contents change. |
|
21 | contents change. | |
22 | * API compatibility with enthought.traits |
|
22 | * API compatibility with enthought.traits | |
23 |
|
23 | |||
24 | There are also some important difference in our design: |
|
24 | There are also some important difference in our design: | |
25 |
|
25 | |||
26 | * enthought.traits does not validate default values. We do. |
|
26 | * enthought.traits does not validate default values. We do. | |
27 |
|
27 | |||
28 | We choose to create this module because we need these capabilities, but |
|
28 | We choose to create this module because we need these capabilities, but | |
29 | we need them to be pure Python so they work in all Python implementations, |
|
29 | we need them to be pure Python so they work in all Python implementations, | |
30 | including Jython and IronPython. |
|
30 | including Jython and IronPython. | |
31 |
|
31 | |||
32 | Authors: |
|
32 | Authors: | |
33 |
|
33 | |||
34 | * Brian Granger |
|
34 | * Brian Granger | |
35 | * Enthought, Inc. Some of the code in this file comes from enthought.traits |
|
35 | * Enthought, Inc. Some of the code in this file comes from enthought.traits | |
36 | and is licensed under the BSD license. Also, many of the ideas also come |
|
36 | and is licensed under the BSD license. Also, many of the ideas also come | |
37 | from enthought.traits even though our implementation is very different. |
|
37 | from enthought.traits even though our implementation is very different. | |
38 | """ |
|
38 | """ | |
39 |
|
39 | |||
40 | #----------------------------------------------------------------------------- |
|
40 | #----------------------------------------------------------------------------- | |
41 | # Copyright (C) 2008-2009 The IPython Development Team |
|
41 | # Copyright (C) 2008-2009 The IPython Development Team | |
42 | # |
|
42 | # | |
43 | # Distributed under the terms of the BSD License. The full license is in |
|
43 | # Distributed under the terms of the BSD License. The full license is in | |
44 | # the file COPYING, distributed as part of this software. |
|
44 | # the file COPYING, distributed as part of this software. | |
45 | #----------------------------------------------------------------------------- |
|
45 | #----------------------------------------------------------------------------- | |
46 |
|
46 | |||
47 | #----------------------------------------------------------------------------- |
|
47 | #----------------------------------------------------------------------------- | |
48 | # Imports |
|
48 | # Imports | |
49 | #----------------------------------------------------------------------------- |
|
49 | #----------------------------------------------------------------------------- | |
50 |
|
50 | |||
51 |
|
51 | |||
52 | import inspect |
|
52 | import inspect | |
53 | import sys |
|
53 | import sys | |
54 | import types |
|
54 | import types | |
55 | from types import ( |
|
55 | from types import ( | |
56 | InstanceType, ClassType, FunctionType, |
|
56 | InstanceType, ClassType, FunctionType, | |
57 | ListType, TupleType |
|
57 | ListType, TupleType | |
58 | ) |
|
58 | ) | |
59 |
|
59 | |||
60 | from IPython.utils.importstring import import_item |
|
60 | from IPython.utils.importstring import import_item | |
61 |
|
61 | |||
62 | ClassTypes = (ClassType, type) |
|
62 | ClassTypes = (ClassType, type) | |
63 |
|
63 | |||
64 | SequenceTypes = (ListType, TupleType) |
|
64 | SequenceTypes = (ListType, TupleType) | |
65 |
|
65 | |||
66 | #----------------------------------------------------------------------------- |
|
66 | #----------------------------------------------------------------------------- | |
67 | # Basic classes |
|
67 | # Basic classes | |
68 | #----------------------------------------------------------------------------- |
|
68 | #----------------------------------------------------------------------------- | |
69 |
|
69 | |||
70 |
|
70 | |||
71 | class NoDefaultSpecified ( object ): pass |
|
71 | class NoDefaultSpecified ( object ): pass | |
72 | NoDefaultSpecified = NoDefaultSpecified() |
|
72 | NoDefaultSpecified = NoDefaultSpecified() | |
73 |
|
73 | |||
74 |
|
74 | |||
75 | class Undefined ( object ): pass |
|
75 | class Undefined ( object ): pass | |
76 | Undefined = Undefined() |
|
76 | Undefined = Undefined() | |
77 |
|
77 | |||
78 |
|
78 | |||
79 | class TraitletError(Exception): |
|
79 | class TraitletError(Exception): | |
80 | pass |
|
80 | pass | |
81 |
|
81 | |||
82 |
|
82 | |||
83 | #----------------------------------------------------------------------------- |
|
83 | #----------------------------------------------------------------------------- | |
84 | # Utilities |
|
84 | # Utilities | |
85 | #----------------------------------------------------------------------------- |
|
85 | #----------------------------------------------------------------------------- | |
86 |
|
86 | |||
87 |
|
87 | |||
88 | def class_of ( object ): |
|
88 | def class_of ( object ): | |
89 | """ Returns a string containing the class name of an object with the |
|
89 | """ Returns a string containing the class name of an object with the | |
90 | correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image', |
|
90 | correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image', | |
91 | 'a PlotValue'). |
|
91 | 'a PlotValue'). | |
92 | """ |
|
92 | """ | |
93 | if isinstance( object, basestring ): |
|
93 | if isinstance( object, basestring ): | |
94 | return add_article( object ) |
|
94 | return add_article( object ) | |
95 |
|
95 | |||
96 | return add_article( object.__class__.__name__ ) |
|
96 | return add_article( object.__class__.__name__ ) | |
97 |
|
97 | |||
98 |
|
98 | |||
99 | def add_article ( name ): |
|
99 | def add_article ( name ): | |
100 | """ Returns a string containing the correct indefinite article ('a' or 'an') |
|
100 | """ Returns a string containing the correct indefinite article ('a' or 'an') | |
101 | prefixed to the specified string. |
|
101 | prefixed to the specified string. | |
102 | """ |
|
102 | """ | |
103 | if name[:1].lower() in 'aeiou': |
|
103 | if name[:1].lower() in 'aeiou': | |
104 | return 'an ' + name |
|
104 | return 'an ' + name | |
105 |
|
105 | |||
106 | return 'a ' + name |
|
106 | return 'a ' + name | |
107 |
|
107 | |||
108 |
|
108 | |||
109 | def repr_type(obj): |
|
109 | def repr_type(obj): | |
110 | """ Return a string representation of a value and its type for readable |
|
110 | """ Return a string representation of a value and its type for readable | |
111 | error messages. |
|
111 | error messages. | |
112 | """ |
|
112 | """ | |
113 | the_type = type(obj) |
|
113 | the_type = type(obj) | |
114 | if the_type is InstanceType: |
|
114 | if the_type is InstanceType: | |
115 | # Old-style class. |
|
115 | # Old-style class. | |
116 | the_type = obj.__class__ |
|
116 | the_type = obj.__class__ | |
117 | msg = '%r %r' % (obj, the_type) |
|
117 | msg = '%r %r' % (obj, the_type) | |
118 | return msg |
|
118 | return msg | |
119 |
|
119 | |||
120 |
|
120 | |||
121 | def parse_notifier_name(name): |
|
121 | def parse_notifier_name(name): | |
122 | """Convert the name argument to a list of names. |
|
122 | """Convert the name argument to a list of names. | |
123 |
|
123 | |||
124 | Examples |
|
124 | Examples | |
125 | -------- |
|
125 | -------- | |
126 |
|
126 | |||
127 | >>> parse_notifier_name('a') |
|
127 | >>> parse_notifier_name('a') | |
128 | ['a'] |
|
128 | ['a'] | |
129 | >>> parse_notifier_name(['a','b']) |
|
129 | >>> parse_notifier_name(['a','b']) | |
130 | ['a', 'b'] |
|
130 | ['a', 'b'] | |
131 | >>> parse_notifier_name(None) |
|
131 | >>> parse_notifier_name(None) | |
132 | ['anytraitlet'] |
|
132 | ['anytraitlet'] | |
133 | """ |
|
133 | """ | |
134 | if isinstance(name, str): |
|
134 | if isinstance(name, str): | |
135 | return [name] |
|
135 | return [name] | |
136 | elif name is None: |
|
136 | elif name is None: | |
137 | return ['anytraitlet'] |
|
137 | return ['anytraitlet'] | |
138 | elif isinstance(name, (list, tuple)): |
|
138 | elif isinstance(name, (list, tuple)): | |
139 | for n in name: |
|
139 | for n in name: | |
140 | assert isinstance(n, str), "names must be strings" |
|
140 | assert isinstance(n, str), "names must be strings" | |
141 | return name |
|
141 | return name | |
142 |
|
142 | |||
143 |
|
143 | |||
144 | class _SimpleTest: |
|
144 | class _SimpleTest: | |
145 | def __init__ ( self, value ): self.value = value |
|
145 | def __init__ ( self, value ): self.value = value | |
146 | def __call__ ( self, test ): |
|
146 | def __call__ ( self, test ): | |
147 | return test == self.value |
|
147 | return test == self.value | |
148 | def __repr__(self): |
|
148 | def __repr__(self): | |
149 | return "<SimpleTest(%r)" % self.value |
|
149 | return "<SimpleTest(%r)" % self.value | |
150 | def __str__(self): |
|
150 | def __str__(self): | |
151 | return self.__repr__() |
|
151 | return self.__repr__() | |
152 |
|
152 | |||
153 |
|
153 | |||
154 | #----------------------------------------------------------------------------- |
|
154 | #----------------------------------------------------------------------------- | |
155 | # Base TraitletType for all traitlets |
|
155 | # Base TraitletType for all traitlets | |
156 | #----------------------------------------------------------------------------- |
|
156 | #----------------------------------------------------------------------------- | |
157 |
|
157 | |||
158 |
|
158 | |||
159 | class TraitletType(object): |
|
159 | class TraitletType(object): | |
160 | """A base class for all traitlet descriptors. |
|
160 | """A base class for all traitlet descriptors. | |
161 |
|
161 | |||
162 | Notes |
|
162 | Notes | |
163 | ----- |
|
163 | ----- | |
164 | Our implementation of traitlets is based on Python's descriptor |
|
164 | Our implementation of traitlets is based on Python's descriptor | |
165 | prototol. This class is the base class for all such descriptors. The |
|
165 | prototol. This class is the base class for all such descriptors. The | |
166 | only magic we use is a custom metaclass for the main :class:`HasTraitlets` |
|
166 | only magic we use is a custom metaclass for the main :class:`HasTraitlets` | |
167 | class that does the following: |
|
167 | class that does the following: | |
168 |
|
168 | |||
169 | 1. Sets the :attr:`name` attribute of every :class:`TraitletType` |
|
169 | 1. Sets the :attr:`name` attribute of every :class:`TraitletType` | |
170 | instance in the class dict to the name of the attribute. |
|
170 | instance in the class dict to the name of the attribute. | |
171 | 2. Sets the :attr:`this_class` attribute of every :class:`TraitletType` |
|
171 | 2. Sets the :attr:`this_class` attribute of every :class:`TraitletType` | |
172 | instance in the class dict to the *class* that declared the traitlet. |
|
172 | instance in the class dict to the *class* that declared the traitlet. | |
173 | This is used by the :class:`This` traitlet to allow subclasses to |
|
173 | This is used by the :class:`This` traitlet to allow subclasses to | |
174 | accept superclasses for :class:`This` values. |
|
174 | accept superclasses for :class:`This` values. | |
175 | """ |
|
175 | """ | |
176 |
|
176 | |||
177 |
|
177 | |||
178 | metadata = {} |
|
178 | metadata = {} | |
179 | default_value = Undefined |
|
179 | default_value = Undefined | |
180 | info_text = 'any value' |
|
180 | info_text = 'any value' | |
181 |
|
181 | |||
182 | def __init__(self, default_value=NoDefaultSpecified, **metadata): |
|
182 | def __init__(self, default_value=NoDefaultSpecified, **metadata): | |
183 | """Create a TraitletType. |
|
183 | """Create a TraitletType. | |
184 | """ |
|
184 | """ | |
185 | if default_value is not NoDefaultSpecified: |
|
185 | if default_value is not NoDefaultSpecified: | |
186 | self.default_value = default_value |
|
186 | self.default_value = default_value | |
187 |
|
187 | |||
188 | if len(metadata) > 0: |
|
188 | if len(metadata) > 0: | |
189 | if len(self.metadata) > 0: |
|
189 | if len(self.metadata) > 0: | |
190 | self._metadata = self.metadata.copy() |
|
190 | self._metadata = self.metadata.copy() | |
191 | self._metadata.update(metadata) |
|
191 | self._metadata.update(metadata) | |
192 | else: |
|
192 | else: | |
193 | self._metadata = metadata |
|
193 | self._metadata = metadata | |
194 | else: |
|
194 | else: | |
195 | self._metadata = self.metadata |
|
195 | self._metadata = self.metadata | |
196 |
|
196 | |||
197 | self.init() |
|
197 | self.init() | |
198 |
|
198 | |||
199 | def init(self): |
|
199 | def init(self): | |
200 | pass |
|
200 | pass | |
201 |
|
201 | |||
202 | def get_default_value(self): |
|
202 | def get_default_value(self): | |
203 | """Create a new instance of the default value.""" |
|
203 | """Create a new instance of the default value.""" | |
204 | dv = self.default_value |
|
204 | dv = self.default_value | |
205 | return dv |
|
205 | return dv | |
206 |
|
206 | |||
207 | def instance_init(self, obj): |
|
207 | def instance_init(self, obj): | |
208 | """This is called by :meth:`HasTraitlets.__new__` to finish init'ing. |
|
208 | """This is called by :meth:`HasTraitlets.__new__` to finish init'ing. | |
209 |
|
209 | |||
210 | Some stages of initialization must be delayed until the parent |
|
210 | Some stages of initialization must be delayed until the parent | |
211 | :class:`HasTraitlets` instance has been created. This method is |
|
211 | :class:`HasTraitlets` instance has been created. This method is | |
212 | called in :meth:`HasTraitlets.__new__` after the instance has been |
|
212 | called in :meth:`HasTraitlets.__new__` after the instance has been | |
213 | created. |
|
213 | created. | |
214 |
|
214 | |||
215 | This method trigger the creation and validation of default values |
|
215 | This method trigger the creation and validation of default values | |
216 | and also things like the resolution of str given class names in |
|
216 | and also things like the resolution of str given class names in | |
217 | :class:`Type` and :class`Instance`. |
|
217 | :class:`Type` and :class`Instance`. | |
218 |
|
218 | |||
219 | Parameters |
|
219 | Parameters | |
220 | ---------- |
|
220 | ---------- | |
221 | obj : :class:`HasTraitlets` instance |
|
221 | obj : :class:`HasTraitlets` instance | |
222 | The parent :class:`HasTraitlets` instance that has just been |
|
222 | The parent :class:`HasTraitlets` instance that has just been | |
223 | created. |
|
223 | created. | |
224 | """ |
|
224 | """ | |
225 | self.set_default_value(obj) |
|
225 | self.set_default_value(obj) | |
226 |
|
226 | |||
227 | def set_default_value(self, obj): |
|
227 | def set_default_value(self, obj): | |
228 | """Set the default value on a per instance basis. |
|
228 | """Set the default value on a per instance basis. | |
229 |
|
229 | |||
230 | This method is called by :meth:`instance_init` to create and |
|
230 | This method is called by :meth:`instance_init` to create and | |
231 | validate the default value. The creation and validation of |
|
231 | validate the default value. The creation and validation of | |
232 | default values must be delayed until the parent :class:`HasTraitlets` |
|
232 | default values must be delayed until the parent :class:`HasTraitlets` | |
233 | class has been instantiated. |
|
233 | class has been instantiated. | |
234 | """ |
|
234 | """ | |
235 | dv = self.get_default_value() |
|
235 | dv = self.get_default_value() | |
236 | newdv = self._validate(obj, dv) |
|
236 | newdv = self._validate(obj, dv) | |
237 | obj._traitlet_values[self.name] = newdv |
|
237 | obj._traitlet_values[self.name] = newdv | |
238 |
|
238 | |||
239 | def __get__(self, obj, cls=None): |
|
239 | def __get__(self, obj, cls=None): | |
240 | """Get the value of the traitlet by self.name for the instance. |
|
240 | """Get the value of the traitlet by self.name for the instance. | |
241 |
|
241 | |||
242 | Default values are instantiated when :meth:`HasTraitlets.__new__` |
|
242 | Default values are instantiated when :meth:`HasTraitlets.__new__` | |
243 | is called. Thus by the time this method gets called either the |
|
243 | is called. Thus by the time this method gets called either the | |
244 | default value or a user defined value (they called :meth:`__set__`) |
|
244 | default value or a user defined value (they called :meth:`__set__`) | |
245 | is in the :class:`HasTraitlets` instance. |
|
245 | is in the :class:`HasTraitlets` instance. | |
246 | """ |
|
246 | """ | |
247 | if obj is None: |
|
247 | if obj is None: | |
248 | return self |
|
248 | return self | |
249 | else: |
|
249 | else: | |
250 | try: |
|
250 | try: | |
251 | value = obj._traitlet_values[self.name] |
|
251 | value = obj._traitlet_values[self.name] | |
252 | except: |
|
252 | except: | |
253 | # HasTraitlets should call set_default_value to populate |
|
253 | # HasTraitlets should call set_default_value to populate | |
254 | # this. So this should never be reached. |
|
254 | # this. So this should never be reached. | |
255 | raise TraitletError('Unexpected error in TraitletType: ' |
|
255 | raise TraitletError('Unexpected error in TraitletType: ' | |
256 | 'default value not set properly') |
|
256 | 'default value not set properly') | |
257 | else: |
|
257 | else: | |
258 | return value |
|
258 | return value | |
259 |
|
259 | |||
260 | def __set__(self, obj, value): |
|
260 | def __set__(self, obj, value): | |
261 | new_value = self._validate(obj, value) |
|
261 | new_value = self._validate(obj, value) | |
262 | old_value = self.__get__(obj) |
|
262 | old_value = self.__get__(obj) | |
263 | if old_value != new_value: |
|
263 | if old_value != new_value: | |
264 | obj._traitlet_values[self.name] = new_value |
|
264 | obj._traitlet_values[self.name] = new_value | |
265 | obj._notify_traitlet(self.name, old_value, new_value) |
|
265 | obj._notify_traitlet(self.name, old_value, new_value) | |
266 |
|
266 | |||
267 | def _validate(self, obj, value): |
|
267 | def _validate(self, obj, value): | |
268 | if hasattr(self, 'validate'): |
|
268 | if hasattr(self, 'validate'): | |
269 | return self.validate(obj, value) |
|
269 | return self.validate(obj, value) | |
270 | elif hasattr(self, 'is_valid_for'): |
|
270 | elif hasattr(self, 'is_valid_for'): | |
271 | valid = self.is_valid_for(value) |
|
271 | valid = self.is_valid_for(value) | |
272 | if valid: |
|
272 | if valid: | |
273 | return value |
|
273 | return value | |
274 | else: |
|
274 | else: | |
275 | raise TraitletError('invalid value for type: %r' % value) |
|
275 | raise TraitletError('invalid value for type: %r' % value) | |
276 | elif hasattr(self, 'value_for'): |
|
276 | elif hasattr(self, 'value_for'): | |
277 | return self.value_for(value) |
|
277 | return self.value_for(value) | |
278 | else: |
|
278 | else: | |
279 | return value |
|
279 | return value | |
280 |
|
280 | |||
281 | def info(self): |
|
281 | def info(self): | |
282 | return self.info_text |
|
282 | return self.info_text | |
283 |
|
283 | |||
284 | def error(self, obj, value): |
|
284 | def error(self, obj, value): | |
285 | if obj is not None: |
|
285 | if obj is not None: | |
286 | e = "The '%s' traitlet of %s instance must be %s, but a value of %s was specified." \ |
|
286 | e = "The '%s' traitlet of %s instance must be %s, but a value of %s was specified." \ | |
287 | % (self.name, class_of(obj), |
|
287 | % (self.name, class_of(obj), | |
288 | self.info(), repr_type(value)) |
|
288 | self.info(), repr_type(value)) | |
289 | else: |
|
289 | else: | |
290 | e = "The '%s' traitlet must be %s, but a value of %r was specified." \ |
|
290 | e = "The '%s' traitlet must be %s, but a value of %r was specified." \ | |
291 | % (self.name, self.info(), repr_type(value)) |
|
291 | % (self.name, self.info(), repr_type(value)) | |
292 | raise TraitletError(e) |
|
292 | raise TraitletError(e) | |
293 |
|
293 | |||
294 | def get_metadata(self, key): |
|
294 | def get_metadata(self, key): | |
295 | return getattr(self, '_metadata', {}).get(key, None) |
|
295 | return getattr(self, '_metadata', {}).get(key, None) | |
296 |
|
296 | |||
297 | def set_metadata(self, key, value): |
|
297 | def set_metadata(self, key, value): | |
298 | getattr(self, '_metadata', {})[key] = value |
|
298 | getattr(self, '_metadata', {})[key] = value | |
299 |
|
299 | |||
300 |
|
300 | |||
301 | #----------------------------------------------------------------------------- |
|
301 | #----------------------------------------------------------------------------- | |
302 | # The HasTraitlets implementation |
|
302 | # The HasTraitlets implementation | |
303 | #----------------------------------------------------------------------------- |
|
303 | #----------------------------------------------------------------------------- | |
304 |
|
304 | |||
305 |
|
305 | |||
306 | class MetaHasTraitlets(type): |
|
306 | class MetaHasTraitlets(type): | |
307 | """A metaclass for HasTraitlets. |
|
307 | """A metaclass for HasTraitlets. | |
308 |
|
308 | |||
309 | This metaclass makes sure that any TraitletType class attributes are |
|
309 | This metaclass makes sure that any TraitletType class attributes are | |
310 | instantiated and sets their name attribute. |
|
310 | instantiated and sets their name attribute. | |
311 | """ |
|
311 | """ | |
312 |
|
312 | |||
313 | def __new__(mcls, name, bases, classdict): |
|
313 | def __new__(mcls, name, bases, classdict): | |
314 | """Create the HasTraitlets class. |
|
314 | """Create the HasTraitlets class. | |
315 |
|
315 | |||
316 | This instantiates all TraitletTypes in the class dict and sets their |
|
316 | This instantiates all TraitletTypes in the class dict and sets their | |
317 | :attr:`name` attribute. |
|
317 | :attr:`name` attribute. | |
318 | """ |
|
318 | """ | |
319 | for k,v in classdict.iteritems(): |
|
319 | for k,v in classdict.iteritems(): | |
320 | if isinstance(v, TraitletType): |
|
320 | if isinstance(v, TraitletType): | |
321 | v.name = k |
|
321 | v.name = k | |
322 | elif inspect.isclass(v): |
|
322 | elif inspect.isclass(v): | |
323 | if issubclass(v, TraitletType): |
|
323 | if issubclass(v, TraitletType): | |
324 | vinst = v() |
|
324 | vinst = v() | |
325 | vinst.name = k |
|
325 | vinst.name = k | |
326 | classdict[k] = vinst |
|
326 | classdict[k] = vinst | |
327 | return super(MetaHasTraitlets, mcls).__new__(mcls, name, bases, classdict) |
|
327 | return super(MetaHasTraitlets, mcls).__new__(mcls, name, bases, classdict) | |
328 |
|
328 | |||
329 | def __init__(cls, name, bases, classdict): |
|
329 | def __init__(cls, name, bases, classdict): | |
330 | """Finish initializing the HasTraitlets class. |
|
330 | """Finish initializing the HasTraitlets class. | |
331 |
|
331 | |||
332 | This sets the :attr:`this_class` attribute of each TraitletType in the |
|
332 | This sets the :attr:`this_class` attribute of each TraitletType in the | |
333 | class dict to the newly created class ``cls``. |
|
333 | class dict to the newly created class ``cls``. | |
334 | """ |
|
334 | """ | |
335 | for k, v in classdict.iteritems(): |
|
335 | for k, v in classdict.iteritems(): | |
336 | if isinstance(v, TraitletType): |
|
336 | if isinstance(v, TraitletType): | |
337 | v.this_class = cls |
|
337 | v.this_class = cls | |
338 | super(MetaHasTraitlets, cls).__init__(name, bases, classdict) |
|
338 | super(MetaHasTraitlets, cls).__init__(name, bases, classdict) | |
339 |
|
339 | |||
340 | class HasTraitlets(object): |
|
340 | class HasTraitlets(object): | |
341 |
|
341 | |||
342 | __metaclass__ = MetaHasTraitlets |
|
342 | __metaclass__ = MetaHasTraitlets | |
343 |
|
343 | |||
344 | def __new__(cls, *args, **kw): |
|
344 | def __new__(cls, *args, **kw): | |
345 | # This is needed because in Python 2.6 object.__new__ only accepts |
|
345 | # This is needed because in Python 2.6 object.__new__ only accepts | |
346 | # the cls argument. |
|
346 | # the cls argument. | |
347 | new_meth = super(HasTraitlets, cls).__new__ |
|
347 | new_meth = super(HasTraitlets, cls).__new__ | |
348 | if new_meth is object.__new__: |
|
348 | if new_meth is object.__new__: | |
349 | inst = new_meth(cls) |
|
349 | inst = new_meth(cls) | |
350 | else: |
|
350 | else: | |
351 | inst = new_meth(cls, *args, **kw) |
|
351 | inst = new_meth(cls, *args, **kw) | |
352 | inst._traitlet_values = {} |
|
352 | inst._traitlet_values = {} | |
353 | inst._traitlet_notifiers = {} |
|
353 | inst._traitlet_notifiers = {} | |
354 | # Here we tell all the TraitletType instances to set their default |
|
354 | # Here we tell all the TraitletType instances to set their default | |
355 | # values on the instance. |
|
355 | # values on the instance. | |
356 | for key in dir(cls): |
|
356 | for key in dir(cls): | |
357 | value = getattr(cls, key) |
|
357 | value = getattr(cls, key) | |
358 | if isinstance(value, TraitletType): |
|
358 | if isinstance(value, TraitletType): | |
359 | value.instance_init(inst) |
|
359 | value.instance_init(inst) | |
360 | return inst |
|
360 | return inst | |
361 |
|
361 | |||
362 | # def __init__(self): |
|
362 | # def __init__(self): | |
363 | # self._traitlet_values = {} |
|
363 | # self._traitlet_values = {} | |
364 | # self._traitlet_notifiers = {} |
|
364 | # self._traitlet_notifiers = {} | |
365 |
|
365 | |||
366 | def _notify_traitlet(self, name, old_value, new_value): |
|
366 | def _notify_traitlet(self, name, old_value, new_value): | |
367 |
|
367 | |||
368 | # First dynamic ones |
|
368 | # First dynamic ones | |
369 | callables = self._traitlet_notifiers.get(name,[]) |
|
369 | callables = self._traitlet_notifiers.get(name,[]) | |
370 | more_callables = self._traitlet_notifiers.get('anytraitlet',[]) |
|
370 | more_callables = self._traitlet_notifiers.get('anytraitlet',[]) | |
371 | callables.extend(more_callables) |
|
371 | callables.extend(more_callables) | |
372 |
|
372 | |||
373 | # Now static ones |
|
373 | # Now static ones | |
374 | try: |
|
374 | try: | |
375 | cb = getattr(self, '_%s_changed' % name) |
|
375 | cb = getattr(self, '_%s_changed' % name) | |
376 | except: |
|
376 | except: | |
377 | pass |
|
377 | pass | |
378 | else: |
|
378 | else: | |
379 | callables.append(cb) |
|
379 | callables.append(cb) | |
380 |
|
380 | |||
381 | # Call them all now |
|
381 | # Call them all now | |
382 | for c in callables: |
|
382 | for c in callables: | |
383 | # Traits catches and logs errors here. I allow them to raise |
|
383 | # Traits catches and logs errors here. I allow them to raise | |
384 | if callable(c): |
|
384 | if callable(c): | |
385 | argspec = inspect.getargspec(c) |
|
385 | argspec = inspect.getargspec(c) | |
386 | nargs = len(argspec[0]) |
|
386 | nargs = len(argspec[0]) | |
387 | # Bound methods have an additional 'self' argument |
|
387 | # Bound methods have an additional 'self' argument | |
388 | # I don't know how to treat unbound methods, but they |
|
388 | # I don't know how to treat unbound methods, but they | |
389 | # can't really be used for callbacks. |
|
389 | # can't really be used for callbacks. | |
390 | if isinstance(c, types.MethodType): |
|
390 | if isinstance(c, types.MethodType): | |
391 | offset = -1 |
|
391 | offset = -1 | |
392 | else: |
|
392 | else: | |
393 | offset = 0 |
|
393 | offset = 0 | |
394 | if nargs + offset == 0: |
|
394 | if nargs + offset == 0: | |
395 | c() |
|
395 | c() | |
396 | elif nargs + offset == 1: |
|
396 | elif nargs + offset == 1: | |
397 | c(name) |
|
397 | c(name) | |
398 | elif nargs + offset == 2: |
|
398 | elif nargs + offset == 2: | |
399 | c(name, new_value) |
|
399 | c(name, new_value) | |
400 | elif nargs + offset == 3: |
|
400 | elif nargs + offset == 3: | |
401 | c(name, old_value, new_value) |
|
401 | c(name, old_value, new_value) | |
402 | else: |
|
402 | else: | |
403 | raise TraitletError('a traitlet changed callback ' |
|
403 | raise TraitletError('a traitlet changed callback ' | |
404 | 'must have 0-3 arguments.') |
|
404 | 'must have 0-3 arguments.') | |
405 | else: |
|
405 | else: | |
406 | raise TraitletError('a traitlet changed callback ' |
|
406 | raise TraitletError('a traitlet changed callback ' | |
407 | 'must be callable.') |
|
407 | 'must be callable.') | |
408 |
|
408 | |||
409 |
|
409 | |||
410 | def _add_notifiers(self, handler, name): |
|
410 | def _add_notifiers(self, handler, name): | |
411 | if not self._traitlet_notifiers.has_key(name): |
|
411 | if not self._traitlet_notifiers.has_key(name): | |
412 | nlist = [] |
|
412 | nlist = [] | |
413 | self._traitlet_notifiers[name] = nlist |
|
413 | self._traitlet_notifiers[name] = nlist | |
414 | else: |
|
414 | else: | |
415 | nlist = self._traitlet_notifiers[name] |
|
415 | nlist = self._traitlet_notifiers[name] | |
416 | if handler not in nlist: |
|
416 | if handler not in nlist: | |
417 | nlist.append(handler) |
|
417 | nlist.append(handler) | |
418 |
|
418 | |||
419 | def _remove_notifiers(self, handler, name): |
|
419 | def _remove_notifiers(self, handler, name): | |
420 | if self._traitlet_notifiers.has_key(name): |
|
420 | if self._traitlet_notifiers.has_key(name): | |
421 | nlist = self._traitlet_notifiers[name] |
|
421 | nlist = self._traitlet_notifiers[name] | |
422 | try: |
|
422 | try: | |
423 | index = nlist.index(handler) |
|
423 | index = nlist.index(handler) | |
424 | except ValueError: |
|
424 | except ValueError: | |
425 | pass |
|
425 | pass | |
426 | else: |
|
426 | else: | |
427 | del nlist[index] |
|
427 | del nlist[index] | |
428 |
|
428 | |||
429 | def on_traitlet_change(self, handler, name=None, remove=False): |
|
429 | def on_traitlet_change(self, handler, name=None, remove=False): | |
430 | """Setup a handler to be called when a traitlet changes. |
|
430 | """Setup a handler to be called when a traitlet changes. | |
431 |
|
431 | |||
432 | This is used to setup dynamic notifications of traitlet changes. |
|
432 | This is used to setup dynamic notifications of traitlet changes. | |
433 |
|
433 | |||
434 | Static handlers can be created by creating methods on a HasTraitlets |
|
434 | Static handlers can be created by creating methods on a HasTraitlets | |
435 | subclass with the naming convention '_[traitletname]_changed'. Thus, |
|
435 | subclass with the naming convention '_[traitletname]_changed'. Thus, | |
436 | to create static handler for the traitlet 'a', create the method |
|
436 | to create static handler for the traitlet 'a', create the method | |
437 | _a_changed(self, name, old, new) (fewer arguments can be used, see |
|
437 | _a_changed(self, name, old, new) (fewer arguments can be used, see | |
438 | below). |
|
438 | below). | |
439 |
|
439 | |||
440 | Parameters |
|
440 | Parameters | |
441 | ---------- |
|
441 | ---------- | |
442 |
|
|
442 | handler : callable | |
443 |
|
|
443 | A callable that is called when a traitlet changes. Its | |
444 |
|
|
444 | signature can be handler(), handler(name), handler(name, new) | |
445 |
|
|
445 | or handler(name, old, new). | |
446 |
|
|
446 | name : list, str, None | |
447 |
|
|
447 | If None, the handler will apply to all traitlets. If a list | |
448 |
|
|
448 | of str, handler will apply to all names in the list. If a | |
449 |
|
|
449 | str, the handler will apply just to that name. | |
450 |
|
|
450 | remove : bool | |
451 |
|
|
451 | If False (the default), then install the handler. If True | |
452 |
|
|
452 | then unintall it. | |
453 | """ |
|
453 | """ | |
454 | if remove: |
|
454 | if remove: | |
455 | names = parse_notifier_name(name) |
|
455 | names = parse_notifier_name(name) | |
456 | for n in names: |
|
456 | for n in names: | |
457 | self._remove_notifiers(handler, n) |
|
457 | self._remove_notifiers(handler, n) | |
458 | else: |
|
458 | else: | |
459 | names = parse_notifier_name(name) |
|
459 | names = parse_notifier_name(name) | |
460 | for n in names: |
|
460 | for n in names: | |
461 | self._add_notifiers(handler, n) |
|
461 | self._add_notifiers(handler, n) | |
462 |
|
462 | |||
463 | def traitlet_names(self, **metadata): |
|
463 | def traitlet_names(self, **metadata): | |
464 | """Get a list of all the names of this classes traitlets.""" |
|
464 | """Get a list of all the names of this classes traitlets.""" | |
465 | return self.traitlets(**metadata).keys() |
|
465 | return self.traitlets(**metadata).keys() | |
466 |
|
466 | |||
467 | def traitlets(self, **metadata): |
|
467 | def traitlets(self, **metadata): | |
468 | """Get a list of all the traitlets of this class. |
|
468 | """Get a list of all the traitlets of this class. | |
469 |
|
469 | |||
470 | The TraitletTypes returned don't know anything about the values |
|
470 | The TraitletTypes returned don't know anything about the values | |
471 | that the various HasTraitlet's instances are holding. |
|
471 | that the various HasTraitlet's instances are holding. | |
472 |
|
472 | |||
473 | This follows the same algorithm as traits does and does not allow |
|
473 | This follows the same algorithm as traits does and does not allow | |
474 | for any simple way of specifying merely that a metadata name |
|
474 | for any simple way of specifying merely that a metadata name | |
475 | exists, but has any value. This is because get_metadata returns |
|
475 | exists, but has any value. This is because get_metadata returns | |
476 | None if a metadata key doesn't exist. |
|
476 | None if a metadata key doesn't exist. | |
477 | """ |
|
477 | """ | |
478 | traitlets = dict([memb for memb in inspect.getmembers(self.__class__) if \ |
|
478 | traitlets = dict([memb for memb in inspect.getmembers(self.__class__) if \ | |
479 | isinstance(memb[1], TraitletType)]) |
|
479 | isinstance(memb[1], TraitletType)]) | |
480 |
|
480 | |||
481 | if len(metadata) == 0: |
|
481 | if len(metadata) == 0: | |
482 | return traitlets |
|
482 | return traitlets | |
483 |
|
483 | |||
484 | for meta_name, meta_eval in metadata.items(): |
|
484 | for meta_name, meta_eval in metadata.items(): | |
485 | if type(meta_eval) is not FunctionType: |
|
485 | if type(meta_eval) is not FunctionType: | |
486 | metadata[meta_name] = _SimpleTest(meta_eval) |
|
486 | metadata[meta_name] = _SimpleTest(meta_eval) | |
487 |
|
487 | |||
488 | result = {} |
|
488 | result = {} | |
489 | for name, traitlet in traitlets.items(): |
|
489 | for name, traitlet in traitlets.items(): | |
490 | for meta_name, meta_eval in metadata.items(): |
|
490 | for meta_name, meta_eval in metadata.items(): | |
491 | if not meta_eval(traitlet.get_metadata(meta_name)): |
|
491 | if not meta_eval(traitlet.get_metadata(meta_name)): | |
492 | break |
|
492 | break | |
493 | else: |
|
493 | else: | |
494 | result[name] = traitlet |
|
494 | result[name] = traitlet | |
495 |
|
495 | |||
496 | return result |
|
496 | return result | |
497 |
|
497 | |||
498 | def traitlet_metadata(self, traitletname, key): |
|
498 | def traitlet_metadata(self, traitletname, key): | |
499 | """Get metadata values for traitlet by key.""" |
|
499 | """Get metadata values for traitlet by key.""" | |
500 | try: |
|
500 | try: | |
501 | traitlet = getattr(self.__class__, traitletname) |
|
501 | traitlet = getattr(self.__class__, traitletname) | |
502 | except AttributeError: |
|
502 | except AttributeError: | |
503 | raise TraitletError("Class %s does not have a traitlet named %s" % |
|
503 | raise TraitletError("Class %s does not have a traitlet named %s" % | |
504 | (self.__class__.__name__, traitletname)) |
|
504 | (self.__class__.__name__, traitletname)) | |
505 | else: |
|
505 | else: | |
506 | return traitlet.get_metadata(key) |
|
506 | return traitlet.get_metadata(key) | |
507 |
|
507 | |||
508 | #----------------------------------------------------------------------------- |
|
508 | #----------------------------------------------------------------------------- | |
509 | # Actual TraitletTypes implementations/subclasses |
|
509 | # Actual TraitletTypes implementations/subclasses | |
510 | #----------------------------------------------------------------------------- |
|
510 | #----------------------------------------------------------------------------- | |
511 |
|
511 | |||
512 | #----------------------------------------------------------------------------- |
|
512 | #----------------------------------------------------------------------------- | |
513 | # TraitletTypes subclasses for handling classes and instances of classes |
|
513 | # TraitletTypes subclasses for handling classes and instances of classes | |
514 | #----------------------------------------------------------------------------- |
|
514 | #----------------------------------------------------------------------------- | |
515 |
|
515 | |||
516 |
|
516 | |||
517 | class ClassBasedTraitletType(TraitletType): |
|
517 | class ClassBasedTraitletType(TraitletType): | |
518 | """A traitlet with error reporting for Type, Instance and This.""" |
|
518 | """A traitlet with error reporting for Type, Instance and This.""" | |
519 |
|
519 | |||
520 | def error(self, obj, value): |
|
520 | def error(self, obj, value): | |
521 | kind = type(value) |
|
521 | kind = type(value) | |
522 | if kind is InstanceType: |
|
522 | if kind is InstanceType: | |
523 | msg = 'class %s' % value.__class__.__name__ |
|
523 | msg = 'class %s' % value.__class__.__name__ | |
524 | else: |
|
524 | else: | |
525 | msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) ) |
|
525 | msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) ) | |
526 |
|
526 | |||
527 | super(ClassBasedTraitletType, self).error(obj, msg) |
|
527 | super(ClassBasedTraitletType, self).error(obj, msg) | |
528 |
|
528 | |||
529 |
|
529 | |||
530 | class Type(ClassBasedTraitletType): |
|
530 | class Type(ClassBasedTraitletType): | |
531 | """A traitlet whose value must be a subclass of a specified class.""" |
|
531 | """A traitlet whose value must be a subclass of a specified class.""" | |
532 |
|
532 | |||
533 | def __init__ (self, default_value=None, klass=None, allow_none=True, **metadata ): |
|
533 | def __init__ (self, default_value=None, klass=None, allow_none=True, **metadata ): | |
534 | """Construct a Type traitlet |
|
534 | """Construct a Type traitlet | |
535 |
|
535 | |||
536 | A Type traitlet specifies that its values must be subclasses of |
|
536 | A Type traitlet specifies that its values must be subclasses of | |
537 | a particular class. |
|
537 | a particular class. | |
538 |
|
538 | |||
539 | If only ``default_value`` is given, it is used for the ``klass`` as |
|
539 | If only ``default_value`` is given, it is used for the ``klass`` as | |
540 | well. |
|
540 | well. | |
541 |
|
541 | |||
542 | Parameters |
|
542 | Parameters | |
543 | ---------- |
|
543 | ---------- | |
544 | default_value : class, str or None |
|
544 | default_value : class, str or None | |
545 | The default value must be a subclass of klass. If an str, |
|
545 | The default value must be a subclass of klass. If an str, | |
546 | the str must be a fully specified class name, like 'foo.bar.Bah'. |
|
546 | the str must be a fully specified class name, like 'foo.bar.Bah'. | |
547 | The string is resolved into real class, when the parent |
|
547 | The string is resolved into real class, when the parent | |
548 | :class:`HasTraitlets` class is instantiated. |
|
548 | :class:`HasTraitlets` class is instantiated. | |
549 | klass : class, str, None |
|
549 | klass : class, str, None | |
550 | Values of this traitlet must be a subclass of klass. The klass |
|
550 | Values of this traitlet must be a subclass of klass. The klass | |
551 | may be specified in a string like: 'foo.bar.MyClass'. |
|
551 | may be specified in a string like: 'foo.bar.MyClass'. | |
552 | The string is resolved into real class, when the parent |
|
552 | The string is resolved into real class, when the parent | |
553 | :class:`HasTraitlets` class is instantiated. |
|
553 | :class:`HasTraitlets` class is instantiated. | |
554 | allow_none : boolean |
|
554 | allow_none : boolean | |
555 | Indicates whether None is allowed as an assignable value. Even if |
|
555 | Indicates whether None is allowed as an assignable value. Even if | |
556 | ``False``, the default value may be ``None``. |
|
556 | ``False``, the default value may be ``None``. | |
557 | """ |
|
557 | """ | |
558 | if default_value is None: |
|
558 | if default_value is None: | |
559 | if klass is None: |
|
559 | if klass is None: | |
560 | klass = object |
|
560 | klass = object | |
561 | elif klass is None: |
|
561 | elif klass is None: | |
562 | klass = default_value |
|
562 | klass = default_value | |
563 |
|
563 | |||
564 | if not (inspect.isclass(klass) or isinstance(klass, basestring)): |
|
564 | if not (inspect.isclass(klass) or isinstance(klass, basestring)): | |
565 | raise TraitletError("A Type traitlet must specify a class.") |
|
565 | raise TraitletError("A Type traitlet must specify a class.") | |
566 |
|
566 | |||
567 | self.klass = klass |
|
567 | self.klass = klass | |
568 | self._allow_none = allow_none |
|
568 | self._allow_none = allow_none | |
569 |
|
569 | |||
570 | super(Type, self).__init__(default_value, **metadata) |
|
570 | super(Type, self).__init__(default_value, **metadata) | |
571 |
|
571 | |||
572 | def validate(self, obj, value): |
|
572 | def validate(self, obj, value): | |
573 | """Validates that the value is a valid object instance.""" |
|
573 | """Validates that the value is a valid object instance.""" | |
574 | try: |
|
574 | try: | |
575 | if issubclass(value, self.klass): |
|
575 | if issubclass(value, self.klass): | |
576 | return value |
|
576 | return value | |
577 | except: |
|
577 | except: | |
578 | if (value is None) and (self._allow_none): |
|
578 | if (value is None) and (self._allow_none): | |
579 | return value |
|
579 | return value | |
580 |
|
580 | |||
581 | self.error(obj, value) |
|
581 | self.error(obj, value) | |
582 |
|
582 | |||
583 | def info(self): |
|
583 | def info(self): | |
584 | """ Returns a description of the trait.""" |
|
584 | """ Returns a description of the trait.""" | |
585 | if isinstance(self.klass, basestring): |
|
585 | if isinstance(self.klass, basestring): | |
586 | klass = self.klass |
|
586 | klass = self.klass | |
587 | else: |
|
587 | else: | |
588 | klass = self.klass.__name__ |
|
588 | klass = self.klass.__name__ | |
589 | result = 'a subclass of ' + klass |
|
589 | result = 'a subclass of ' + klass | |
590 | if self._allow_none: |
|
590 | if self._allow_none: | |
591 | return result + ' or None' |
|
591 | return result + ' or None' | |
592 | return result |
|
592 | return result | |
593 |
|
593 | |||
594 | def instance_init(self, obj): |
|
594 | def instance_init(self, obj): | |
595 | self._resolve_classes() |
|
595 | self._resolve_classes() | |
596 | super(Type, self).instance_init(obj) |
|
596 | super(Type, self).instance_init(obj) | |
597 |
|
597 | |||
598 | def _resolve_classes(self): |
|
598 | def _resolve_classes(self): | |
599 | if isinstance(self.klass, basestring): |
|
599 | if isinstance(self.klass, basestring): | |
600 | self.klass = import_item(self.klass) |
|
600 | self.klass = import_item(self.klass) | |
601 | if isinstance(self.default_value, basestring): |
|
601 | if isinstance(self.default_value, basestring): | |
602 | self.default_value = import_item(self.default_value) |
|
602 | self.default_value = import_item(self.default_value) | |
603 |
|
603 | |||
604 | def get_default_value(self): |
|
604 | def get_default_value(self): | |
605 | return self.default_value |
|
605 | return self.default_value | |
606 |
|
606 | |||
607 |
|
607 | |||
608 | class DefaultValueGenerator(object): |
|
608 | class DefaultValueGenerator(object): | |
609 | """A class for generating new default value instances.""" |
|
609 | """A class for generating new default value instances.""" | |
610 |
|
610 | |||
611 | def __init__(self, *args, **kw): |
|
611 | def __init__(self, *args, **kw): | |
612 | self.args = args |
|
612 | self.args = args | |
613 | self.kw = kw |
|
613 | self.kw = kw | |
614 |
|
614 | |||
615 | def generate(self, klass): |
|
615 | def generate(self, klass): | |
616 | return klass(*self.args, **self.kw) |
|
616 | return klass(*self.args, **self.kw) | |
617 |
|
617 | |||
618 |
|
618 | |||
619 | class Instance(ClassBasedTraitletType): |
|
619 | class Instance(ClassBasedTraitletType): | |
620 | """A trait whose value must be an instance of a specified class. |
|
620 | """A trait whose value must be an instance of a specified class. | |
621 |
|
621 | |||
622 | The value can also be an instance of a subclass of the specified class. |
|
622 | The value can also be an instance of a subclass of the specified class. | |
623 | """ |
|
623 | """ | |
624 |
|
624 | |||
625 | def __init__(self, klass=None, args=None, kw=None, |
|
625 | def __init__(self, klass=None, args=None, kw=None, | |
626 | allow_none=True, **metadata ): |
|
626 | allow_none=True, **metadata ): | |
627 | """Construct an Instance traitlet. |
|
627 | """Construct an Instance traitlet. | |
628 |
|
628 | |||
629 | This traitlet allows values that are instances of a particular |
|
629 | This traitlet allows values that are instances of a particular | |
630 | class or its sublclasses. Our implementation is quite different |
|
630 | class or its sublclasses. Our implementation is quite different | |
631 | from that of enthough.traits as we don't allow instances to be used |
|
631 | from that of enthough.traits as we don't allow instances to be used | |
632 | for klass and we handle the ``args`` and ``kw`` arguments differently. |
|
632 | for klass and we handle the ``args`` and ``kw`` arguments differently. | |
633 |
|
633 | |||
634 | Parameters |
|
634 | Parameters | |
635 | ---------- |
|
635 | ---------- | |
636 | klass : class, str |
|
636 | klass : class, str | |
637 | The class that forms the basis for the traitlet. Class names |
|
637 | The class that forms the basis for the traitlet. Class names | |
638 | can also be specified as strings, like 'foo.bar.Bar'. |
|
638 | can also be specified as strings, like 'foo.bar.Bar'. | |
639 | args : tuple |
|
639 | args : tuple | |
640 | Positional arguments for generating the default value. |
|
640 | Positional arguments for generating the default value. | |
641 | kw : dict |
|
641 | kw : dict | |
642 | Keyword arguments for generating the default value. |
|
642 | Keyword arguments for generating the default value. | |
643 | allow_none : bool |
|
643 | allow_none : bool | |
644 | Indicates whether None is allowed as a value. |
|
644 | Indicates whether None is allowed as a value. | |
645 |
|
645 | |||
646 | Default Value |
|
646 | Default Value | |
647 | ------------- |
|
647 | ------------- | |
648 | If both ``args`` and ``kw`` are None, then the default value is None. |
|
648 | If both ``args`` and ``kw`` are None, then the default value is None. | |
649 | If ``args`` is a tuple and ``kw`` is a dict, then the default is |
|
649 | If ``args`` is a tuple and ``kw`` is a dict, then the default is | |
650 | created as ``klass(*args, **kw)``. If either ``args`` or ``kw`` is |
|
650 | created as ``klass(*args, **kw)``. If either ``args`` or ``kw`` is | |
651 | not (but not both), None is replace by ``()`` or ``{}``. |
|
651 | not (but not both), None is replace by ``()`` or ``{}``. | |
652 | """ |
|
652 | """ | |
653 |
|
653 | |||
654 | self._allow_none = allow_none |
|
654 | self._allow_none = allow_none | |
655 |
|
655 | |||
656 | if (klass is None) or (not (inspect.isclass(klass) or isinstance(klass, basestring))): |
|
656 | if (klass is None) or (not (inspect.isclass(klass) or isinstance(klass, basestring))): | |
657 | raise TraitletError('The klass argument must be a class' |
|
657 | raise TraitletError('The klass argument must be a class' | |
658 | ' you gave: %r' % klass) |
|
658 | ' you gave: %r' % klass) | |
659 | self.klass = klass |
|
659 | self.klass = klass | |
660 |
|
660 | |||
661 | # self.klass is a class, so handle default_value |
|
661 | # self.klass is a class, so handle default_value | |
662 | if args is None and kw is None: |
|
662 | if args is None and kw is None: | |
663 | default_value = None |
|
663 | default_value = None | |
664 | else: |
|
664 | else: | |
665 | if args is None: |
|
665 | if args is None: | |
666 | # kw is not None |
|
666 | # kw is not None | |
667 | args = () |
|
667 | args = () | |
668 | elif kw is None: |
|
668 | elif kw is None: | |
669 | # args is not None |
|
669 | # args is not None | |
670 | kw = {} |
|
670 | kw = {} | |
671 |
|
671 | |||
672 | if not isinstance(kw, dict): |
|
672 | if not isinstance(kw, dict): | |
673 | raise TraitletError("The 'kw' argument must be a dict or None.") |
|
673 | raise TraitletError("The 'kw' argument must be a dict or None.") | |
674 | if not isinstance(args, tuple): |
|
674 | if not isinstance(args, tuple): | |
675 | raise TraitletError("The 'args' argument must be a tuple or None.") |
|
675 | raise TraitletError("The 'args' argument must be a tuple or None.") | |
676 |
|
676 | |||
677 | default_value = DefaultValueGenerator(*args, **kw) |
|
677 | default_value = DefaultValueGenerator(*args, **kw) | |
678 |
|
678 | |||
679 | super(Instance, self).__init__(default_value, **metadata) |
|
679 | super(Instance, self).__init__(default_value, **metadata) | |
680 |
|
680 | |||
681 | def validate(self, obj, value): |
|
681 | def validate(self, obj, value): | |
682 | if value is None: |
|
682 | if value is None: | |
683 | if self._allow_none: |
|
683 | if self._allow_none: | |
684 | return value |
|
684 | return value | |
685 | self.error(obj, value) |
|
685 | self.error(obj, value) | |
686 |
|
686 | |||
687 | if isinstance(value, self.klass): |
|
687 | if isinstance(value, self.klass): | |
688 | return value |
|
688 | return value | |
689 | else: |
|
689 | else: | |
690 | self.error(obj, value) |
|
690 | self.error(obj, value) | |
691 |
|
691 | |||
692 | def info(self): |
|
692 | def info(self): | |
693 | if isinstance(self.klass, basestring): |
|
693 | if isinstance(self.klass, basestring): | |
694 | klass = self.klass |
|
694 | klass = self.klass | |
695 | else: |
|
695 | else: | |
696 | klass = self.klass.__name__ |
|
696 | klass = self.klass.__name__ | |
697 | result = class_of(klass) |
|
697 | result = class_of(klass) | |
698 | if self._allow_none: |
|
698 | if self._allow_none: | |
699 | return result + ' or None' |
|
699 | return result + ' or None' | |
700 |
|
700 | |||
701 | return result |
|
701 | return result | |
702 |
|
702 | |||
703 | def instance_init(self, obj): |
|
703 | def instance_init(self, obj): | |
704 | self._resolve_classes() |
|
704 | self._resolve_classes() | |
705 | super(Instance, self).instance_init(obj) |
|
705 | super(Instance, self).instance_init(obj) | |
706 |
|
706 | |||
707 | def _resolve_classes(self): |
|
707 | def _resolve_classes(self): | |
708 | if isinstance(self.klass, basestring): |
|
708 | if isinstance(self.klass, basestring): | |
709 | self.klass = import_item(self.klass) |
|
709 | self.klass = import_item(self.klass) | |
710 |
|
710 | |||
711 | def get_default_value(self): |
|
711 | def get_default_value(self): | |
712 | """Instantiate a default value instance. |
|
712 | """Instantiate a default value instance. | |
713 |
|
713 | |||
714 | This is called when the containing HasTraitlets classes' |
|
714 | This is called when the containing HasTraitlets classes' | |
715 | :meth:`__new__` method is called to ensure that a unique instance |
|
715 | :meth:`__new__` method is called to ensure that a unique instance | |
716 | is created for each HasTraitlets instance. |
|
716 | is created for each HasTraitlets instance. | |
717 | """ |
|
717 | """ | |
718 | dv = self.default_value |
|
718 | dv = self.default_value | |
719 | if isinstance(dv, DefaultValueGenerator): |
|
719 | if isinstance(dv, DefaultValueGenerator): | |
720 | return dv.generate(self.klass) |
|
720 | return dv.generate(self.klass) | |
721 | else: |
|
721 | else: | |
722 | return dv |
|
722 | return dv | |
723 |
|
723 | |||
724 |
|
724 | |||
725 | class This(ClassBasedTraitletType): |
|
725 | class This(ClassBasedTraitletType): | |
726 | """A traitlet for instances of the class containing this trait. |
|
726 | """A traitlet for instances of the class containing this trait. | |
727 |
|
727 | |||
728 | Because how how and when class bodies are executed, the ``This`` |
|
728 | Because how how and when class bodies are executed, the ``This`` | |
729 | traitlet can only have a default value of None. This, and because we |
|
729 | traitlet can only have a default value of None. This, and because we | |
730 | always validate default values, ``allow_none`` is *always* true. |
|
730 | always validate default values, ``allow_none`` is *always* true. | |
731 | """ |
|
731 | """ | |
732 |
|
732 | |||
733 | info_text = 'an instance of the same type as the receiver or None' |
|
733 | info_text = 'an instance of the same type as the receiver or None' | |
734 |
|
734 | |||
735 | def __init__(self, **metadata): |
|
735 | def __init__(self, **metadata): | |
736 | super(This, self).__init__(None, **metadata) |
|
736 | super(This, self).__init__(None, **metadata) | |
737 |
|
737 | |||
738 | def validate(self, obj, value): |
|
738 | def validate(self, obj, value): | |
739 | # What if value is a superclass of obj.__class__? This is |
|
739 | # What if value is a superclass of obj.__class__? This is | |
740 | # complicated if it was the superclass that defined the This |
|
740 | # complicated if it was the superclass that defined the This | |
741 | # traitlet. |
|
741 | # traitlet. | |
742 | if isinstance(value, self.this_class) or (value is None): |
|
742 | if isinstance(value, self.this_class) or (value is None): | |
743 | return value |
|
743 | return value | |
744 | else: |
|
744 | else: | |
745 | self.error(obj, value) |
|
745 | self.error(obj, value) | |
746 |
|
746 | |||
747 |
|
747 | |||
748 | #----------------------------------------------------------------------------- |
|
748 | #----------------------------------------------------------------------------- | |
749 | # Basic TraitletTypes implementations/subclasses |
|
749 | # Basic TraitletTypes implementations/subclasses | |
750 | #----------------------------------------------------------------------------- |
|
750 | #----------------------------------------------------------------------------- | |
751 |
|
751 | |||
752 |
|
752 | |||
753 | class Any(TraitletType): |
|
753 | class Any(TraitletType): | |
754 | default_value = None |
|
754 | default_value = None | |
755 | info_text = 'any value' |
|
755 | info_text = 'any value' | |
756 |
|
756 | |||
757 |
|
757 | |||
758 | class Int(TraitletType): |
|
758 | class Int(TraitletType): | |
759 | """A integer traitlet.""" |
|
759 | """A integer traitlet.""" | |
760 |
|
760 | |||
761 | evaluate = int |
|
761 | evaluate = int | |
762 | default_value = 0 |
|
762 | default_value = 0 | |
763 | info_text = 'an integer' |
|
763 | info_text = 'an integer' | |
764 |
|
764 | |||
765 | def validate(self, obj, value): |
|
765 | def validate(self, obj, value): | |
766 | if isinstance(value, int): |
|
766 | if isinstance(value, int): | |
767 | return value |
|
767 | return value | |
768 | self.error(obj, value) |
|
768 | self.error(obj, value) | |
769 |
|
769 | |||
770 | class CInt(Int): |
|
770 | class CInt(Int): | |
771 | """A casting version of the int traitlet.""" |
|
771 | """A casting version of the int traitlet.""" | |
772 |
|
772 | |||
773 | def validate(self, obj, value): |
|
773 | def validate(self, obj, value): | |
774 | try: |
|
774 | try: | |
775 | return int(value) |
|
775 | return int(value) | |
776 | except: |
|
776 | except: | |
777 | self.error(obj, value) |
|
777 | self.error(obj, value) | |
778 |
|
778 | |||
779 |
|
779 | |||
780 | class Long(TraitletType): |
|
780 | class Long(TraitletType): | |
781 | """A long integer traitlet.""" |
|
781 | """A long integer traitlet.""" | |
782 |
|
782 | |||
783 | evaluate = long |
|
783 | evaluate = long | |
784 | default_value = 0L |
|
784 | default_value = 0L | |
785 | info_text = 'a long' |
|
785 | info_text = 'a long' | |
786 |
|
786 | |||
787 | def validate(self, obj, value): |
|
787 | def validate(self, obj, value): | |
788 | if isinstance(value, long): |
|
788 | if isinstance(value, long): | |
789 | return value |
|
789 | return value | |
790 | if isinstance(value, int): |
|
790 | if isinstance(value, int): | |
791 | return long(value) |
|
791 | return long(value) | |
792 | self.error(obj, value) |
|
792 | self.error(obj, value) | |
793 |
|
793 | |||
794 |
|
794 | |||
795 | class CLong(Long): |
|
795 | class CLong(Long): | |
796 | """A casting version of the long integer traitlet.""" |
|
796 | """A casting version of the long integer traitlet.""" | |
797 |
|
797 | |||
798 | def validate(self, obj, value): |
|
798 | def validate(self, obj, value): | |
799 | try: |
|
799 | try: | |
800 | return long(value) |
|
800 | return long(value) | |
801 | except: |
|
801 | except: | |
802 | self.error(obj, value) |
|
802 | self.error(obj, value) | |
803 |
|
803 | |||
804 |
|
804 | |||
805 | class Float(TraitletType): |
|
805 | class Float(TraitletType): | |
806 | """A float traitlet.""" |
|
806 | """A float traitlet.""" | |
807 |
|
807 | |||
808 | evaluate = float |
|
808 | evaluate = float | |
809 | default_value = 0.0 |
|
809 | default_value = 0.0 | |
810 | info_text = 'a float' |
|
810 | info_text = 'a float' | |
811 |
|
811 | |||
812 | def validate(self, obj, value): |
|
812 | def validate(self, obj, value): | |
813 | if isinstance(value, float): |
|
813 | if isinstance(value, float): | |
814 | return value |
|
814 | return value | |
815 | if isinstance(value, int): |
|
815 | if isinstance(value, int): | |
816 | return float(value) |
|
816 | return float(value) | |
817 | self.error(obj, value) |
|
817 | self.error(obj, value) | |
818 |
|
818 | |||
819 |
|
819 | |||
820 | class CFloat(Float): |
|
820 | class CFloat(Float): | |
821 | """A casting version of the float traitlet.""" |
|
821 | """A casting version of the float traitlet.""" | |
822 |
|
822 | |||
823 | def validate(self, obj, value): |
|
823 | def validate(self, obj, value): | |
824 | try: |
|
824 | try: | |
825 | return float(value) |
|
825 | return float(value) | |
826 | except: |
|
826 | except: | |
827 | self.error(obj, value) |
|
827 | self.error(obj, value) | |
828 |
|
828 | |||
829 | class Complex(TraitletType): |
|
829 | class Complex(TraitletType): | |
830 | """A traitlet for complex numbers.""" |
|
830 | """A traitlet for complex numbers.""" | |
831 |
|
831 | |||
832 | evaluate = complex |
|
832 | evaluate = complex | |
833 | default_value = 0.0 + 0.0j |
|
833 | default_value = 0.0 + 0.0j | |
834 | info_text = 'a complex number' |
|
834 | info_text = 'a complex number' | |
835 |
|
835 | |||
836 | def validate(self, obj, value): |
|
836 | def validate(self, obj, value): | |
837 | if isinstance(value, complex): |
|
837 | if isinstance(value, complex): | |
838 | return value |
|
838 | return value | |
839 | if isinstance(value, (float, int)): |
|
839 | if isinstance(value, (float, int)): | |
840 | return complex(value) |
|
840 | return complex(value) | |
841 | self.error(obj, value) |
|
841 | self.error(obj, value) | |
842 |
|
842 | |||
843 |
|
843 | |||
844 | class CComplex(Complex): |
|
844 | class CComplex(Complex): | |
845 | """A casting version of the complex number traitlet.""" |
|
845 | """A casting version of the complex number traitlet.""" | |
846 |
|
846 | |||
847 | def validate (self, obj, value): |
|
847 | def validate (self, obj, value): | |
848 | try: |
|
848 | try: | |
849 | return complex(value) |
|
849 | return complex(value) | |
850 | except: |
|
850 | except: | |
851 | self.error(obj, value) |
|
851 | self.error(obj, value) | |
852 |
|
852 | |||
853 |
|
853 | |||
854 | class Str(TraitletType): |
|
854 | class Str(TraitletType): | |
855 | """A traitlet for strings.""" |
|
855 | """A traitlet for strings.""" | |
856 |
|
856 | |||
857 | evaluate = lambda x: x |
|
857 | evaluate = lambda x: x | |
858 | default_value = '' |
|
858 | default_value = '' | |
859 | info_text = 'a string' |
|
859 | info_text = 'a string' | |
860 |
|
860 | |||
861 | def validate(self, obj, value): |
|
861 | def validate(self, obj, value): | |
862 | if isinstance(value, str): |
|
862 | if isinstance(value, str): | |
863 | return value |
|
863 | return value | |
864 | self.error(obj, value) |
|
864 | self.error(obj, value) | |
865 |
|
865 | |||
866 |
|
866 | |||
867 | class CStr(Str): |
|
867 | class CStr(Str): | |
868 | """A casting version of the string traitlet.""" |
|
868 | """A casting version of the string traitlet.""" | |
869 |
|
869 | |||
870 | def validate(self, obj, value): |
|
870 | def validate(self, obj, value): | |
871 | try: |
|
871 | try: | |
872 | return str(value) |
|
872 | return str(value) | |
873 | except: |
|
873 | except: | |
874 | try: |
|
874 | try: | |
875 | return unicode(value) |
|
875 | return unicode(value) | |
876 | except: |
|
876 | except: | |
877 | self.error(obj, value) |
|
877 | self.error(obj, value) | |
878 |
|
878 | |||
879 |
|
879 | |||
880 | class Unicode(TraitletType): |
|
880 | class Unicode(TraitletType): | |
881 | """A traitlet for unicode strings.""" |
|
881 | """A traitlet for unicode strings.""" | |
882 |
|
882 | |||
883 | evaluate = unicode |
|
883 | evaluate = unicode | |
884 | default_value = u'' |
|
884 | default_value = u'' | |
885 | info_text = 'a unicode string' |
|
885 | info_text = 'a unicode string' | |
886 |
|
886 | |||
887 | def validate(self, obj, value): |
|
887 | def validate(self, obj, value): | |
888 | if isinstance(value, unicode): |
|
888 | if isinstance(value, unicode): | |
889 | return value |
|
889 | return value | |
890 | if isinstance(value, str): |
|
890 | if isinstance(value, str): | |
891 | return unicode(value) |
|
891 | return unicode(value) | |
892 | self.error(obj, value) |
|
892 | self.error(obj, value) | |
893 |
|
893 | |||
894 |
|
894 | |||
895 | class CUnicode(Unicode): |
|
895 | class CUnicode(Unicode): | |
896 | """A casting version of the unicode traitlet.""" |
|
896 | """A casting version of the unicode traitlet.""" | |
897 |
|
897 | |||
898 | def validate(self, obj, value): |
|
898 | def validate(self, obj, value): | |
899 | try: |
|
899 | try: | |
900 | return unicode(value) |
|
900 | return unicode(value) | |
901 | except: |
|
901 | except: | |
902 | self.error(obj, value) |
|
902 | self.error(obj, value) | |
903 |
|
903 | |||
904 |
|
904 | |||
905 | class Bool(TraitletType): |
|
905 | class Bool(TraitletType): | |
906 | """A boolean (True, False) traitlet.""" |
|
906 | """A boolean (True, False) traitlet.""" | |
907 | evaluate = bool |
|
907 | evaluate = bool | |
908 | default_value = False |
|
908 | default_value = False | |
909 | info_text = 'a boolean' |
|
909 | info_text = 'a boolean' | |
910 |
|
910 | |||
911 | def validate(self, obj, value): |
|
911 | def validate(self, obj, value): | |
912 | if isinstance(value, bool): |
|
912 | if isinstance(value, bool): | |
913 | return value |
|
913 | return value | |
914 | self.error(obj, value) |
|
914 | self.error(obj, value) | |
915 |
|
915 | |||
916 |
|
916 | |||
917 | class CBool(Bool): |
|
917 | class CBool(Bool): | |
918 | """A casting version of the boolean traitlet.""" |
|
918 | """A casting version of the boolean traitlet.""" | |
919 |
|
919 | |||
920 | def validate(self, obj, value): |
|
920 | def validate(self, obj, value): | |
921 | try: |
|
921 | try: | |
922 | return bool(value) |
|
922 | return bool(value) | |
923 | except: |
|
923 | except: | |
924 | self.error(obj, value) |
|
924 | self.error(obj, value) | |
925 |
|
925 | |||
926 |
|
926 | |||
927 | class Enum(TraitletType): |
|
927 | class Enum(TraitletType): | |
928 | """An enum that whose value must be in a given sequence.""" |
|
928 | """An enum that whose value must be in a given sequence.""" | |
929 |
|
929 | |||
930 | def __init__(self, values, default_value=None, allow_none=True, **metadata): |
|
930 | def __init__(self, values, default_value=None, allow_none=True, **metadata): | |
931 | self.values = values |
|
931 | self.values = values | |
932 | self._allow_none = allow_none |
|
932 | self._allow_none = allow_none | |
933 | super(Enum, self).__init__(default_value, **metadata) |
|
933 | super(Enum, self).__init__(default_value, **metadata) | |
934 |
|
934 | |||
935 | def validate(self, obj, value): |
|
935 | def validate(self, obj, value): | |
936 | if value is None: |
|
936 | if value is None: | |
937 | if self._allow_none: |
|
937 | if self._allow_none: | |
938 | return value |
|
938 | return value | |
939 |
|
939 | |||
940 | if value in self.values: |
|
940 | if value in self.values: | |
941 | return value |
|
941 | return value | |
942 | self.error(obj, value) |
|
942 | self.error(obj, value) | |
943 |
|
943 | |||
944 | def info(self): |
|
944 | def info(self): | |
945 | """ Returns a description of the trait.""" |
|
945 | """ Returns a description of the trait.""" | |
946 | result = 'any of ' + repr(self.values) |
|
946 | result = 'any of ' + repr(self.values) | |
947 | if self._allow_none: |
|
947 | if self._allow_none: | |
948 | return result + ' or None' |
|
948 | return result + ' or None' | |
949 | return result |
|
949 | return result | |
950 |
|
950 | |||
951 | class CaselessStrEnum(Enum): |
|
951 | class CaselessStrEnum(Enum): | |
952 | """An enum of strings that are caseless in validate.""" |
|
952 | """An enum of strings that are caseless in validate.""" | |
953 |
|
953 | |||
954 | def validate(self, obj, value): |
|
954 | def validate(self, obj, value): | |
955 | if value is None: |
|
955 | if value is None: | |
956 | if self._allow_none: |
|
956 | if self._allow_none: | |
957 | return value |
|
957 | return value | |
958 |
|
958 | |||
959 | if not isinstance(value, str): |
|
959 | if not isinstance(value, str): | |
960 | self.error(obj, value) |
|
960 | self.error(obj, value) | |
961 |
|
961 | |||
962 | for v in self.values: |
|
962 | for v in self.values: | |
963 | if v.lower() == value.lower(): |
|
963 | if v.lower() == value.lower(): | |
964 | return v |
|
964 | return v | |
965 | self.error(obj, value) |
|
965 | self.error(obj, value) | |
966 |
|
966 | |||
967 |
|
967 | |||
968 | class List(Instance): |
|
968 | class List(Instance): | |
969 | """An instance of a Python list.""" |
|
969 | """An instance of a Python list.""" | |
970 |
|
970 | |||
971 | def __init__(self, default_value=None, allow_none=True, **metadata): |
|
971 | def __init__(self, default_value=None, allow_none=True, **metadata): | |
972 | """Create a list traitlet type from a list or tuple. |
|
972 | """Create a list traitlet type from a list or tuple. | |
973 |
|
973 | |||
974 | The default value is created by doing ``list(default_value)``, |
|
974 | The default value is created by doing ``list(default_value)``, | |
975 | which creates a copy of the ``default_value``. |
|
975 | which creates a copy of the ``default_value``. | |
976 | """ |
|
976 | """ | |
977 | if default_value is None: |
|
977 | if default_value is None: | |
978 | args = ((),) |
|
978 | args = ((),) | |
979 | elif isinstance(default_value, SequenceTypes): |
|
979 | elif isinstance(default_value, SequenceTypes): | |
980 | args = (default_value,) |
|
980 | args = (default_value,) | |
981 |
|
981 | |||
982 | super(List,self).__init__(klass=list, args=args, |
|
982 | super(List,self).__init__(klass=list, args=args, | |
983 | allow_none=allow_none, **metadata) |
|
983 | allow_none=allow_none, **metadata) |
@@ -1,23 +1,23 b'' | |||||
1 | {% extends "!layout.html" %} |
|
1 | {% extends "!layout.html" %} | |
2 |
|
2 | |||
3 |
|
3 | |||
4 | {% block rootrellink %} |
|
4 | {% block rootrellink %} | |
5 | <li><a href="{{ pathto('index') }}">home</a>| </li> |
|
5 | <li><a href="{{ pathto('index') }}">home</a>| </li> | |
6 | <li><a href="{{ pathto('search') }}">search</a>| </li> |
|
6 | <li><a href="{{ pathto('search') }}">search</a>| </li> | |
7 |
<li><a href="{{ pathto(' |
|
7 | <li><a href="{{ pathto('index') }}">documentation </a> »</li> | |
8 | {% endblock %} |
|
8 | {% endblock %} | |
9 |
|
9 | |||
10 |
|
10 | |||
11 | {% block relbar1 %} |
|
11 | {% block relbar1 %} | |
12 |
|
12 | |||
13 | <div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px"> |
|
13 | <div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px"> | |
14 | <a href="{{ pathto('index') }}"><img src="{{ |
|
14 | <a href="{{ pathto('index') }}"><img src="{{ | |
15 | pathto("_static/logo.png", 1) }}" border="0" alt="IPython Documentation"/></a> |
|
15 | pathto("_static/logo.png", 1) }}" border="0" alt="IPython Documentation"/></a> | |
16 | </div> |
|
16 | </div> | |
17 | {{ super() }} |
|
17 | {{ super() }} | |
18 | {% endblock %} |
|
18 | {% endblock %} | |
19 |
|
19 | |||
20 | {# put the sidebar before the body #} |
|
20 | {# put the sidebar before the body #} | |
21 | {% block sidebar1 %}{{ sidebar() }}{% endblock %} |
|
21 | {% block sidebar1 %}{{ sidebar() }}{% endblock %} | |
22 | {% block sidebar2 %}{% endblock %} |
|
22 | {% block sidebar2 %}{% endblock %} | |
23 |
|
23 |
@@ -1,11 +1,11 b'' | |||||
1 | =============================== |
|
1 | =============================== | |
2 | Configuration and customization |
|
2 | Configuration and customization | |
3 | =============================== |
|
3 | =============================== | |
4 |
|
4 | |||
5 | .. toctree:: |
|
5 | .. toctree:: | |
6 | :maxdepth: 2 |
|
6 | :maxdepth: 2 | |
7 |
|
7 | |||
8 | initial_config.txt |
|
8 | overview.txt | |
9 | customization.txt |
|
9 | ipython.txt | |
10 | new_config.txt |
|
10 | editors.txt | |
11 |
|
11 | old.txt |
@@ -1,250 +1,230 b'' | |||||
1 | .. _initial config: |
|
1 | .. _initial config: | |
2 |
|
2 | |||
3 | ========================================= |
|
3 | ============================================================= | |
4 | Initial configuration of your environment |
|
4 | Outdated configuration information that might still be useful | |
5 | ========================================= |
|
5 | ============================================================= | |
|
6 | ||||
|
7 | .. warning:: | |||
|
8 | ||||
|
9 | All of the information in this file is outdated. Until the new | |||
|
10 | configuration system is better documented, this material is being kept. | |||
6 |
|
11 | |||
7 | This section will help you set various things in your environment for |
|
12 | This section will help you set various things in your environment for | |
8 | your IPython sessions to be as efficient as possible. All of IPython's |
|
13 | your IPython sessions to be as efficient as possible. All of IPython's | |
9 | configuration information, along with several example files, is stored |
|
14 | configuration information, along with several example files, is stored | |
10 | in a directory named by default $HOME/.ipython. You can change this by |
|
15 | in a directory named by default $HOME/.ipython. You can change this by | |
11 | defining the environment variable IPYTHONDIR, or at runtime with the |
|
16 | defining the environment variable IPYTHONDIR, or at runtime with the | |
12 | command line option -ipythondir. |
|
17 | command line option -ipythondir. | |
13 |
|
18 | |||
14 | If all goes well, the first time you run IPython it should automatically create |
|
19 | If all goes well, the first time you run IPython it should automatically create | |
15 | a user copy of the config directory for you, based on its builtin defaults. You |
|
20 | a user copy of the config directory for you, based on its builtin defaults. You | |
16 | can look at the files it creates to learn more about configuring the |
|
21 | can look at the files it creates to learn more about configuring the | |
17 | system. The main file you will modify to configure IPython's behavior is called |
|
22 | system. The main file you will modify to configure IPython's behavior is called | |
18 | ipythonrc (with a .ini extension under Windows), included for reference |
|
23 | ipythonrc (with a .ini extension under Windows), included for reference | |
19 | :ref:`here <ipythonrc>`. This file is very commented and has many variables you |
|
24 | :ref:`here <ipythonrc>`. This file is very commented and has many variables you | |
20 | can change to suit your taste, you can find more details :ref:`here |
|
25 | can change to suit your taste, you can find more details :ref:`here | |
21 | <customization>`. Here we discuss the basic things you will want to make sure |
|
26 | <customization>`. Here we discuss the basic things you will want to make sure | |
22 | things are working properly from the beginning. |
|
27 | things are working properly from the beginning. | |
23 |
|
28 | |||
24 |
|
||||
25 | .. _accessing_help: |
|
|||
26 |
|
||||
27 | Access to the Python help system |
|
|||
28 | ================================ |
|
|||
29 |
|
||||
30 | This is true for Python in general (not just for IPython): you should have an |
|
|||
31 | environment variable called PYTHONDOCS pointing to the directory where your |
|
|||
32 | HTML Python documentation lives. In my system it's |
|
|||
33 | :file:`/usr/share/doc/python-doc/html`, check your local details or ask your |
|
|||
34 | systems administrator. |
|
|||
35 |
|
||||
36 | This is the directory which holds the HTML version of the Python |
|
|||
37 | manuals. Unfortunately it seems that different Linux distributions |
|
|||
38 | package these files differently, so you may have to look around a bit. |
|
|||
39 | Below I show the contents of this directory on my system for reference:: |
|
|||
40 |
|
||||
41 | [html]> ls |
|
|||
42 | about.html dist/ icons/ lib/ python2.5.devhelp.gz whatsnew/ |
|
|||
43 | acks.html doc/ index.html mac/ ref/ |
|
|||
44 | api/ ext/ inst/ modindex.html tut/ |
|
|||
45 |
|
||||
46 | You should really make sure this variable is correctly set so that |
|
|||
47 | Python's pydoc-based help system works. It is a powerful and convenient |
|
|||
48 | system with full access to the Python manuals and all modules accessible |
|
|||
49 | to you. |
|
|||
50 |
|
||||
51 | Under Windows it seems that pydoc finds the documentation automatically, |
|
|||
52 | so no extra setup appears necessary. |
|
|||
53 |
|
||||
54 |
|
||||
55 | Editor |
|
|||
56 | ====== |
|
|||
57 |
|
||||
58 | The %edit command (and its alias %ed) will invoke the editor set in your |
|
|||
59 | environment as EDITOR. If this variable is not set, it will default to |
|
|||
60 | vi under Linux/Unix and to notepad under Windows. You may want to set |
|
|||
61 | this variable properly and to a lightweight editor which doesn't take |
|
|||
62 | too long to start (that is, something other than a new instance of |
|
|||
63 | Emacs). This way you can edit multi-line code quickly and with the power |
|
|||
64 | of a real editor right inside IPython. |
|
|||
65 |
|
||||
66 | If you are a dedicated Emacs user, you should set up the Emacs server so |
|
|||
67 | that new requests are handled by the original process. This means that |
|
|||
68 | almost no time is spent in handling the request (assuming an Emacs |
|
|||
69 | process is already running). For this to work, you need to set your |
|
|||
70 | EDITOR environment variable to 'emacsclient'. The code below, supplied |
|
|||
71 | by Francois Pinard, can then be used in your .emacs file to enable the |
|
|||
72 | server:: |
|
|||
73 |
|
||||
74 | (defvar server-buffer-clients) |
|
|||
75 | (when (and (fboundp 'server-start) (string-equal (getenv "TERM") 'xterm)) |
|
|||
76 | (server-start) |
|
|||
77 | (defun fp-kill-server-with-buffer-routine () |
|
|||
78 | (and server-buffer-clients (server-done))) |
|
|||
79 | (add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine)) |
|
|||
80 |
|
||||
81 | You can also set the value of this editor via the commmand-line option |
|
|||
82 | '-editor' or in your ipythonrc file. This is useful if you wish to use |
|
|||
83 | specifically for IPython an editor different from your typical default |
|
|||
84 | (and for Windows users who tend to use fewer environment variables). |
|
|||
85 |
|
||||
86 |
|
||||
87 | Color |
|
29 | Color | |
88 | ===== |
|
30 | ===== | |
89 |
|
31 | |||
90 | The default IPython configuration has most bells and whistles turned on |
|
32 | The default IPython configuration has most bells and whistles turned on | |
91 | (they're pretty safe). But there's one that may cause problems on some |
|
33 | (they're pretty safe). But there's one that may cause problems on some | |
92 | systems: the use of color on screen for displaying information. This is |
|
34 | systems: the use of color on screen for displaying information. This is | |
93 | very useful, since IPython can show prompts and exception tracebacks |
|
35 | very useful, since IPython can show prompts and exception tracebacks | |
94 | with various colors, display syntax-highlighted source code, and in |
|
36 | with various colors, display syntax-highlighted source code, and in | |
95 | general make it easier to visually parse information. |
|
37 | general make it easier to visually parse information. | |
96 |
|
38 | |||
97 | The following terminals seem to handle the color sequences fine: |
|
39 | The following terminals seem to handle the color sequences fine: | |
98 |
|
40 | |||
99 | * Linux main text console, KDE Konsole, Gnome Terminal, E-term, |
|
41 | * Linux main text console, KDE Konsole, Gnome Terminal, E-term, | |
100 | rxvt, xterm. |
|
42 | rxvt, xterm. | |
101 | * CDE terminal (tested under Solaris). This one boldfaces light colors. |
|
43 | * CDE terminal (tested under Solaris). This one boldfaces light colors. | |
102 | * (X)Emacs buffers. See the emacs_ section for more details on |
|
44 | * (X)Emacs buffers. See the emacs_ section for more details on | |
103 | using IPython with (X)Emacs. |
|
45 | using IPython with (X)Emacs. | |
104 | * A Windows (XP/2k) command prompt with pyreadline_. |
|
46 | * A Windows (XP/2k) command prompt with pyreadline_. | |
105 | * A Windows (XP/2k) CygWin shell. Although some users have reported |
|
47 | * A Windows (XP/2k) CygWin shell. Although some users have reported | |
106 | problems; it is not clear whether there is an issue for everyone |
|
48 | problems; it is not clear whether there is an issue for everyone | |
107 | or only under specific configurations. If you have full color |
|
49 | or only under specific configurations. If you have full color | |
108 | support under cygwin, please post to the IPython mailing list so |
|
50 | support under cygwin, please post to the IPython mailing list so | |
109 | this issue can be resolved for all users. |
|
51 | this issue can be resolved for all users. | |
110 |
|
52 | |||
111 | .. _pyreadline: https://code.launchpad.net/pyreadline |
|
53 | .. _pyreadline: https://code.launchpad.net/pyreadline | |
112 |
|
54 | |||
113 | These have shown problems: |
|
55 | These have shown problems: | |
114 |
|
56 | |||
115 | * Windows command prompt in WinXP/2k logged into a Linux machine via |
|
57 | * Windows command prompt in WinXP/2k logged into a Linux machine via | |
116 | telnet or ssh. |
|
58 | telnet or ssh. | |
117 | * Windows native command prompt in WinXP/2k, without Gary Bishop's |
|
59 | * Windows native command prompt in WinXP/2k, without Gary Bishop's | |
118 | extensions. Once Gary's readline library is installed, the normal |
|
60 | extensions. Once Gary's readline library is installed, the normal | |
119 | WinXP/2k command prompt works perfectly. |
|
61 | WinXP/2k command prompt works perfectly. | |
120 |
|
62 | |||
121 | Currently the following color schemes are available: |
|
63 | Currently the following color schemes are available: | |
122 |
|
64 | |||
123 | * NoColor: uses no color escapes at all (all escapes are empty '' '' |
|
65 | * NoColor: uses no color escapes at all (all escapes are empty '' '' | |
124 | strings). This 'scheme' is thus fully safe to use in any terminal. |
|
66 | strings). This 'scheme' is thus fully safe to use in any terminal. | |
125 | * Linux: works well in Linux console type environments: dark |
|
67 | * Linux: works well in Linux console type environments: dark | |
126 | background with light fonts. It uses bright colors for |
|
68 | background with light fonts. It uses bright colors for | |
127 | information, so it is difficult to read if you have a light |
|
69 | information, so it is difficult to read if you have a light | |
128 | colored background. |
|
70 | colored background. | |
129 | * LightBG: the basic colors are similar to those in the Linux scheme |
|
71 | * LightBG: the basic colors are similar to those in the Linux scheme | |
130 | but darker. It is easy to read in terminals with light backgrounds. |
|
72 | but darker. It is easy to read in terminals with light backgrounds. | |
131 |
|
73 | |||
132 | IPython uses colors for two main groups of things: prompts and |
|
74 | IPython uses colors for two main groups of things: prompts and | |
133 | tracebacks which are directly printed to the terminal, and the object |
|
75 | tracebacks which are directly printed to the terminal, and the object | |
134 | introspection system which passes large sets of data through a pager. |
|
76 | introspection system which passes large sets of data through a pager. | |
135 |
|
77 | |||
136 |
|
||||
137 | Input/Output prompts and exception tracebacks |
|
78 | Input/Output prompts and exception tracebacks | |
138 | ============================================= |
|
79 | ============================================= | |
139 |
|
80 | |||
140 | You can test whether the colored prompts and tracebacks work on your |
|
81 | You can test whether the colored prompts and tracebacks work on your | |
141 | system interactively by typing '%colors Linux' at the prompt (use |
|
82 | system interactively by typing '%colors Linux' at the prompt (use | |
142 | '%colors LightBG' if your terminal has a light background). If the input |
|
83 | '%colors LightBG' if your terminal has a light background). If the input | |
143 | prompt shows garbage like:: |
|
84 | prompt shows garbage like:: | |
144 |
|
85 | |||
145 | [0;32mIn [[1;32m1[0;32m]: [0;00m |
|
86 | [0;32mIn [[1;32m1[0;32m]: [0;00m | |
146 |
|
87 | |||
147 | instead of (in color) something like:: |
|
88 | instead of (in color) something like:: | |
148 |
|
89 | |||
149 | In [1]: |
|
90 | In [1]: | |
150 |
|
91 | |||
151 | this means that your terminal doesn't properly handle color escape |
|
92 | this means that your terminal doesn't properly handle color escape | |
152 | sequences. You can go to a 'no color' mode by typing '%colors NoColor'. |
|
93 | sequences. You can go to a 'no color' mode by typing '%colors NoColor'. | |
153 |
|
94 | |||
154 | You can try using a different terminal emulator program (Emacs users, |
|
95 | You can try using a different terminal emulator program (Emacs users, | |
155 | see below). To permanently set your color preferences, edit the file |
|
96 | see below). To permanently set your color preferences, edit the file | |
156 | $HOME/.ipython/ipythonrc and set the colors option to the desired value. |
|
97 | $HOME/.ipython/ipythonrc and set the colors option to the desired value. | |
157 |
|
98 | |||
158 |
|
99 | |||
159 | Object details (types, docstrings, source code, etc.) |
|
100 | Object details (types, docstrings, source code, etc.) | |
160 | ===================================================== |
|
101 | ===================================================== | |
161 |
|
102 | |||
162 | IPython has a set of special functions for studying the objects you are working |
|
103 | IPython has a set of special functions for studying the objects you are working | |
163 | with, discussed in detail :ref:`here <dynamic_object_info>`. But this system |
|
104 | with, discussed in detail :ref:`here <dynamic_object_info>`. But this system | |
164 | relies on passing information which is longer than your screen through a data |
|
105 | relies on passing information which is longer than your screen through a data | |
165 | pager, such as the common Unix less and more programs. In order to be able to |
|
106 | pager, such as the common Unix less and more programs. In order to be able to | |
166 | see this information in color, your pager needs to be properly configured. I |
|
107 | see this information in color, your pager needs to be properly configured. I | |
167 | strongly recommend using less instead of more, as it seems that more simply can |
|
108 | strongly recommend using less instead of more, as it seems that more simply can | |
168 | not understand colored text correctly. |
|
109 | not understand colored text correctly. | |
169 |
|
110 | |||
170 | In order to configure less as your default pager, do the following: |
|
111 | In order to configure less as your default pager, do the following: | |
171 |
|
112 | |||
172 | 1. Set the environment PAGER variable to less. |
|
113 | 1. Set the environment PAGER variable to less. | |
173 | 2. Set the environment LESS variable to -r (plus any other options |
|
114 | 2. Set the environment LESS variable to -r (plus any other options | |
174 | you always want to pass to less by default). This tells less to |
|
115 | you always want to pass to less by default). This tells less to | |
175 | properly interpret control sequences, which is how color |
|
116 | properly interpret control sequences, which is how color | |
176 | information is given to your terminal. |
|
117 | information is given to your terminal. | |
177 |
|
118 | |||
178 | For the bash shell, add to your ~/.bashrc file the lines:: |
|
119 | For the bash shell, add to your ~/.bashrc file the lines:: | |
179 |
|
120 | |||
180 | export PAGER=less |
|
121 | export PAGER=less | |
181 | export LESS=-r |
|
122 | export LESS=-r | |
182 |
|
123 | |||
183 | For the csh or tcsh shells, add to your ~/.cshrc file the lines:: |
|
124 | For the csh or tcsh shells, add to your ~/.cshrc file the lines:: | |
184 |
|
125 | |||
185 | setenv PAGER less |
|
126 | setenv PAGER less | |
186 | setenv LESS -r |
|
127 | setenv LESS -r | |
187 |
|
128 | |||
188 | There is similar syntax for other Unix shells, look at your system |
|
129 | There is similar syntax for other Unix shells, look at your system | |
189 | documentation for details. |
|
130 | documentation for details. | |
190 |
|
131 | |||
191 | If you are on a system which lacks proper data pagers (such as Windows), |
|
132 | If you are on a system which lacks proper data pagers (such as Windows), | |
192 | IPython will use a very limited builtin pager. |
|
133 | IPython will use a very limited builtin pager. | |
193 |
|
134 | |||
194 |
.. _ |
|
135 | .. _Prompts: | |
195 |
|
136 | |||
196 | (X)Emacs configuration |
|
137 | Fine-tuning your prompt | |
197 | ====================== |
|
138 | ======================= | |
198 |
|
139 | |||
199 | Thanks to the work of Alexander Schmolck and Prabhu Ramachandran, |
|
140 | IPython's prompts can be customized using a syntax similar to that of | |
200 | currently (X)Emacs and IPython get along very well. |
|
141 | the bash shell. Many of bash's escapes are supported, as well as a few | |
201 |
|
142 | additional ones. We list them below:: | ||
202 | Important note: You will need to use a recent enough version of |
|
143 | ||
203 | python-mode.el, along with the file ipython.el. You can check that the |
|
144 | \# | |
204 | version you have of python-mode.el is new enough by either looking at |
|
145 | the prompt/history count number. This escape is automatically | |
205 | the revision number in the file itself, or asking for it in (X)Emacs via |
|
146 | wrapped in the coloring codes for the currently active color scheme. | |
206 | M-x py-version. Versions 4.68 and newer contain the necessary fixes for |
|
147 | \N | |
207 | proper IPython support. |
|
148 | the 'naked' prompt/history count number: this is just the number | |
208 |
|
149 | itself, without any coloring applied to it. This lets you produce | ||
209 | The file ipython.el is included with the IPython distribution, in the |
|
150 | numbered prompts with your own colors. | |
210 | documentation directory (where this manual resides in PDF and HTML |
|
151 | \D | |
211 | formats). |
|
152 | the prompt/history count, with the actual digits replaced by dots. | |
212 |
|
153 | Used mainly in continuation prompts (prompt_in2) | ||
213 | Once you put these files in your Emacs path, all you need in your .emacs |
|
154 | \w | |
214 | file is:: |
|
155 | the current working directory | |
215 |
|
156 | \W | ||
216 | (require 'ipython) |
|
157 | the basename of current working directory | |
217 |
|
158 | \Xn | ||
218 | This should give you full support for executing code snippets via |
|
159 | where $n=0\ldots5.$ The current working directory, with $HOME | |
219 | IPython, opening IPython as your Python shell via ``C-c !``, etc. |
|
160 | replaced by ~, and filtered out to contain only $n$ path elements | |
220 |
|
161 | \Yn | ||
221 | You can customize the arguments passed to the IPython instance at startup by |
|
162 | Similar to \Xn, but with the $n+1$ element included if it is ~ (this | |
222 | setting the ``py-python-command-args`` variable. For example, to start always |
|
163 | is similar to the behavior of the %cn escapes in tcsh) | |
223 | in ``pylab`` mode with hardcoded light-background colors, you can use:: |
|
164 | \u | |
224 |
|
165 | the username of the current user | ||
225 | (setq py-python-command-args '("-pylab" "-colors" "LightBG")) |
|
166 | \$ | |
226 |
|
167 | if the effective UID is 0, a #, otherwise a $ | ||
227 | If you happen to get garbage instead of colored prompts as described in |
|
168 | \h | |
228 | the previous section, you may need to set also in your .emacs file:: |
|
169 | the hostname up to the first '.' | |
229 |
|
170 | \H | ||
230 | (setq ansi-color-for-comint-mode t) |
|
171 | the hostname | |
231 |
|
172 | \n | ||
232 | Notes: |
|
173 | a newline | |
|
174 | \r | |||
|
175 | a carriage return | |||
|
176 | \v | |||
|
177 | IPython version string | |||
|
178 | ||||
|
179 | In addition to these, ANSI color escapes can be insterted into the | |||
|
180 | prompts, as \C_ColorName. The list of valid color names is: Black, Blue, | |||
|
181 | Brown, Cyan, DarkGray, Green, LightBlue, LightCyan, LightGray, | |||
|
182 | LightGreen, LightPurple, LightRed, NoColor, Normal, Purple, Red, White, | |||
|
183 | Yellow. | |||
|
184 | ||||
|
185 | Finally, IPython supports the evaluation of arbitrary expressions in | |||
|
186 | your prompt string. The prompt strings are evaluated through the syntax | |||
|
187 | of PEP 215, but basically you can use $x.y to expand the value of x.y, | |||
|
188 | and for more complicated expressions you can use braces: ${foo()+x} will | |||
|
189 | call function foo and add to it the value of x, before putting the | |||
|
190 | result into your prompt. For example, using | |||
|
191 | prompt_in1 '${commands.getoutput("uptime")}\nIn [\#]: ' | |||
|
192 | will print the result of the uptime command on each prompt (assuming the | |||
|
193 | commands module has been imported in your ipythonrc file). | |||
|
194 | ||||
|
195 | ||||
|
196 | Prompt examples | |||
|
197 | ||||
|
198 | The following options in an ipythonrc file will give you IPython's | |||
|
199 | default prompts:: | |||
|
200 | ||||
|
201 | prompt_in1 'In [\#]:' | |||
|
202 | prompt_in2 ' .\D.:' | |||
|
203 | prompt_out 'Out[\#]:' | |||
|
204 | ||||
|
205 | which look like this:: | |||
|
206 | ||||
|
207 | In [1]: 1+2 | |||
|
208 | Out[1]: 3 | |||
|
209 | ||||
|
210 | In [2]: for i in (1,2,3): | |||
|
211 | ...: print i, | |||
|
212 | ...: | |||
|
213 | 1 2 3 | |||
|
214 | ||||
|
215 | These will give you a very colorful prompt with path information:: | |||
|
216 | ||||
|
217 | #prompt_in1 '\C_Red\u\C_Blue[\C_Cyan\Y1\C_Blue]\C_LightGreen\#>' | |||
|
218 | prompt_in2 ' ..\D>' | |||
|
219 | prompt_out '<\#>' | |||
|
220 | ||||
|
221 | which look like this:: | |||
|
222 | ||||
|
223 | fperez[~/ipython]1> 1+2 | |||
|
224 | <1> 3 | |||
|
225 | fperez[~/ipython]2> for i in (1,2,3): | |||
|
226 | ...> print i, | |||
|
227 | ...> | |||
|
228 | 1 2 3 | |||
233 |
|
229 | |||
234 | * There is one caveat you should be aware of: you must start the |
|
|||
235 | IPython shell before attempting to execute any code regions via |
|
|||
236 | ``C-c |``. Simply type C-c ! to start IPython before passing any code |
|
|||
237 | regions to the interpreter, and you shouldn't experience any |
|
|||
238 | problems. |
|
|||
239 | This is due to a bug in Python itself, which has been fixed for |
|
|||
240 | Python 2.3, but exists as of Python 2.2.2 (reported as SF bug [ |
|
|||
241 | 737947 ]). |
|
|||
242 | * The (X)Emacs support is maintained by Alexander Schmolck, so all |
|
|||
243 | comments/requests should be directed to him through the IPython |
|
|||
244 | mailing lists. |
|
|||
245 | * This code is still somewhat experimental so it's a bit rough |
|
|||
246 | around the edges (although in practice, it works quite well). |
|
|||
247 | * Be aware that if you customize py-python-command previously, this |
|
|||
248 | value will override what ipython.el does (because loading the |
|
|||
249 | customization variables comes later). |
|
|||
250 |
|
230 |
@@ -1,156 +1,78 b'' | |||||
1 |
============ |
|
1 | ============ | |
2 |
|
|
2 | Coding guide | |
3 |
============ |
|
3 | ============ | |
4 |
|
4 | |||
5 |
|
5 | General coding conventions | ||
6 | Coding conventions |
|
6 | ========================== | |
7 | ================== |
|
|||
8 |
|
7 | |||
9 | In general, we'll try to follow the standard Python style conventions as |
|
8 | In general, we'll try to follow the standard Python style conventions as | |
10 |
described in Python's |
|
9 | described in Python's PEP 8 [PEP8]_, the official Python Style Guide. | |
11 |
|
10 | |||
12 | .. _PEP 8: http://www.python.org/peps/pep-0008.html |
|
11 | Other general comments: | |
13 |
|
12 | |||
14 | Other comments: |
|
13 | * In a large file, top level classes and functions should be separated by 2 | |
15 |
|
||||
16 | - In a large file, top level classes and functions should be separated by 2-3 |
|
|||
17 | lines to make it easier to separate them visually. |
|
14 | lines to make it easier to separate them visually. | |
18 |
|
15 | |||
19 |
|
|
16 | * Use 4 spaces for indentation, **never** use hard tabs. | |
20 |
|
17 | |||
21 |
|
|
18 | * Keep the ordering of methods the same in classes that have the same methods. | |
22 | This is particularly true for classes that implement similar interfaces and |
|
19 | This is particularly true for classes that implement similar interfaces and | |
23 | for interfaces that are similar. |
|
20 | for interfaces that are similar. | |
24 |
|
21 | |||
25 | Naming conventions |
|
22 | Naming conventions | |
26 | ------------------ |
|
23 | ================== | |
27 |
|
24 | |||
28 |
In terms of naming conventions, we'll follow the guidelines of PEP 8. |
|
25 | In terms of naming conventions, we'll follow the guidelines of PEP 8 [PEP8]_. | |
29 |
the existing code doesn't honor this perfectly, but for all new |
|
26 | Some of the existing code doesn't honor this perfectly, but for all new | |
30 | (and much existing code is being refactored), we'll use: |
|
27 | IPython code (and much existing code is being refactored), we'll use: | |
31 |
|
28 | |||
32 |
|
|
29 | * All ``lowercase`` module names. | |
33 |
|
30 | |||
34 |
|
|
31 | * ``CamelCase`` for class names. | |
35 |
|
32 | |||
36 |
|
|
33 | * ``lowercase_with_underscores`` for methods, functions, variables and | |
37 | attributes. |
|
34 | attributes. | |
38 |
|
35 | |||
39 | This may be confusing as some of the existing codebase uses a different |
|
36 | This may be confusing as some of the existing codebase uses a different | |
40 | convention (``lowerCamelCase`` for methods and attributes). Slowly, we will |
|
37 | convention (``lowerCamelCase`` for methods and attributes). Slowly, we will | |
41 | move IPython over to the new convention, providing shadow names for backward |
|
38 | move IPython over to the new convention, providing shadow names for backward | |
42 | compatibility in public interfaces. |
|
39 | compatibility in public interfaces. | |
43 |
|
40 | |||
44 | There are, however, some important exceptions to these rules. In some cases, |
|
41 | There are, however, some important exceptions to these rules. In some cases, | |
45 | IPython code will interface with packages (Twisted, Wx, Qt) that use other |
|
42 | IPython code will interface with packages (Twisted, Wx, Qt) that use other | |
46 | conventions. At some level this makes it impossible to adhere to our own |
|
43 | conventions. At some level this makes it impossible to adhere to our own | |
47 | standards at all times. In particular, when subclassing classes that use other |
|
44 | standards at all times. In particular, when subclassing classes that use other | |
48 | naming conventions, you must follow their naming conventions. To deal with |
|
45 | naming conventions, you must follow their naming conventions. To deal with | |
49 | cases like this, we propose the following policy: |
|
46 | cases like this, we propose the following policy: | |
50 |
|
47 | |||
51 | - If you are subclassing a class that uses different conventions, use its |
|
|||
52 | naming conventions throughout your subclass. Thus, if you are creating a |
|
|||
53 | Twisted Protocol class, used Twisted's |
|
|||
54 | ``namingSchemeForMethodsAndAttributes.`` |
|
|||
55 |
|
||||
56 | - All IPython's official interfaces should use our conventions. In some cases |
|
|||
57 | this will mean that you need to provide shadow names (first implement |
|
|||
58 | ``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all |
|
|||
59 | costs, but it will probably be necessary at times. But, please use this |
|
|||
60 | sparingly! |
|
|||
61 |
|
||||
62 | Implementation-specific *private* methods will use |
|
|||
63 | ``_single_underscore_prefix``. Names with a leading double underscore will |
|
|||
64 | *only* be used in special cases, as they makes subclassing difficult (such |
|
|||
65 | names are not easily seen by child classes). |
|
|||
66 |
|
||||
67 | Occasionally some run-in lowercase names are used, but mostly for very short |
|
|||
68 | names or where we are implementing methods very similar to existing ones in a |
|
|||
69 | base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had |
|
|||
70 | established precedent). |
|
|||
71 |
|
||||
72 | The old IPython codebase has a big mix of classes and modules prefixed with an |
|
|||
73 | explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned |
|
|||
74 | upon, as namespaces offer cleaner prefixing. The only case where this approach |
|
|||
75 | is justified is for classes which are expected to be imported into external |
|
|||
76 | namespaces and a very generic name (like Shell) is too likely to clash with |
|
|||
77 | something else. We'll need to revisit this issue as we clean up and refactor |
|
|||
78 | the code, but in general we should remove as many unnecessary ``IP``/``ip`` |
|
|||
79 | prefixes as possible. However, if a prefix seems absolutely necessary the more |
|
|||
80 | specific ``IPY`` or ``ipy`` are preferred. |
|
|||
81 |
|
||||
82 | Older material |
|
|||
83 | ============== |
|
|||
84 |
|
||||
85 | General |
|
|||
86 | ------- |
|
|||
87 |
|
||||
88 | In general, we'll try to follow the standard Python style conventions as |
|
|||
89 | described here: |
|
|||
90 |
|
||||
91 | * `Style Guide for Python Code <http://www.python.org/peps/pep-0008.html>`_ |
|
|||
92 |
|
||||
93 |
|
||||
94 | Other comments: |
|
|||
95 |
|
||||
96 | * In a large file, top level classes and functions should be |
|
|||
97 | separated by 2-3 lines to make it easier to separate them visually. |
|
|||
98 | * Use 4 spaces for indentation. |
|
|||
99 | * Keep the ordering of methods the same in classes that have the same |
|
|||
100 | methods. This is particularly true for classes that implement an interface. |
|
|||
101 |
|
||||
102 | Naming conventions |
|
|||
103 | ------------------ |
|
|||
104 |
|
||||
105 | In terms of naming conventions, we'll follow the guidelines from the `Style |
|
|||
106 | Guide for Python Code`_. |
|
|||
107 |
|
||||
108 | For all new IPython code (and much existing code is being refactored), we'll |
|
|||
109 | use: |
|
|||
110 |
|
||||
111 | * All ``lowercase`` module names. |
|
|||
112 |
|
||||
113 | * ``CamelCase`` for class names. |
|
|||
114 |
|
||||
115 | * ``lowercase_with_underscores`` for methods, functions, variables and |
|
|||
116 | attributes. |
|
|||
117 |
|
||||
118 | There are, however, some important exceptions to these rules. In some cases, |
|
|||
119 | IPython code will interface with packages (Twisted, Wx, Qt) that use other |
|
|||
120 | conventions. At some level this makes it impossible to adhere to our own |
|
|||
121 | standards at all times. In particular, when subclassing classes that use other |
|
|||
122 | naming conventions, you must follow their naming conventions. To deal with |
|
|||
123 | cases like this, we propose the following policy: |
|
|||
124 |
|
||||
125 | * If you are subclassing a class that uses different conventions, use its |
|
48 | * If you are subclassing a class that uses different conventions, use its | |
126 | naming conventions throughout your subclass. Thus, if you are creating a |
|
49 | naming conventions throughout your subclass. Thus, if you are creating a | |
127 | Twisted Protocol class, used Twisted's |
|
50 | Twisted Protocol class, used Twisted's | |
128 | ``namingSchemeForMethodsAndAttributes.`` |
|
51 | ``namingSchemeForMethodsAndAttributes.`` | |
129 |
|
52 | |||
130 | * All IPython's official interfaces should use our conventions. In some cases |
|
53 | * All IPython's official interfaces should use our conventions. In some cases | |
131 | this will mean that you need to provide shadow names (first implement |
|
54 | this will mean that you need to provide shadow names (first implement | |
132 | ``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all |
|
55 | ``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all | |
133 | costs, but it will probably be necessary at times. But, please use this |
|
56 | costs, but it will probably be necessary at times. But, please use this | |
134 | sparingly! |
|
57 | sparingly! | |
135 |
|
58 | |||
136 | Implementation-specific *private* methods will use |
|
59 | Implementation-specific *private* methods will use | |
137 | ``_single_underscore_prefix``. Names with a leading double underscore will |
|
60 | ``_single_underscore_prefix``. Names with a leading double underscore will | |
138 | *only* be used in special cases, as they makes subclassing difficult (such |
|
61 | *only* be used in special cases, as they makes subclassing difficult (such | |
139 | names are not easily seen by child classes). |
|
62 | names are not easily seen by child classes). | |
140 |
|
63 | |||
141 | Occasionally some run-in lowercase names are used, but mostly for very short |
|
64 | Occasionally some run-in lowercase names are used, but mostly for very short | |
142 | names or where we are implementing methods very similar to existing ones in a |
|
65 | names or where we are implementing methods very similar to existing ones in a | |
143 | base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had |
|
66 | base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had | |
144 | established precedent). |
|
67 | established precedent). | |
145 |
|
68 | |||
146 | The old IPython codebase has a big mix of classes and modules prefixed with an |
|
69 | The old IPython codebase has a big mix of classes and modules prefixed with an | |
147 | explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned |
|
70 | explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned | |
148 | upon, as namespaces offer cleaner prefixing. The only case where this approach |
|
71 | upon, as namespaces offer cleaner prefixing. The only case where this approach | |
149 | is justified is for classes which are expected to be imported into external |
|
72 | is justified is for classes which are expected to be imported into external | |
150 | namespaces and a very generic name (like Shell) is too likely to clash with |
|
73 | namespaces and a very generic name (like Shell) is too likely to clash with | |
151 | something else. We'll need to revisit this issue as we clean up and refactor |
|
74 | something else. However, if a prefix seems absolutely necessary the more | |
152 | the code, but in general we should remove as many unnecessary ``IP``/``ip`` |
|
|||
153 | prefixes as possible. However, if a prefix seems absolutely necessary the more |
|
|||
154 | specific ``IPY`` or ``ipy`` are preferred. |
|
75 | specific ``IPY`` or ``ipy`` are preferred. | |
155 |
|
76 | |||
|
77 | .. [PEP8] Python Enhancement Proposal 8. http://www.python.org/peps/pep-0008.html | |||
156 |
|
78 |
@@ -1,191 +1,209 b'' | |||||
|
1 | .. _contributing: | |||
|
2 | ||||
|
3 | ============================ | |||
1 | How to contribute to IPython |
|
4 | How to contribute to IPython | |
2 | ============================ |
|
5 | ============================ | |
3 |
|
6 | |||
|
7 | Overview | |||
|
8 | ======== | |||
|
9 | ||||
4 | IPython development is done using Bazaar [Bazaar]_ and Launchpad [Launchpad]_. |
|
10 | IPython development is done using Bazaar [Bazaar]_ and Launchpad [Launchpad]_. | |
5 | This makes it easy for people to contribute to the development of IPython. |
|
11 | This makes it easy for people to contribute to the development of IPython. | |
6 | There are several ways in which you can join in. |
|
12 | There are several ways in which you can join in. | |
7 |
|
13 | |||
8 |
If you have a small change that you want to |
|
14 | If you have a small change that you want to contribute, you can edit your | |
9 |
|
|
15 | Bazaar checkout of IPython (see below) in-place, and ask Bazaar for the | |
10 |
differences: |
|
16 | differences: | |
|
17 | ||||
|
18 | .. code-block:: bash | |||
11 |
|
19 | |||
12 | $ cd /path/to/your/copy/of/ipython |
|
20 | $ cd /path/to/your/copy/of/ipython | |
13 | $ bzr diff > my_fixes.diff |
|
21 | $ bzr diff > my_fixes.diff | |
14 |
|
22 | |||
15 | This produces a patch file with your fixes, which we can apply to the source |
|
23 | This produces a patch file with your fixes, which we can apply to the source | |
16 |
tree. |
|
24 | tree. This file should then be attached to a ticket in our `bug tracker | |
17 | <https://bugs.launchpad.net/ipython>`_, indicating what it does. |
|
25 | <https://bugs.launchpad.net/ipython>`_, indicating what it does. | |
18 |
|
26 | |||
19 | This model of creating small, self-contained patches works very well and there |
|
27 | This model of creating small, self-contained patches works very well and there | |
20 |
are open source projects that do their entire development this way. |
|
28 | are open source projects that do their entire development this way. However, | |
21 | in IPython we have found that for tracking larger changes, making use of |
|
29 | in IPython we have found that for tracking larger changes, making use of | |
22 |
|
|
30 | Bazaar's full capabilities in conjunction with Launchpad's code hosting | |
23 | services makes for a much better experience. |
|
31 | services makes for a much better experience. | |
24 |
|
32 | |||
25 | Making your own branch of IPython allows you to refine your changes over time, |
|
33 | Making your own branch of IPython allows you to refine your changes over time, | |
26 | track the development of the main team, and propose your own full version of |
|
34 | track the development of the main team, and propose your own full version of | |
27 |
the code for others to use and review, with a minimum amount of fuss. |
|
35 | the code for others to use and review, with a minimum amount of fuss. The next | |
28 | parts of this document will explain how to do this. |
|
36 | parts of this document will explain how to do this. | |
29 |
|
37 | |||
30 | Install Bazaar and create a Launchpad account |
|
38 | Install Bazaar and create a Launchpad account | |
31 | --------------------------------------------- |
|
39 | --------------------------------------------- | |
32 |
|
40 | |||
33 | First make sure you have installed Bazaar (see their `website |
|
41 | First make sure you have installed Bazaar (see their `website | |
34 | <http://bazaar-vcs.org/>`_). To see that Bazaar is installed and knows about |
|
42 | <http://bazaar-vcs.org/>`_). To see that Bazaar is installed and knows about | |
35 |
you, try the following: |
|
43 | you, try the following: | |
|
44 | ||||
|
45 | .. code-block:: bash | |||
36 |
|
46 | |||
37 | $ bzr whoami |
|
47 | $ bzr whoami | |
38 | Joe Coder <jcoder@gmail.com> |
|
48 | Joe Coder <jcoder@gmail.com> | |
39 |
|
49 | |||
40 | This should display your name and email. Next, you will want to create an |
|
50 | This should display your name and email. Next, you will want to create an | |
41 | account on the `Launchpad website <http://www.launchpad.net>`_ and setup your |
|
51 | account on the `Launchpad website <http://www.launchpad.net>`_ and setup your | |
42 | ssh keys. For more information of setting up your ssh keys, see `this link |
|
52 | ssh keys. For more information of setting up your ssh keys, see `this link | |
43 | <https://help.launchpad.net/YourAccount/CreatingAnSSHKeyPair>`_. |
|
53 | <https://help.launchpad.net/YourAccount/CreatingAnSSHKeyPair>`_. | |
44 |
|
54 | |||
45 | Get the main IPython branch from Launchpad |
|
55 | Get the main IPython branch from Launchpad | |
46 | ------------------------------------------ |
|
56 | ------------------------------------------ | |
47 |
|
57 | |||
48 | Now, you can get a copy of the main IPython development branch (we call this |
|
58 | Now, you can get a copy of the main IPython development branch (we call this | |
49 |
the "trunk"): |
|
59 | the "trunk"): | |
|
60 | ||||
|
61 | .. code-block:: bash | |||
50 |
|
62 | |||
51 | $ bzr branch lp:ipython |
|
63 | $ bzr branch lp:ipython | |
52 |
|
64 | |||
53 | Create a working branch |
|
65 | Create a working branch | |
54 | ----------------------- |
|
66 | ----------------------- | |
55 |
|
67 | |||
56 | When working on IPython, you won't actually make edits directly to the |
|
68 | When working on IPython, you won't actually make edits directly to the | |
57 | :file:`lp:ipython` branch. Instead, you will create a separate branch for your |
|
69 | :file:`lp:ipython` branch. Instead, you will create a separate branch for your | |
58 | changes. For now, let's assume you want to do your work in a branch named |
|
70 | changes. For now, let's assume you want to do your work in a branch named | |
59 |
"ipython-mybranch". Create this branch by doing: |
|
71 | "ipython-mybranch". Create this branch by doing: | |
|
72 | ||||
|
73 | .. code-block:: bash | |||
60 |
|
74 | |||
61 | $ bzr branch ipython ipython-mybranch |
|
75 | $ bzr branch ipython ipython-mybranch | |
62 |
|
76 | |||
63 | When you actually create a branch, you will want to give it a name that |
|
77 | When you actually create a branch, you will want to give it a name that | |
64 | reflects the nature of the work that you will be doing in it, like |
|
78 | reflects the nature of the work that you will be doing in it, like | |
65 | "install-docs-update". |
|
79 | "install-docs-update". | |
66 |
|
80 | |||
67 | Make edits in your working branch |
|
81 | Make edits in your working branch | |
68 | --------------------------------- |
|
82 | --------------------------------- | |
69 |
|
83 | |||
70 | Now you are ready to actually make edits in your :file:`ipython-mybranch` |
|
84 | Now you are ready to actually make edits in your :file:`ipython-mybranch` | |
71 | branch. Before doing this, it is helpful to install this branch so you can |
|
85 | branch. Before doing this, it is helpful to install this branch so you can | |
72 | test your changes as you work. This is easiest if you have setuptools |
|
86 | test your changes as you work. This is easiest if you have setuptools | |
73 |
installed. Then, just do: |
|
87 | installed. Then, just do: | |
|
88 | ||||
|
89 | .. code-block:: bash | |||
74 |
|
90 | |||
75 | $ cd ipython-mybranch |
|
91 | $ cd ipython-mybranch | |
76 | $ python setupegg.py develop |
|
92 | $ python setupegg.py develop | |
77 |
|
93 | |||
78 | Now, make some changes. After a while, you will want to commit your changes. |
|
94 | Now, make some changes. After a while, you will want to commit your changes. | |
79 | This let's Bazaar know that you like the changes you have made and gives you |
|
95 | This let's Bazaar know that you like the changes you have made and gives you | |
80 | an opportunity to keep a nice record of what you have done. This looks like |
|
96 | an opportunity to keep a nice record of what you have done. This looks like | |
81 |
this: |
|
97 | this: | |
|
98 | ||||
|
99 | .. code-block:: bash | |||
82 |
|
100 | |||
83 | $ ...do work in ipython-mybranch... |
|
101 | $ ...do work in ipython-mybranch... | |
84 | $ bzr commit -m "the commit message goes here" |
|
102 | $ bzr commit -m "the commit message goes here" | |
85 |
|
103 | |||
86 | Please note that since we now don't use an old-style linear ChangeLog (that |
|
104 | Please note that since we now don't use an old-style linear ChangeLog (that | |
87 | tends to cause problems with distributed version control systems), you should |
|
105 | tends to cause problems with distributed version control systems), you should | |
88 | ensure that your log messages are reasonably detailed. Use a docstring-like |
|
106 | ensure that your log messages are reasonably detailed. Use a docstring-like | |
89 | approach in the commit messages (including the second line being left |
|
107 | approach in the commit messages (including the second line being left | |
90 | *blank*):: |
|
108 | *blank*):: | |
91 |
|
109 | |||
92 | Single line summary of changes being committed. |
|
110 | Single line summary of changes being committed. | |
93 |
|
111 | |||
94 | * more details when warranted ... |
|
112 | * more details when warranted ... | |
95 | * including crediting outside contributors if they sent the |
|
113 | * including crediting outside contributors if they sent the | |
96 | code/bug/idea! |
|
114 | code/bug/idea! | |
97 |
|
115 | |||
98 | As you work, you will repeat this edit/commit cycle many times. If you work on |
|
116 | As you work, you will repeat this edit/commit cycle many times. If you work on | |
99 | your branch for a long time, you will also want to get the latest changes from |
|
117 | your branch for a long time, you will also want to get the latest changes from | |
100 | the :file:`lp:ipython` branch. This can be done with the following sequence of |
|
118 | the :file:`lp:ipython` branch. This can be done with the following sequence of | |
101 |
commands: |
|
119 | commands: | |
|
120 | ||||
|
121 | .. code-block:: bash | |||
102 |
|
122 | |||
103 | $ ls |
|
123 | $ ls | |
104 | ipython |
|
124 | ipython | |
105 | ipython-mybranch |
|
125 | ipython-mybranch | |
106 |
|
126 | |||
107 | $ cd ipython |
|
127 | $ cd ipython | |
108 | $ bzr pull |
|
128 | $ bzr pull | |
109 | $ cd ../ipython-mybranch |
|
129 | $ cd ../ipython-mybranch | |
110 | $ bzr merge ../ipython |
|
130 | $ bzr merge ../ipython | |
111 | $ bzr commit -m "Merging changes from trunk" |
|
131 | $ bzr commit -m "Merging changes from trunk" | |
112 |
|
132 | |||
113 | Along the way, you should also run the IPython test suite. You can do this |
|
|||
114 | using the :command:`iptest` command (which is basically a customized version of |
|
|||
115 | :command:`nosetests`):: |
|
|||
116 |
|
||||
117 | $ cd |
|
|||
118 | $ iptest |
|
|||
119 |
|
||||
120 | The :command:`iptest` command will also pick up and run any tests you have |
|
|||
121 | written. See :ref:`testing documentation <devel_testing>` for further details |
|
|||
122 | on the testing system. |
|
|||
123 |
|
||||
124 |
|
||||
125 | Post your branch and request a code review |
|
133 | Post your branch and request a code review | |
126 | ------------------------------------------ |
|
134 | ------------------------------------------ | |
127 |
|
135 | |||
128 | Once you are done with your edits, you should post your branch on Launchpad so |
|
136 | Once you are done with your edits, you should post your branch on Launchpad so | |
129 | that other IPython developers can review the changes and help you merge your |
|
137 | that other IPython developers can review the changes and help you merge your | |
130 | changes into the main development branch. To post your branch on Launchpad, |
|
138 | changes into the main development branch. To post your branch on Launchpad, | |
131 |
do: |
|
139 | do: | |
|
140 | ||||
|
141 | .. code-block:: bash | |||
132 |
|
142 | |||
133 | $ cd ipython-mybranch |
|
143 | $ cd ipython-mybranch | |
134 | $ bzr push lp:~yourusername/ipython/ipython-mybranch |
|
144 | $ bzr push lp:~yourusername/ipython/ipython-mybranch | |
135 |
|
145 | |||
136 |
Then, go to the `IPython Launchpad site <www.launchpad.net/ipython>`_, |
|
146 | Then, go to the `IPython Launchpad site <http://www.launchpad.net/ipython>`_, | |
137 |
should see your branch under the "Code" tab. If you click on your |
|
147 | and you should see your branch under the "Code" tab. If you click on your | |
138 |
can provide a short description of the branch as well as mark its |
|
148 | branch, you can provide a short description of the branch as well as mark its | |
139 |
importantly, you should click the link that reads "Propose for |
|
149 | status. Most importantly, you should click the link that reads "Propose for | |
140 | another branch". What does this do? |
|
150 | merging into another branch". What does this do? | |
141 |
|
151 | |||
142 | This let's the other IPython developers know that your branch is ready to be |
|
152 | This let's the other IPython developers know that your branch is ready to be | |
143 | reviewed and merged into the main development branch. During this review |
|
153 | reviewed and merged into the main development branch. During this review | |
144 | process, other developers will give you feedback and help you get your code |
|
154 | process, other developers will give you feedback and help you get your code | |
145 | ready to be merged. What types of things will we be looking for: |
|
155 | ready to be merged. What types of things will we be looking for: | |
146 |
|
156 | |||
147 | * All code is documented. |
|
157 | * All code is documented. How to document your code is described in | |
148 | * All code has tests. |
|
158 | :ref:`this section <documenting-ipython>`. | |
|
159 | * All code has tests. How to write and run tests is described in | |||
|
160 | :ref:`this section <testing>`. | |||
149 | * The entire IPython test suite passes. |
|
161 | * The entire IPython test suite passes. | |
150 |
|
162 | |||
|
163 | You should also provide us with a list of changes that your branch contains. | |||
|
164 | See the :ref:`What's new <whatsnew_index>` section of our documentation | |||
|
165 | (:file:`docs/source/whatsnew`) for details on the format and content of this. | |||
|
166 | ||||
151 | Once your changes have been reviewed and approved, someone will merge them |
|
167 | Once your changes have been reviewed and approved, someone will merge them | |
152 | into the main development branch. |
|
168 | into the main development branch. | |
153 |
|
169 | |||
154 |
|
170 | |||
155 | Some notes for core developers when merging third-party contributions |
|
171 | Merging a branch into trunk | |
156 | ===================================================================== |
|
172 | =========================== | |
157 |
|
173 | |||
158 | Core developers, who ultimately merge any approved branch (from themselves, |
|
174 | Core developers, who ultimately merge any approved branch (from themselves, | |
159 | another developer, or any third-party contribution) will typically use |
|
175 | another developer, or any third-party contribution) will typically use | |
160 | :command:`bzr merge` to merge the branch into the trunk and push it to the |
|
176 | :command:`bzr merge` to merge the branch into the trunk and push it to the | |
161 |
main Launc |
|
177 | main Launchpad site. There are a number of things to keep in mind when doing | |
162 |
this |
|
178 | this, so that the project history is easy to understand in the long | |
163 | run, and that generating release notes is as painless and accurate as |
|
179 | run, and that generating release notes is as painless and accurate as | |
164 | possible. |
|
180 | possible. | |
165 |
|
181 | |||
166 |
|
|
182 | * When you merge any non-trivial functionality (from one small bug fix to a | |
167 |
big feature branch), please remember to always edit the |
|
183 | big feature branch), please remember to always edit the appropriate file in | |
168 | file accordingly. This file has one main section for each release, and if |
|
184 | the :ref:`What's new <whatsnew_index>` section of our documentation. | |
169 | you edit it as you go, noting what new features, bug fixes or API changes |
|
185 | Ideally, the author of the branch should provide this content when they | |
170 | you have made, the release notes will be almost finished when they are |
|
186 | submit the branch for review. But if they don't it is the responsibility of | |
171 | needed later. This is much easier if done when you merge the work, rather |
|
187 | the developer doing the merge to add this information. | |
172 | than weeks or months later by re-reading a massive Bazaar log. |
|
188 | ||
173 |
|
189 | * When merges are done, the practice of putting a summary commit message in | ||
174 | - When big merges are done, the practice of putting a summary commit message |
|
190 | the merge is *extremely* useful. It is probably easiest if you simply use | |
175 | in the merge is *extremely* useful. It makes this kind of job much nicer, |
|
191 | the same list of changes that were added to the :ref:`What's new | |
176 | because that summary log message can be almost copy/pasted without changes, |
|
192 | <whatsnew_index>` section of the documentation. | |
177 | if it was well written, rather than dissecting the next-level messages from |
|
193 | ||
178 | the individual commits. |
|
194 | * It's important that we remember to always credit who gave us something if | |
179 |
|
||||
180 | - It's important that we remember to always credit who gave us something if |
|
|||
181 | it's not the committer. In general, we have been fairly good on this front, |
|
195 | it's not the committer. In general, we have been fairly good on this front, | |
182 | this is just a reminder to keep things up. As a note, if you are ever |
|
196 | this is just a reminder to keep things up. As a note, if you are ever | |
183 | committing something that is completely (or almost so) a third-party |
|
197 | committing something that is completely (or almost so) a third-party | |
184 | contribution, do the commit as:: |
|
198 | contribution, do the commit as:: | |
185 |
|
199 | |||
186 | $ bzr commit --author="Someone Else" |
|
200 | $ bzr commit --author="Someone Else" | |
187 |
|
201 | |||
188 | This way it will show that name separately in the log, which makes it even |
|
202 | This way it will show that name separately in the log, which makes it even | |
189 | easier to spot. Obviously we often rework third party contributions |
|
203 | easier to spot. Obviously we often rework third party contributions | |
190 | extensively, but this is still good to keep in mind for cases when we don't |
|
204 | extensively, but this is still good to keep in mind for cases when we don't | |
191 | touch the code too much. No newline at end of file |
|
205 | touch the code too much. | |
|
206 | ||||
|
207 | ||||
|
208 | .. [Bazaar] Bazaar. http://bazaar-vcs.org/ | |||
|
209 | .. [Launchpad] Launchpad. http://www.launchpad.net/ipython |
@@ -1,141 +1,104 b'' | |||||
1 | .. _documenting-ipython: |
|
1 | .. _documenting-ipython: | |
2 |
|
2 | |||
3 | ===================== |
|
3 | ===================== | |
4 | Documenting IPython |
|
4 | Documenting IPython | |
5 | ===================== |
|
5 | ===================== | |
6 |
|
6 | |||
7 | Standalone documentation |
|
7 | Standalone documentation | |
8 | ======================== |
|
8 | ======================== | |
9 |
|
9 | |||
10 | All standalone documentation should be written in plain text (``.txt``) files |
|
10 | All standalone documentation should be written in plain text (``.txt``) files | |
11 |
using |
|
11 | using reStructuredText [reStructuredText]_ for markup and formatting. All such | |
12 |
should be placed in the |
|
12 | documentation should be placed in the directory :file:`docs/source` of the | |
13 |
tree. Or, when appropriate, a suitably named subdirectory |
|
13 | IPython source tree. Or, when appropriate, a suitably named subdirectory | |
14 |
documentation in this location will serve as the main |
|
14 | should be used. The documentation in this location will serve as the main | |
15 | documentation and all existing documentation should be converted to this |
|
15 | source for IPython documentation. | |
16 | format. |
|
|||
17 |
|
||||
18 | The actual HTML and PDF docs are built using the Sphinx_ documentation |
|
|||
19 | generation tool. Sphinx has been adopted as the default documentation tool for |
|
|||
20 | Python itself as of version 2.6, as well as by a number of projects that |
|
|||
21 | IPython is related with, such as numpy, scipy, matplotlib, sage and nipy. |
|
|||
22 |
|
16 | |||
23 | .. _reStructuredText: http://docutils.sourceforge.net/rst.html |
|
17 | The actual HTML and PDF docs are built using the Sphinx [Sphinx]_ | |
24 | .. _Sphinx: http://sphinx.pocoo.org/ |
|
18 | documentation generation tool. Once you have Sphinx installed, you can build | |
|
19 | the html docs yourself by doing: | |||
25 |
|
20 | |||
|
21 | .. code-block:: bash | |||
26 |
|
22 | |||
27 | The rest of this document is mostly taken from the `matploblib |
|
23 | $ cd ipython-mybranch/docs | |
28 | documentation`__; we are using a number of Sphinx tools and extensions written |
|
24 | $ make html | |
29 | by the matplotlib team and will mostly follow their conventions, which are |
|
|||
30 | nicely spelled out in their guide. What follows is thus a lightly adapted |
|
|||
31 | version of the matplotlib documentation guide, taken with permission from the |
|
|||
32 | MPL team. |
|
|||
33 |
|
25 | |||
34 | .. __: http://matplotlib.sourceforge.net/devel/documenting_mpl.html |
|
26 | Our usage of Sphinx follows that of matplotlib [Matplotlib]_ closely. We are | |
|
27 | using a number of Sphinx tools and extensions written by the matplotlib team | |||
|
28 | and will mostly follow their conventions, which are nicely spelled out in | |||
|
29 | their documentation guide [MatplotlibDocGuide]_. What follows is thus a | |||
|
30 | abridged version of the matplotlib documentation guide, taken with permission | |||
|
31 | from the matplotlib team. | |||
35 |
|
32 | |||
|
33 | If you are reading this in a web browser, you can click on the "Show Source" | |||
|
34 | link to see the original reStricturedText for the following examples. | |||
36 |
|
35 | |||
37 | A bit of Python code:: |
|
36 | A bit of Python code:: | |
38 |
|
37 | |||
39 | for i in range(10): |
|
38 | for i in range(10): | |
40 | print i, |
|
39 | print i, | |
41 | print "A big number:",2**34 |
|
40 | print "A big number:",2**34 | |
42 |
|
41 | |||
43 | An interactive Python session:: |
|
42 | An interactive Python session:: | |
44 |
|
43 | |||
45 | >>> from IPython import genutils |
|
44 | >>> from IPython import genutils | |
46 | >>> genutils.get_ipython_dir() |
|
45 | >>> genutils.get_ipython_dir() | |
47 | '/home/fperez/.ipython' |
|
46 | '/home/fperez/.ipython' | |
48 |
|
47 | |||
49 |
|
||||
50 | An IPython session: |
|
48 | An IPython session: | |
51 |
|
49 | |||
52 | .. code-block:: ipython |
|
50 | .. code-block:: ipython | |
53 |
|
51 | |||
54 | In [7]: import IPython |
|
52 | In [7]: import IPython | |
55 |
|
53 | |||
56 | In [8]: print "This IPython is version:",IPython.__version__ |
|
54 | In [8]: print "This IPython is version:",IPython.__version__ | |
57 | This IPython is version: 0.9.1 |
|
55 | This IPython is version: 0.9.1 | |
58 |
|
56 | |||
59 | In [9]: 2+4 |
|
57 | In [9]: 2+4 | |
60 | Out[9]: 6 |
|
58 | Out[9]: 6 | |
61 |
|
59 | |||
62 |
|
60 | |||
63 | A bit of shell code: |
|
61 | A bit of shell code: | |
64 |
|
62 | |||
65 | .. code-block:: bash |
|
63 | .. code-block:: bash | |
66 |
|
64 | |||
67 | cd /tmp |
|
65 | cd /tmp | |
68 | echo "My home directory is: $HOME" |
|
66 | echo "My home directory is: $HOME" | |
69 | ls |
|
67 | ls | |
70 |
|
68 | |||
71 |
|
||||
72 | Docstring format |
|
69 | Docstring format | |
73 | ================ |
|
70 | ================ | |
74 |
|
71 | |||
75 | Good docstrings are very important. Unfortunately, Python itself only provides |
|
72 | Good docstrings are very important. Unfortunately, Python itself only provides | |
76 |
a rather loose standard for docstrings |
|
73 | a rather loose standard for docstrings [PEP257]_, and there is no universally | |
77 | accepted convention for all the different parts of a complete docstring. |
|
74 | accepted convention for all the different parts of a complete docstring. | |
78 | However, the NumPy project has established a very reasonable standard, and has |
|
75 | However, the NumPy project has established a very reasonable standard, and has | |
79 | developed some tools to support the smooth inclusion of such docstrings in |
|
76 | developed some tools to support the smooth inclusion of such docstrings in | |
80 | Sphinx-generated manuals. Rather than inventing yet another pseudo-standard, |
|
77 | Sphinx-generated manuals. Rather than inventing yet another pseudo-standard, | |
81 | IPython will be henceforth documented using the NumPy conventions; we carry |
|
78 | IPython will be henceforth documented using the NumPy conventions; we carry | |
82 | copies of some of the NumPy support tools to remain self-contained, but share |
|
79 | copies of some of the NumPy support tools to remain self-contained, but share | |
83 | back upstream with NumPy any improvements or fixes we may make to the tools. |
|
80 | back upstream with NumPy any improvements or fixes we may make to the tools. | |
84 |
|
81 | |||
85 |
The |
|
82 | The NumPy documentation guidelines [NumPyDocGuide]_ contain detailed | |
86 |
standard, and for a quick overview, the NumPy |
|
83 | information on this standard, and for a quick overview, the NumPy example | |
87 | read. |
|
84 | docstring [NumPyExampleDocstring]_ is a useful read. | |
88 |
|
85 | |||
89 |
|
|
86 | In the past IPython used epydoc so currently many docstrings still use epydoc | |
90 |
conventions. We will update them as we go, but all new code should be |
|
87 | conventions. We will update them as we go, but all new code should be | |
91 | documented using the NumPy standard. |
|
88 | documented using the NumPy standard. | |
92 |
|
89 | |||
93 | .. _PEP 257: http://www.python.org/peps/pep-0257.html |
|
90 | Here are two additional PEPs of interest regarding documentation of code. | |
94 | .. _NumPy documentation guidelines: http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines |
|
91 | While both of these were rejected, the ideas therein form much of the basis of | |
95 |
|
92 | docutils (the machinery to process reStructuredText): | ||
96 | .. _example docstring: http://projects.scipy.org/numpy/browser/trunk/doc/EXAMPLE_DOCSTRING.txt |
|
|||
97 |
|
||||
98 | Additional PEPs of interest regarding documentation of code. While both of |
|
|||
99 | these were rejected, the ideas therein form much of the basis of docutils (the |
|
|||
100 | machinery to process reStructuredText): |
|
|||
101 |
|
||||
102 | - `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_ |
|
|||
103 | - `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_ |
|
|||
104 |
|
||||
105 | Older material |
|
|||
106 | ============== |
|
|||
107 |
|
||||
108 | Documentation |
|
|||
109 | ============= |
|
|||
110 |
|
||||
111 | Standalone documentation |
|
|||
112 | ------------------------ |
|
|||
113 |
|
||||
114 | All standalone documentation should be written in plain text (``.txt``) files |
|
|||
115 | using reStructuredText [reStructuredText]_ for markup and formatting. All such |
|
|||
116 | documentation should be placed in directory :file:`docs/source` of the IPython |
|
|||
117 | source tree. The documentation in this location will serve as the main source |
|
|||
118 | for IPython documentation and all existing documentation should be converted |
|
|||
119 | to this format. |
|
|||
120 |
|
||||
121 | To build the final documentation, we use Sphinx [Sphinx]_. Once you have |
|
|||
122 | Sphinx installed, you can build the html docs yourself by doing:: |
|
|||
123 |
|
||||
124 | $ cd ipython-mybranch/docs |
|
|||
125 | $ make html |
|
|||
126 |
|
93 | |||
127 | Docstring format |
|
|||
128 | ---------------- |
|
|||
129 |
|
||||
130 | Good docstrings are very important. All new code should have docstrings that |
|
|||
131 | are formatted using reStructuredText for markup and formatting, since it is |
|
|||
132 | understood by a wide variety of tools. Details about using reStructuredText |
|
|||
133 | for docstrings can be found `here |
|
|||
134 | <http://epydoc.sourceforge.net/manual-othermarkup.html>`_. |
|
|||
135 |
|
||||
136 | Additional PEPs of interest regarding documentation of code: |
|
|||
137 |
|
||||
138 | * `Docstring Conventions <http://www.python.org/peps/pep-0257.html>`_ |
|
|||
139 | * `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_ |
|
94 | * `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_ | |
140 | * `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_ |
|
95 | * `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_ | |
141 |
|
96 | |||
|
97 | ||||
|
98 | .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html | |||
|
99 | .. [Sphinx] Sphinx. http://sphinx.pocoo.org/ | |||
|
100 | .. [MatplotlibDocGuide] http://matplotlib.sourceforge.net/devel/documenting_mpl.html | |||
|
101 | .. [PEP257] PEP 257. http://www.python.org/peps/pep-0257.html | |||
|
102 | .. [NumPyDocGuide] NumPy documentation guide. http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines | |||
|
103 | .. [NumPyExampleDocstring] NumPy example docstring. http://projects.scipy.org/numpy/browser/trunk/doc/EXAMPLE_DOCSTRING.txt | |||
|
104 |
@@ -1,25 +1,18 b'' | |||||
1 | .. _developer_guide: |
|
1 | .. _developer_guide: | |
2 |
|
2 | |||
3 | ========================= |
|
3 | ========================= | |
4 | IPython developer's guide |
|
4 | IPython developer's guide | |
5 | ========================= |
|
5 | ========================= | |
6 |
|
6 | |||
7 | .. toctree:: |
|
7 | .. toctree:: | |
8 |
:maxdepth: |
|
8 | :maxdepth: 1 | |
9 |
|
9 | |||
10 | contributing.txt |
|
10 | contributing.txt | |
11 | coding_guide.txt |
|
11 | coding_guide.txt | |
12 | doc_guide.txt |
|
12 | doc_guide.txt | |
13 | testing.txt |
|
13 | testing.txt | |
14 | release.txt |
|
14 | release.txt | |
15 | roadmap.txt |
|
15 | roadmap.txt | |
16 |
|
||||
17 | notification_blueprint.txt |
|
|||
18 | reorg.txt |
|
16 | reorg.txt | |
|
17 | notification_blueprint.txt | |||
19 |
|
18 | |||
20 |
|
||||
21 | .. [Bazaar] Bazaar. http://bazaar-vcs.org/ |
|
|||
22 | .. [Launchpad] Launchpad. http://www.launchpad.net/ipython |
|
|||
23 | .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html |
|
|||
24 | .. [Sphinx] Sphinx. http://sphinx.pocoo.org/ |
|
|||
25 | .. [Nose] Nose: a discovery based unittest extension. http://code.google.com/p/python-nose/ No newline at end of file |
|
@@ -1,25 +1,32 b'' | |||||
1 | Release checklist |
|
1 | .. _releasing_ipython: | |
|
2 | ||||
|
3 | ================= | |||
|
4 | Releasing IPython | |||
2 | ================= |
|
5 | ================= | |
3 |
|
6 | |||
|
7 | This section contains notes about the process that is used to release IPython. | |||
|
8 | Our release process is currently not very formal and could be improved. | |||
|
9 | ||||
4 | Most of the release process is automated by the :file:`release` script in the |
|
10 | Most of the release process is automated by the :file:`release` script in the | |
5 | :file:`tools` directory. This is just a handy reminder for the release manager. |
|
11 | :file:`tools` directory. This is just a handy reminder for the release manager. | |
6 |
|
12 | |||
7 | #. First, run :file:`build_release`, which does all the file checking and |
|
13 | #. First, run :file:`build_release`, which does all the file checking and | |
8 | building that the real release script will do. This will let you do test |
|
14 | building that the real release script will do. This will let you do test | |
9 | installations, check that the build procedure runs OK, etc. You may want to |
|
15 | installations, check that the build procedure runs OK, etc. You may want to | |
10 | disable a few things like multi-version RPM building while testing, because |
|
16 | disable a few things like multi-version RPM building while testing, because | |
11 | otherwise the build takes really long. |
|
17 | otherwise the build takes really long. | |
12 |
|
18 | |||
13 | #. Run the release script, which makes the tar.gz, eggs and Win32 .exe |
|
19 | #. Run the release script, which makes the tar.gz, eggs and Win32 .exe | |
14 | installer. It posts them to the site and registers the release with PyPI. |
|
20 | installer. It posts them to the site and registers the release with PyPI. | |
15 |
|
21 | |||
16 |
#. Updat |
|
22 | #. Update the website with announcements and links to the updated changes.txt | |
17 |
|
|
23 | in html form. Remember to put a short note both on the news page of the | |
18 |
|
|
24 | site and on Launcphad. | |
19 |
|
25 | |||
20 | #. Drafting a short release announcement with i) highlights and ii) a link to |
|
26 | #. Drafting a short release announcement with i) highlights and ii) a link to | |
21 | the html changes.txt. |
|
27 | the html version of the :ref:`Whats new <whatsnew_index>` section of the | |
|
28 | documentation. | |||
22 |
|
29 | |||
23 | #. Make sure that the released version of the docs is live on the site. |
|
30 | #. Make sure that the released version of the docs is live on the site. | |
24 |
|
31 | |||
25 | #. Celebrate! No newline at end of file |
|
32 | #. Celebrate! |
@@ -1,85 +1,64 b'' | |||||
1 | ============================= |
|
1 | .. _module_reorg: | |
2 | IPython module reorganization |
|
|||
3 | ============================= |
|
|||
4 |
|
2 | |||
5 | Currently, IPython has many top-level modules that serve many different |
|
3 | =========================== | |
6 | purposes. The lack of organization make it very difficult for developers to |
|
4 | IPython module organization | |
7 | work on IPython and understand its design. This document contains notes about |
|
5 | =========================== | |
8 | how we will reorganize the modules into sub-packages. |
|
|||
9 |
|
6 | |||
10 | .. warning:: |
|
7 | As of the 0.11 release of IPython, the top-level packages and modules have | |
|
8 | been completely reorganized. This section describes the purpose of the | |||
|
9 | top-level IPython subpackages. | |||
11 |
|
10 | |||
12 | This effort will possibly break third party packages that use IPython as |
|
11 | Subpackage descriptions | |
13 | a library or hack on the IPython internals. |
|
12 | ======================= | |
14 |
|
13 | |||
15 | .. warning:: |
|
14 | * :mod:`IPython.config`. This package contains the configuration system of | |
|
15 | IPython, as well as default configuration files for the different IPython | |||
|
16 | applications. | |||
16 |
|
17 | |||
17 | This effort will result in the removal from IPython of certain modules |
|
18 | * :mod:`IPython.core`. This sub-package contains the core of the IPython | |
18 | that are not used anymore, don't currently work, are unmaintained, etc. |
|
19 | interpreter, but none of its extended capabilities. | |
19 |
|
||||
20 |
|
||||
21 | Current subpackges |
|
|||
22 | ================== |
|
|||
23 |
|
||||
24 | IPython currently has the following sub-packages: |
|
|||
25 |
|
||||
26 | * :mod:`IPython.config` |
|
|||
27 |
|
||||
28 | * :mod:`IPython.Extensions` |
|
|||
29 |
|
||||
30 | * :mod:`IPython.external` |
|
|||
31 |
|
||||
32 | * :mod:`IPython.frontend` |
|
|||
33 |
|
||||
34 | * :mod:`IPython.gui` |
|
|||
35 |
|
20 | |||
36 | * :mod:`IPython.kernel` |
|
21 | * :mod:`IPython.deathrow`. This is for code that is outdated, untested, | |
|
22 | rotting, or that belongs in a separate third party project. Eventually all | |||
|
23 | this code will either i) be revived by someone willing to maintain it with | |||
|
24 | tests and docs and re-included into IPython or 2) be removed from IPython | |||
|
25 | proper, but put into a separate third-party Python package. No new code will | |||
|
26 | be allowed here. | |||
37 |
|
27 | |||
38 | * :mod:`IPython.testing` |
|
28 | * :mod:`IPython.extensions`. This package contains fully supported IPython | |
|
29 | extensions. These extensions adhere to the official IPython extension API | |||
|
30 | and can be enabled by adding them to a field in the configuration file. | |||
39 |
|
31 | |||
40 | * :mod:`IPython.tests` |
|
32 | * :mod:`IPython.external`. This package contains third party packages and | |
|
33 | modules that IPython ships internally to reduce the number of dependencies. | |||
|
34 | Usually, these are short, single file modules. | |||
41 |
|
35 | |||
42 | * :mod:`IPython.tools` |
|
36 | * :mod:`IPython.frontend`. This package contains the various IPython | |
|
37 | frontends. Currently, the code in this subpackage is very experimental and | |||
|
38 | may be broken. | |||
43 |
|
39 | |||
44 | * :mod:`IPython.UserConfig` |
|
40 | * :mod:`IPython.gui`. Another semi-experimental wxPython based IPython GUI. | |
45 |
|
41 | |||
46 | New Subpackages to be created |
|
42 | * :mod:`IPython.kernel`. This contains IPython's parallel computing system. | |
47 | ============================= |
|
|||
48 |
|
43 | |||
49 | We propose to create the following new sub-packages: |
|
44 | * :mod:`IPython.lib`. IPython has many extended capabilities that are not part | |
|
45 | of the IPython core. These things will go here and in. Modules in this | |||
|
46 | package are similar to extensions, but don't adhere to the official | |||
|
47 | IPython extension API. | |||
50 |
|
48 | |||
51 |
* :mod:`IPython. |
|
49 | * :mod:`IPython.quarantine`. This is for code that doesn't meet IPython's | |
52 | interpreter, but none of its extended capabilities. |
|
50 | standards, but that we plan on keeping. To be moved out of this sub-package | |
|
51 | a module needs to have approval of the core IPython developers, tests and | |||
|
52 | documentation. | |||
53 |
|
53 | |||
54 | * :mod:`IPython.lib`. IPython has many extended capabilities that are not part |
|
54 | * :mod:`IPython.scripts`. This package contains a variety of top-level | |
55 | of the IPython core. These things will go here. |
|
55 | command line scripts. Eventually, these should be moved to the | |
|
56 | :file:`scripts` subdirectory of the appropriate IPython subpackage. | |||
56 |
|
57 | |||
57 | * :mod:`IPython.utils`. This sub-package will contain anything that might |
|
58 | * :mod:`IPython.utils`. This sub-package will contain anything that might | |
58 | eventually be found in the Python standard library, like things in |
|
59 | eventually be found in the Python standard library, like things in | |
59 | :mod:`genutils`. Each sub-module in this sub-package should contain |
|
60 | :mod:`genutils`. Each sub-module in this sub-package should contain | |
60 |
functions and classes that serve a single purpose |
|
61 | functions and classes that serve a single purpose and that don't | |
61 |
|
62 | depend on things in the rest of IPython. | ||
62 | * :mod:`IPython.deathrow`. This is for code that is untested and/or rotting |
|
|||
63 | and needs to be removed from IPython. Eventually all this code will either |
|
|||
64 | i) be revived by someone willing to maintain it with tests and docs and |
|
|||
65 | re-included into IPython or 2) be removed from IPython proper, but put into |
|
|||
66 | a separate top-level (not IPython) package that we keep around. No new code |
|
|||
67 | will be allowed here. |
|
|||
68 |
|
||||
69 | * :mod:`IPython.quarantine`. This is for code that doesn't meet IPython's |
|
|||
70 | standards, but that we plan on keeping. To be moved out of this sub-package |
|
|||
71 | a module needs to have a maintainer, tests and documentation. |
|
|||
72 |
|
||||
73 | Procedure |
|
|||
74 | ========= |
|
|||
75 |
|
||||
76 | 1. Move the file to its new location with its new name. |
|
|||
77 | 2. Rename all import statements to reflect the change. |
|
|||
78 | 3. Run PyFlakes on each changes module. |
|
|||
79 | 4. Add tests/test_imports.py to test it. |
|
|||
80 |
|
||||
81 | Status |
|
|||
82 | ====== |
|
|||
83 |
|
63 | |||
84 | This branch was merged into trunk in early August of 2009. |
|
|||
85 |
|
64 |
@@ -1,114 +1,121 b'' | |||||
1 | .. _roadmap: |
|
1 | .. _roadmap: | |
2 |
|
2 | |||
3 | =================== |
|
3 | =================== | |
4 | Development roadmap |
|
4 | Development roadmap | |
5 | =================== |
|
5 | =================== | |
6 |
|
6 | |||
7 | IPython is an ambitious project that is still under heavy development. |
|
7 | IPython is an ambitious project that is still under heavy development. | |
8 | However, we want IPython to become useful to as many people as possible, as |
|
8 | However, we want IPython to become useful to as many people as possible, as | |
9 | quickly as possible. To help us accomplish this, we are laying out a roadmap |
|
9 | quickly as possible. To help us accomplish this, we are laying out a roadmap | |
10 | of where we are headed and what needs to happen to get there. Hopefully, this |
|
10 | of where we are headed and what needs to happen to get there. Hopefully, this | |
11 | will help the IPython developers figure out the best things to work on for |
|
11 | will help the IPython developers figure out the best things to work on for | |
12 | each upcoming release. |
|
12 | each upcoming release. | |
13 |
|
13 | |||
14 | Work targeted to particular releases |
|
14 | Work targeted to particular releases | |
15 | ==================================== |
|
15 | ==================================== | |
16 |
|
16 | |||
17 | Release 0.11 |
|
17 | Release 0.11 | |
18 | ------------ |
|
18 | ------------ | |
19 |
|
19 | |||
20 | * Full module and package reorganization (done). |
|
20 | * Full module and package reorganization (done). | |
21 |
|
21 | |||
22 | * Removal of the threaded shells and new implementation of GUI support |
|
22 | * Removal of the threaded shells and new implementation of GUI support | |
23 | based on ``PyOSInputHook`` (done). |
|
23 | based on ``PyOSInputHook`` (done). | |
24 |
|
24 | |||
25 | * Refactor the configuration system (done). |
|
25 | * Refactor the configuration system (done). | |
26 |
|
26 | |||
27 | * Prepare to refactor IPython's core by creating a new component and |
|
27 | * Prepare to refactor IPython's core by creating a new component and | |
28 | application system (done). |
|
28 | application system (done). | |
29 |
|
29 | |||
30 | * Start to refactor IPython's core by turning everything into components |
|
30 | * Start to refactor IPython's core by turning everything into components | |
31 | (started). |
|
31 | (started). | |
32 |
|
32 | |||
33 | Release 0.12 |
|
33 | Release 0.12 | |
34 | ------------ |
|
34 | ------------ | |
35 |
|
35 | |||
36 | * Continue to refactor IPython's core by turning everything into components. |
|
36 | * Continue to refactor IPython's core by turning everything into components. | |
37 |
|
37 | |||
38 |
|
38 | |||
39 | Major areas of work |
|
39 | Major areas of work | |
40 | =================== |
|
40 | =================== | |
41 |
|
41 | |||
42 | Refactoring the main IPython core |
|
42 | Refactoring the main IPython core | |
43 | --------------------------------- |
|
43 | --------------------------------- | |
44 |
|
44 | |||
45 |
During the summer of 2009, we began refactoring IPython's core. |
|
45 | During the summer of 2009, we began refactoring IPython's core. The main | |
46 | thrust in this work was make the IPython core into a set of loosely coupled |
|
46 | thrust in this work was to make the IPython core into a set of loosely coupled | |
47 |
components. |
|
47 | components. The base component class for this is | |
48 |
:class:`IPython.core.component.Component`. |
|
48 | :class:`IPython.core.component.Component`. This section outlines the status of | |
49 |
|
|
49 | this work. | |
50 |
|
50 | |||
51 | Parts of the IPython core that have been turned into components: |
|
51 | Parts of the IPython core that have been turned into components: | |
52 |
|
52 | |||
53 | * The main :class:`InteractiveShell` class. |
|
53 | * The main :class:`~IPython.core.iplib.InteractiveShell` class. | |
54 |
* The aliases (:mod:`IPython.core.alias |
|
54 | * The aliases (:mod:`IPython.core.alias`). | |
55 | * The display and builtin traps (:mod:`IPython.core.display_trap` and |
|
55 | * The display and builtin traps (:mod:`IPython.core.display_trap` and | |
56 | :mod:`IPython.core.builtin_trap`). |
|
56 | :mod:`IPython.core.builtin_trap`). | |
57 | * The prefilter machinery (:mod:`IPython.core.prefilter`). |
|
57 | * The prefilter machinery (:mod:`IPython.core.prefilter`). | |
58 |
|
58 | |||
59 | Parts of the IPythoncore that need to be turned into components: |
|
59 | Parts of the IPythoncore that still need to be turned into components: | |
60 |
|
60 | |||
61 | * Magics. |
|
61 | * Magics. | |
62 | * Input and output history management. |
|
62 | * Input and output history management. | |
63 | * Prompts. |
|
63 | * Prompts. | |
64 |
* |
|
64 | * Tab completers. | |
65 | * Logging. |
|
65 | * Logging. | |
66 | * Exception handling. |
|
66 | * Exception handling. | |
67 | * Anything else. |
|
67 | * Anything else. | |
68 |
|
68 | |||
69 | Process management for :mod:`IPython.kernel` |
|
69 | Process management for :mod:`IPython.kernel` | |
70 | -------------------------------------------- |
|
70 | -------------------------------------------- | |
71 |
|
71 | |||
|
72 | A number of things need to be done to improve how processes are started | |||
|
73 | up and managed for the parallel computing side of IPython: | |||
|
74 | ||||
|
75 | * All of the processes need to use the new configuration system, components | |||
|
76 | and application. | |||
|
77 | * We need to add support for other batch systems. | |||
|
78 | ||||
72 | Performance problems |
|
79 | Performance problems | |
73 | -------------------- |
|
80 | -------------------- | |
74 |
|
81 | |||
75 | Currently, we have a number of performance issues in :mod:`IPython.kernel`: |
|
82 | Currently, we have a number of performance issues in :mod:`IPython.kernel`: | |
76 |
|
83 | |||
77 | * The controller stores a large amount of state in Python dictionaries. Under |
|
84 | * The controller stores a large amount of state in Python dictionaries. Under | |
78 | heavy usage, these dicts with get very large, causing memory usage problems. |
|
85 | heavy usage, these dicts with get very large, causing memory usage problems. | |
79 | We need to develop more scalable solutions to this problem. This will also |
|
86 | We need to develop more scalable solutions to this problem. This will also | |
80 | help the controller to be more fault tolerant. |
|
87 | help the controller to be more fault tolerant. | |
81 |
|
88 | |||
82 | * We currently don't have a good way of handling large objects in the |
|
89 | * We currently don't have a good way of handling large objects in the | |
83 | controller. The biggest problem is that because we don't have any way of |
|
90 | controller. The biggest problem is that because we don't have any way of | |
84 | streaming objects, we get lots of temporary copies in the low-level buffers. |
|
91 | streaming objects, we get lots of temporary copies in the low-level buffers. | |
85 | We need to implement a better serialization approach and true streaming |
|
92 | We need to implement a better serialization approach and true streaming | |
86 | support. |
|
93 | support. | |
87 |
|
94 | |||
88 | * The controller currently unpickles and repickles objects. We need to use the |
|
95 | * The controller currently unpickles and repickles objects. We need to use the | |
89 | [push|pull]_serialized methods instead. |
|
96 | [push|pull]_serialized methods instead. | |
90 |
|
97 | |||
91 | * Currently the controller is a bottleneck. The best approach for this is to |
|
98 | * Currently the controller is a bottleneck. The best approach for this is to | |
92 | separate the controller itself into multiple processes, one for the core |
|
99 | separate the controller itself into multiple processes, one for the core | |
93 | controller and one each for the controller interfaces. |
|
100 | controller and one each for the controller interfaces. | |
94 |
|
101 | |||
95 | Porting to 3.0 |
|
102 | Porting to 3.0 | |
96 | ============== |
|
103 | ============== | |
97 |
|
104 | |||
98 | There are no definite plans for porting of IPython to Python 3. The major |
|
105 | There are no definite plans for porting of IPython to Python 3. The major | |
99 | issue is the dependency on Twisted framework for the networking/threading |
|
106 | issue is the dependency on Twisted framework for the networking/threading | |
100 | stuff. It is possible that it the traditional IPython interactive console |
|
107 | stuff. It is possible that it the traditional IPython interactive console | |
101 | could be ported more easily since it has no such dependency. Here are a few |
|
108 | could be ported more easily since it has no such dependency. Here are a few | |
102 | things that will need to be considered when doing such a port especially |
|
109 | things that will need to be considered when doing such a port especially | |
103 | if we want to have a codebase that works directly on both 2.x and 3.x. |
|
110 | if we want to have a codebase that works directly on both 2.x and 3.x. | |
104 |
|
111 | |||
105 | 1. The syntax for exceptions changed (PEP 3110). The old `except exc, var` |
|
112 | 1. The syntax for exceptions changed (PEP 3110). The old `except exc, var` | |
106 | changed to `except exc as var`. At last count there was 78 occurrences of this |
|
113 | changed to `except exc as var`. At last count there was 78 occurrences of this | |
107 | usage in the code base. This is a particularly problematic issue, because it's |
|
114 | usage in the code base. This is a particularly problematic issue, because it's | |
108 | not easy to implement it in a 2.5-compatible way. |
|
115 | not easy to implement it in a 2.5-compatible way. | |
109 |
|
116 | |||
110 | Because it is quite difficult to support simultaneously Python 2.5 and 3.x, we |
|
117 | Because it is quite difficult to support simultaneously Python 2.5 and 3.x, we | |
111 | will likely at some point put out a release that requires strictly 2.6 and |
|
118 | will likely at some point put out a release that requires strictly 2.6 and | |
112 | abandons 2.5 compatibility. This will then allow us to port the code to using |
|
119 | abandons 2.5 compatibility. This will then allow us to port the code to using | |
113 | :func:`print` as a function, `except exc as var` syntax, etc. But as of |
|
120 | :func:`print` as a function, `except exc as var` syntax, etc. But as of | |
114 | version 0.11 at least, we will retain Python 2.5 compatibility. |
|
121 | version 0.11 at least, we will retain Python 2.5 compatibility. |
@@ -1,194 +1,54 b'' | |||||
1 | .. _testing: |
|
1 | .. _testing: | |
2 |
|
2 | |||
3 | ========================= |
|
3 | ========================= | |
4 | Writing and running tests |
|
4 | Writing and running tests | |
5 | ========================= |
|
5 | ========================= | |
6 |
|
6 | |||
7 | Overview |
|
7 | Overview | |
8 | ======== |
|
8 | ======== | |
9 |
|
9 | |||
10 | It is extremely important that all code contributed to IPython has tests. |
|
10 | It is extremely important that all code contributed to IPython has tests. | |
11 | Tests should be written as unittests, doctests or other entities that the |
|
11 | Tests should be written as unittests, doctests or other entities that the | |
12 | IPython test system can detect. See below for more details on this. |
|
12 | IPython test system can detect. See below for more details on this. | |
13 |
|
13 | |||
14 | Each subpackage in IPython should have its own :file:`tests` directory that |
|
14 | Each subpackage in IPython should have its own :file:`tests` directory that | |
15 | contains all of the tests for that subpackage. All of the files in the |
|
15 | contains all of the tests for that subpackage. All of the files in the | |
16 | :file:`tests` directory should have the word "tests" in them to enable |
|
16 | :file:`tests` directory should have the word "tests" in them to enable | |
17 | the testing framework to find them. |
|
17 | the testing framework to find them. | |
18 |
|
18 | |||
19 | If a subpackage has any dependencies beyond the Python standard library, the |
|
19 | If a subpackage has any dependencies beyond the Python standard library, the | |
20 | tests for that subpackage should be skipped if the dependencies are not found. |
|
20 | tests for that subpackage should be skipped if the dependencies are not found. | |
21 | This is very important so users don't get tests failing simply because they |
|
21 | This is very important so users don't get tests failing simply because they | |
22 | don't have dependencies. We are still figuring out the best way for this |
|
22 | don't have dependencies. We are still figuring out the best way for this | |
23 | to be handled. |
|
23 | to be handled. | |
24 |
|
24 | |||
25 | Status |
|
25 | Status | |
26 | ====== |
|
26 | ====== | |
27 |
|
27 | |||
28 | Currently IPython's testing system is being reworked. In the meantime, |
|
28 | Currently IPython's testing system is being reworked. In the meantime, | |
29 | we recommend the following testing practices: |
|
29 | we recommend the following testing practices: | |
30 |
|
30 | |||
31 |
* To run regular tests, use the :cmd:`nosetests` command |
|
31 | * To run regular tests, use the :command:`nosetests` command that Nose [Nose]_ | |
|
32 | provides on a per file basis: | |||
32 |
|
33 | |||
33 | .. code-block:: bash |
|
34 | .. code-block:: bash | |
34 |
|
35 | |||
35 | nosetests -vvs IPython.core.tests.test_component |
|
36 | nosetests -vvs IPython.core.tests.test_component | |
36 |
|
37 | |||
37 | * To run Twisted-using tests, use the :cmd:`trial` command on a per file |
|
38 | * To run Twisted-using tests, use the :command:`trial` command on a per file | |
38 | basis: |
|
39 | basis: | |
39 |
|
40 | |||
40 | .. code-block:: bash |
|
41 | .. code-block:: bash | |
41 |
|
42 | |||
42 | trial IPython.kernel |
|
43 | trial IPython.kernel | |
43 |
|
44 | |||
44 | * For now, regular tests (of non-Twisted using code) should be written as |
|
45 | * For now, regular tests (of non-Twisted using code) should be written as | |
45 | unit tests. They should be subclasses of :class:`unittest.TestCase`. |
|
46 | unit tests. They should be subclasses of :class:`unittest.TestCase`. | |
46 |
|
47 | |||
47 | * Tests of Twisted [Twisted]_ using code should be written by subclassing the |
|
48 | * Tests of Twisted [Twisted]_ using code should be written by subclassing the | |
48 | ``TestCase`` class that comes with ``twisted.trial.unittest``. |
|
49 | ``TestCase`` class that comes with ``twisted.trial.unittest``. Furthermore, | |
49 |
|
50 | all :class:`Deferred` instances that are created in the test must be | ||
50 | .. _devel_testing: |
|
51 | properly chained and the final one *must* be the return value of the test | |
51 |
|
52 | method. | ||
52 | Older material |
|
|||
53 | ============== |
|
|||
54 |
|
||||
55 | It is extremely important that all code contributed to IPython has tests. |
|
|||
56 | Tests should be written as unittests, doctests or as entities that the Nose |
|
|||
57 | [Nose]_ testing package will find. Regardless of how the tests are written, we |
|
|||
58 | will use Nose for discovering and running the tests. Nose will be required to |
|
|||
59 | run the IPython test suite, but will not be required to simply use IPython. |
|
|||
60 |
|
||||
61 | Tests of Twisted using code need to follow two additional guidelines: |
|
|||
62 |
|
||||
63 | 1. Twisted using tests should be written by subclassing the :class:`TestCase` |
|
|||
64 | class that comes with :mod:`twisted.trial.unittest`. |
|
|||
65 |
|
||||
66 | 2. All :class:`Deferred` instances that are created in the test must be |
|
|||
67 | properly chained and the final one *must* be the return value of the test |
|
|||
68 | method. |
|
|||
69 |
|
||||
70 | When these two things are done, Nose will be able to run the tests and the |
|
|||
71 | twisted reactor will be handled correctly. |
|
|||
72 |
|
||||
73 | Each subpackage in IPython should have its own :file:`tests` directory that |
|
|||
74 | contains all of the tests for that subpackage. This allows each subpackage to |
|
|||
75 | be self-contained. A good convention to follow is to have a file named |
|
|||
76 | :file:`test_foo.py` for each module :file:`foo.py` in the package. This makes |
|
|||
77 | it easy to organize the tests, though like most conventions, it's OK to break |
|
|||
78 | it if logic and common sense dictate otherwise. |
|
|||
79 |
|
||||
80 | If a subpackage has any dependencies beyond the Python standard library, the |
|
|||
81 | tests for that subpackage should be skipped if the dependencies are not |
|
|||
82 | found. This is very important so users don't get tests failing simply because |
|
|||
83 | they don't have dependencies. We ship a set of decorators in the |
|
|||
84 | :mod:`IPython.testing` package to tag tests that may be platform-specific or |
|
|||
85 | otherwise may have restrictions; if the existing ones don't fit your needs, add |
|
|||
86 | a new decorator in that location so other tests can reuse it. |
|
|||
87 |
|
||||
88 | To run the IPython test suite, use the :command:`iptest` command that is |
|
|||
89 | installed with IPython (if you are using IPython in-place, without installing |
|
|||
90 | it, you can find this script in the :file:`scripts` directory):: |
|
|||
91 |
|
||||
92 | $ iptest |
|
|||
93 |
|
||||
94 | This command colects all IPython tests into separate groups, and then calls |
|
|||
95 | either Nose with the proper options and extensions, or Twisted's |
|
|||
96 | :command:`trial`. This ensures that tests that need the Twisted reactor |
|
|||
97 | management facilities execute separate of Nose. If any individual test group |
|
|||
98 | fails, :command:`iptest` will print what you need to type so you can rerun that |
|
|||
99 | particular test group alone for debugging. |
|
|||
100 |
|
||||
101 | By default, :command:`iptest` runs the entire IPython test |
|
|||
102 | suite (skipping tests that may be platform-specific or which depend on tools |
|
|||
103 | you may not have). But you can also use it to run only one specific test file, |
|
|||
104 | or a specific test function. For example, this will run only the |
|
|||
105 | :file:`test_magic` file from the test suite:: |
|
|||
106 |
|
||||
107 | $ iptest IPython.tests.test_magic |
|
|||
108 | ---------------------------------------------------------------------- |
|
|||
109 | Ran 10 tests in 0.348s |
|
|||
110 |
|
||||
111 | OK (SKIP=3) |
|
|||
112 | Deleting object: second_pass |
|
|||
113 |
|
||||
114 | while the ``path:function`` syntax allows you to select a specific function in |
|
|||
115 | that file to run:: |
|
|||
116 |
|
||||
117 | $ iptest IPython.tests.test_magic:test_obj_del |
|
|||
118 | ---------------------------------------------------------------------- |
|
|||
119 | Ran 1 test in 0.204s |
|
|||
120 |
|
||||
121 | OK |
|
|||
122 |
|
||||
123 | Since :command:`iptest` is based on nosetests, you can pass it any regular |
|
|||
124 | nosetests option. For example, you can use ``--pdb`` or ``--pdb-failures`` to |
|
|||
125 | automatically activate the interactive Pdb debugger on errors or failures. See |
|
|||
126 | the nosetests documentation for further details. |
|
|||
127 |
|
||||
128 |
|
||||
129 | A few tips for writing tests |
|
|||
130 | ---------------------------- |
|
|||
131 |
|
||||
132 | You can write tests either as normal test files, using all the conventions that |
|
|||
133 | Nose recognizes, or as doctests. Note that *all* IPython functions should have |
|
|||
134 | at least one example that serves as a doctest, whenever technically feasible. |
|
|||
135 | However, example doctests should only be in the main docstring if they are *a |
|
|||
136 | good example*, i.e. if they convey useful information about the function. If |
|
|||
137 | you simply would like to write a test as a doctest, put it in a separate test |
|
|||
138 | file and write a no-op function whose only purpose is its docstring. |
|
|||
139 |
|
||||
140 | Note, however, that in a file named :file:`test_X`, functions whose only test |
|
|||
141 | is their docstring (as a doctest) and which have no test functionality of their |
|
|||
142 | own, should be called *doctest_foo* instead of *test_foo*, otherwise they get |
|
|||
143 | double-counted (the empty function call is counted as a test, which just |
|
|||
144 | inflates tests numbers artificially). This restriction does not apply to |
|
|||
145 | functions in files with other names, due to how Nose discovers tests. |
|
|||
146 |
|
||||
147 | You can use IPython examples in your docstrings. Those can make full use of |
|
|||
148 | IPython functionality (magics, variable substitution, etc), but be careful to |
|
|||
149 | keep them generic enough that they run identically on all Operating Systems. |
|
|||
150 |
|
||||
151 | The prompts in your doctests can be either of the plain Python ``>>>`` variety |
|
|||
152 | or ``In [1]:`` IPython style. Since this is the IPython system, after all, we |
|
|||
153 | encourage you to use IPython prompts throughout, unless you are illustrating a |
|
|||
154 | specific aspect of the normal prompts (such as the ``%doctest_mode`` magic). |
|
|||
155 |
|
||||
156 | If a test isn't safe to run inside the main nose process (e.g. because it loads |
|
|||
157 | a GUI toolkit), consider running it in a subprocess and capturing its output |
|
|||
158 | for evaluation and test decision later. Here is an example of how to do it, by |
|
|||
159 | relying on the builtin ``_ip`` object that contains the public IPython api as |
|
|||
160 | defined in :mod:`IPython.ipapi`:: |
|
|||
161 |
|
||||
162 | def test_obj_del(): |
|
|||
163 | """Test that object's __del__ methods are called on exit.""" |
|
|||
164 | test_dir = os.path.dirname(__file__) |
|
|||
165 | del_file = os.path.join(test_dir,'obj_del.py') |
|
|||
166 | out = _ip.IP.getoutput('ipython %s' % del_file) |
|
|||
167 | nt.assert_equals(out,'object A deleted') |
|
|||
168 |
|
||||
169 |
|
||||
170 |
|
||||
171 | If a doctest contains input whose output you don't want to verify identically |
|
|||
172 | via doctest (random output, an object id, etc), you can mark a docstring with |
|
|||
173 | ``#random``. All of these test will have their code executed but no output |
|
|||
174 | checking will be done:: |
|
|||
175 |
|
||||
176 | >>> 1+3 |
|
|||
177 | junk goes here... # random |
|
|||
178 |
|
||||
179 | >>> 1+2 |
|
|||
180 | again, anything goes #random |
|
|||
181 | if multiline, the random mark is only needed once. |
|
|||
182 |
|
||||
183 | >>> 1+2 |
|
|||
184 | You can also put the random marker at the end: |
|
|||
185 | # random |
|
|||
186 |
|
||||
187 | >>> 1+2 |
|
|||
188 | # random |
|
|||
189 | .. or at the beginning. |
|
|||
190 |
|
||||
191 | In a case where you want an *entire* docstring to be executed but not verified |
|
|||
192 | (this only serves to check that the code runs without crashing, so it should be |
|
|||
193 | used very sparingly), you can put ``# all-random`` in the docstring. |
|
|||
194 |
|
53 | |||
|
54 | .. [Nose] Nose: a discovery based unittest extension. http://code.google.com/p/python-nose/ |
@@ -1,328 +1,341 b'' | |||||
1 | Overview |
|
1 | Overview | |
2 | ======== |
|
2 | ======== | |
3 |
|
3 | |||
4 | This document describes the steps required to install IPython. IPython is |
|
4 | This document describes the steps required to install IPython. IPython is | |
5 | organized into a number of subpackages, each of which has its own dependencies. |
|
5 | organized into a number of subpackages, each of which has its own dependencies. | |
6 | All of the subpackages come with IPython, so you don't need to download and |
|
6 | All of the subpackages come with IPython, so you don't need to download and | |
7 | install them separately. However, to use a given subpackage, you will need to |
|
7 | install them separately. However, to use a given subpackage, you will need to | |
8 | install all of its dependencies. |
|
8 | install all of its dependencies. | |
9 |
|
9 | |||
10 |
|
10 | |||
11 | Please let us know if you have problems installing IPython or any of its |
|
11 | Please let us know if you have problems installing IPython or any of its | |
12 | dependencies. Officially, IPython requires Python version 2.5 or 2.6. We |
|
12 | dependencies. Officially, IPython requires Python version 2.5 or 2.6. We | |
13 | have *not* yet started to port IPython to Python 3.0. |
|
13 | have *not* yet started to port IPython to Python 3.0. | |
14 |
|
14 | |||
15 | .. warning:: |
|
15 | .. warning:: | |
16 |
|
16 | |||
17 | Officially, IPython supports Python versions 2.5 and 2.6. |
|
17 | Officially, IPython supports Python versions 2.5 and 2.6. | |
18 |
|
18 | |||
19 | IPython 0.10 has only been well tested with Python 2.5 and 2.6. Parts of |
|
19 | IPython 0.10 has only been well tested with Python 2.5 and 2.6. Parts of | |
20 | it may work with Python 2.4, but we do not officially support Python 2.4 |
|
20 | it may work with Python 2.4, but we do not officially support Python 2.4 | |
21 | anymore. If you need to use 2.4, you can still run IPython 0.9. |
|
21 | anymore. If you need to use 2.4, you can still run IPython 0.9. | |
22 |
|
22 | |||
23 | Some of the installation approaches use the :mod:`setuptools` package and its |
|
23 | Some of the installation approaches use the :mod:`setuptools` package and its | |
24 | :command:`easy_install` command line program. In many scenarios, this provides |
|
24 | :command:`easy_install` command line program. In many scenarios, this provides | |
25 | the most simple method of installing IPython and its dependencies. It is not |
|
25 | the most simple method of installing IPython and its dependencies. It is not | |
26 | required though. More information about :mod:`setuptools` can be found on its |
|
26 | required though. More information about :mod:`setuptools` can be found on its | |
27 | website. |
|
27 | website. | |
28 |
|
28 | |||
29 | More general information about installing Python packages can be found in |
|
29 | More general information about installing Python packages can be found in | |
30 | Python's documentation at http://www.python.org/doc/. |
|
30 | Python's documentation at http://www.python.org/doc/. | |
31 |
|
31 | |||
32 | Quickstart |
|
32 | Quickstart | |
33 | ========== |
|
33 | ========== | |
34 |
|
34 | |||
35 | If you have :mod:`setuptools` installed and you are on OS X or Linux (not |
|
35 | If you have :mod:`setuptools` installed and you are on OS X or Linux (not | |
36 | Windows), the following will download and install IPython *and* the main |
|
36 | Windows), the following will download and install IPython *and* the main | |
37 | optional dependencies: |
|
37 | optional dependencies: | |
38 |
|
38 | |||
39 | .. code-block:: bash |
|
39 | .. code-block:: bash | |
40 |
|
40 | |||
41 | easy_install ipython[kernel,security,test] |
|
41 | $ easy_install ipython[kernel,security,test] | |
42 |
|
42 | |||
43 | This will get Twisted, zope.interface and Foolscap, which are needed for |
|
43 | This will get Twisted, zope.interface and Foolscap, which are needed for | |
44 | IPython's parallel computing features as well as the nose package, which will |
|
44 | IPython's parallel computing features as well as the nose package, which will | |
45 |
enable you to run IPython's test suite. |
|
45 | enable you to run IPython's test suite. | |
46 | :command:`iptest` command: |
|
46 | ||
|
47 | .. warning:: | |||
|
48 | ||||
|
49 | IPython's test system is being refactored and currently the | |||
|
50 | :command:`iptest` shown below does not work. More details about the | |||
|
51 | testing situation can be found :ref:`here <testing>` | |||
|
52 | ||||
|
53 | To run IPython's test suite, use the :command:`iptest` command: | |||
47 |
|
54 | |||
48 | .. code-block:: bash |
|
55 | .. code-block:: bash | |
49 |
|
56 | |||
50 | iptest |
|
57 | $ iptest | |
51 |
|
58 | |||
52 | Read on for more specific details and instructions for Windows. |
|
59 | Read on for more specific details and instructions for Windows. | |
53 |
|
60 | |||
54 | Installing IPython itself |
|
61 | Installing IPython itself | |
55 | ========================= |
|
62 | ========================= | |
56 |
|
63 | |||
57 | Given a properly built Python, the basic interactive IPython shell will work |
|
64 | Given a properly built Python, the basic interactive IPython shell will work | |
58 | with no external dependencies. However, some Python distributions |
|
65 | with no external dependencies. However, some Python distributions | |
59 | (particularly on Windows and OS X), don't come with a working :mod:`readline` |
|
66 | (particularly on Windows and OS X), don't come with a working :mod:`readline` | |
60 | module. The IPython shell will work without :mod:`readline`, but will lack |
|
67 | module. The IPython shell will work without :mod:`readline`, but will lack | |
61 | many features that users depend on, such as tab completion and command line |
|
68 | many features that users depend on, such as tab completion and command line | |
62 | editing. See below for details of how to make sure you have a working |
|
69 | editing. See below for details of how to make sure you have a working | |
63 | :mod:`readline`. |
|
70 | :mod:`readline`. | |
64 |
|
71 | |||
65 | Installation using easy_install |
|
72 | Installation using easy_install | |
66 | ------------------------------- |
|
73 | ------------------------------- | |
67 |
|
74 | |||
68 | If you have :mod:`setuptools` installed, the easiest way of getting IPython is |
|
75 | If you have :mod:`setuptools` installed, the easiest way of getting IPython is | |
69 | to simple use :command:`easy_install`: |
|
76 | to simple use :command:`easy_install`: | |
70 |
|
77 | |||
71 | .. code-block:: bash |
|
78 | .. code-block:: bash | |
72 |
|
79 | |||
73 | easy_install ipython |
|
80 | $ easy_install ipython | |
74 |
|
81 | |||
75 | That's it. |
|
82 | That's it. | |
76 |
|
83 | |||
77 | Installation from source |
|
84 | Installation from source | |
78 | ------------------------ |
|
85 | ------------------------ | |
79 |
|
86 | |||
80 | If you don't want to use :command:`easy_install`, or don't have it installed, |
|
87 | If you don't want to use :command:`easy_install`, or don't have it installed, | |
81 | just grab the latest stable build of IPython from `here |
|
88 | just grab the latest stable build of IPython from `here | |
82 | <http://ipython.scipy.org/dist/>`_. Then do the following: |
|
89 | <http://ipython.scipy.org/dist/>`_. Then do the following: | |
83 |
|
90 | |||
84 | .. code-block:: bash |
|
91 | .. code-block:: bash | |
85 |
|
92 | |||
86 | tar -xzf ipython.tar.gz |
|
93 | $ tar -xzf ipython.tar.gz | |
87 | cd ipython |
|
94 | $ cd ipython | |
88 | python setup.py install |
|
95 | $ python setup.py install | |
89 |
|
96 | |||
90 | If you are installing to a location (like ``/usr/local``) that requires higher |
|
97 | If you are installing to a location (like ``/usr/local``) that requires higher | |
91 | permissions, you may need to run the last command with :command:`sudo`. |
|
98 | permissions, you may need to run the last command with :command:`sudo`. | |
92 |
|
99 | |||
93 | Windows |
|
100 | Windows | |
94 | ------- |
|
101 | ------- | |
95 |
|
102 | |||
96 | There are a few caveats for Windows users. The main issue is that a basic |
|
103 | There are a few caveats for Windows users. The main issue is that a basic | |
97 | ``python setup.py install`` approach won't create ``.bat`` file or Start Menu |
|
104 | ``python setup.py install`` approach won't create ``.bat`` file or Start Menu | |
98 | shortcuts, which most users want. To get an installation with these, you can |
|
105 | shortcuts, which most users want. To get an installation with these, you can | |
99 | use any of the following alternatives: |
|
106 | use any of the following alternatives: | |
100 |
|
107 | |||
101 | 1. Install using :command:`easy_install`. |
|
108 | 1. Install using :command:`easy_install`. | |
102 |
|
109 | |||
103 | 2. Install using our binary ``.exe`` Windows installer, which can be found at |
|
110 | 2. Install using our binary ``.exe`` Windows installer, which can be found at | |
104 | `here <http://ipython.scipy.org/dist/>`_ |
|
111 | `here <http://ipython.scipy.org/dist/>`_ | |
105 |
|
112 | |||
106 | 3. Install from source, but using :mod:`setuptools` (``python setupegg.py |
|
113 | 3. Install from source, but using :mod:`setuptools` (``python setupegg.py | |
107 | install``). |
|
114 | install``). | |
108 |
|
115 | |||
109 | IPython by default runs in a terminal window, but the normal terminal |
|
116 | IPython by default runs in a terminal window, but the normal terminal | |
110 | application supplied by Microsoft Windows is very primitive. You may want to |
|
117 | application supplied by Microsoft Windows is very primitive. You may want to | |
111 | download the excellent and free Console_ application instead, which is a far |
|
118 | download the excellent and free Console_ application instead, which is a far | |
112 | superior tool. You can even configure Console to give you by default an |
|
119 | superior tool. You can even configure Console to give you by default an | |
113 | IPython tab, which is very convenient to create new IPython sessions directly |
|
120 | IPython tab, which is very convenient to create new IPython sessions directly | |
114 | from the working terminal. |
|
121 | from the working terminal. | |
115 |
|
122 | |||
116 | .. _Console: http://sourceforge.net/projects/console |
|
123 | .. _Console: http://sourceforge.net/projects/console | |
117 |
|
124 | |||
118 |
|
125 | |||
119 | Installing the development version |
|
126 | Installing the development version | |
120 | ---------------------------------- |
|
127 | ---------------------------------- | |
121 |
|
128 | |||
122 | It is also possible to install the development version of IPython from our |
|
129 | It is also possible to install the development version of IPython from our | |
123 | `Bazaar <http://bazaar-vcs.org/>`_ source code repository. To do this you will |
|
130 | `Bazaar <http://bazaar-vcs.org/>`_ source code repository. To do this you will | |
124 | need to have Bazaar installed on your system. Then just do: |
|
131 | need to have Bazaar installed on your system. Then just do: | |
125 |
|
132 | |||
126 | .. code-block:: bash |
|
133 | .. code-block:: bash | |
127 |
|
134 | |||
128 | bzr branch lp:ipython |
|
135 | $ bzr branch lp:ipython | |
129 | cd ipython |
|
136 | $ cd ipython | |
130 | python setup.py install |
|
137 | $ python setup.py install | |
131 |
|
138 | |||
132 | Again, this last step on Windows won't create ``.bat`` files or Start Menu |
|
139 | Again, this last step on Windows won't create ``.bat`` files or Start Menu | |
133 | shortcuts, so you will have to use one of the other approaches listed above. |
|
140 | shortcuts, so you will have to use one of the other approaches listed above. | |
134 |
|
141 | |||
135 | Some users want to be able to follow the development branch as it changes. If |
|
142 | Some users want to be able to follow the development branch as it changes. If | |
136 | you have :mod:`setuptools` installed, this is easy. Simply replace the last |
|
143 | you have :mod:`setuptools` installed, this is easy. Simply replace the last | |
137 | step by: |
|
144 | step by: | |
138 |
|
145 | |||
139 | .. code-block:: bash |
|
146 | .. code-block:: bash | |
140 |
|
147 | |||
141 | python setupegg.py develop |
|
148 | $ python setupegg.py develop | |
142 |
|
149 | |||
143 | This creates links in the right places and installs the command line script to |
|
150 | This creates links in the right places and installs the command line script to | |
144 | the appropriate places. Then, if you want to update your IPython at any time, |
|
151 | the appropriate places. Then, if you want to update your IPython at any time, | |
145 | just do: |
|
152 | just do: | |
146 |
|
153 | |||
147 | .. code-block:: bash |
|
154 | .. code-block:: bash | |
148 |
|
155 | |||
149 | bzr pull |
|
156 | $ bzr pull | |
150 |
|
157 | |||
151 | Basic optional dependencies |
|
158 | Basic optional dependencies | |
152 | =========================== |
|
159 | =========================== | |
153 |
|
160 | |||
154 | There are a number of basic optional dependencies that most users will want to |
|
161 | There are a number of basic optional dependencies that most users will want to | |
155 | get. These are: |
|
162 | get. These are: | |
156 |
|
163 | |||
157 | * readline (for command line editing, tab completion, etc.) |
|
164 | * readline (for command line editing, tab completion, etc.) | |
158 | * nose (to run the IPython test suite) |
|
165 | * nose (to run the IPython test suite) | |
159 | * pexpect (to use things like irunner) |
|
166 | * pexpect (to use things like irunner) | |
160 |
|
167 | |||
161 | If you are comfortable installing these things yourself, have at it, otherwise |
|
168 | If you are comfortable installing these things yourself, have at it, otherwise | |
162 | read on for more details. |
|
169 | read on for more details. | |
163 |
|
170 | |||
164 | readline |
|
171 | readline | |
165 | -------- |
|
172 | -------- | |
166 |
|
173 | |||
167 | In principle, all Python distributions should come with a working |
|
174 | In principle, all Python distributions should come with a working | |
168 | :mod:`readline` module. But, reality is not quite that simple. There are two |
|
175 | :mod:`readline` module. But, reality is not quite that simple. There are two | |
169 | common situations where you won't have a working :mod:`readline` module: |
|
176 | common situations where you won't have a working :mod:`readline` module: | |
170 |
|
177 | |||
171 | * If you are using the built-in Python on Mac OS X. |
|
178 | * If you are using the built-in Python on Mac OS X. | |
172 |
|
179 | |||
173 | * If you are running Windows, which doesn't have a :mod:`readline` module. |
|
180 | * If you are running Windows, which doesn't have a :mod:`readline` module. | |
174 |
|
181 | |||
175 | On OS X, the built-in Python doesn't not have :mod:`readline` because of |
|
182 | On OS X, the built-in Python doesn't not have :mod:`readline` because of | |
176 | license issues. Starting with OS X 10.5 (Leopard), Apple's built-in Python has |
|
183 | license issues. Starting with OS X 10.5 (Leopard), Apple's built-in Python has | |
177 | a BSD-licensed not-quite-compatible readline replacement. As of IPython 0.9, |
|
184 | a BSD-licensed not-quite-compatible readline replacement. As of IPython 0.9, | |
178 | many of the issues related to the differences between readline and libedit have |
|
185 | many of the issues related to the differences between readline and libedit have | |
179 | been resolved. For many users, libedit may be sufficient. |
|
186 | been resolved. For many users, libedit may be sufficient. | |
180 |
|
187 | |||
181 | Most users on OS X will want to get the full :mod:`readline` module. To get a |
|
188 | Most users on OS X will want to get the full :mod:`readline` module. To get a | |
182 | working :mod:`readline` module, just do (with :mod:`setuptools` installed): |
|
189 | working :mod:`readline` module, just do (with :mod:`setuptools` installed): | |
183 |
|
190 | |||
184 | .. code-block:: bash |
|
191 | .. code-block:: bash | |
185 |
|
192 | |||
186 | easy_install readline |
|
193 | $ easy_install readline | |
187 |
|
194 | |||
188 | .. note: |
|
195 | .. note:: | |
189 |
|
196 | |||
190 | Other Python distributions on OS X (such as fink, MacPorts and the |
|
197 | Other Python distributions on OS X (such as fink, MacPorts and the | |
191 | official python.org binaries) already have readline installed so |
|
198 | official python.org binaries) already have readline installed so | |
192 | you don't have to do this step. |
|
199 | you don't have to do this step. | |
193 |
|
200 | |||
194 | If needed, the readline egg can be build and installed from source (see the |
|
201 | If needed, the readline egg can be build and installed from source (see the | |
195 | wiki page at http://ipython.scipy.org/moin/InstallationOSXLeopard). |
|
202 | wiki page at http://ipython.scipy.org/moin/InstallationOSXLeopard). | |
196 |
|
203 | |||
197 | On Windows, you will need the PyReadline module. PyReadline is a separate, |
|
204 | On Windows, you will need the PyReadline module. PyReadline is a separate, | |
198 | Windows only implementation of readline that uses native Windows calls through |
|
205 | Windows only implementation of readline that uses native Windows calls through | |
199 | :mod:`ctypes`. The easiest way of installing PyReadline is you use the binary |
|
206 | :mod:`ctypes`. The easiest way of installing PyReadline is you use the binary | |
200 | installer available `here <http://ipython.scipy.org/dist/>`_. The :mod:`ctypes` |
|
207 | installer available `here <http://ipython.scipy.org/dist/>`_. The :mod:`ctypes` | |
201 | module, which comes with Python 2.5 and greater, is required by PyReadline. It |
|
208 | module, which comes with Python 2.5 and greater, is required by PyReadline. It | |
202 | is available for Python 2.4 at http://python.net/crew/theller/ctypes. |
|
209 | is available for Python 2.4 at http://python.net/crew/theller/ctypes. | |
203 |
|
210 | |||
204 | nose |
|
211 | nose | |
205 | ---- |
|
212 | ---- | |
206 |
|
213 | |||
207 | To run the IPython test suite you will need the :mod:`nose` package. Nose |
|
214 | To run the IPython test suite you will need the :mod:`nose` package. Nose | |
208 | provides a great way of sniffing out and running all of the IPython tests. The |
|
215 | provides a great way of sniffing out and running all of the IPython tests. The | |
209 | simplest way of getting nose, is to use :command:`easy_install`: |
|
216 | simplest way of getting nose, is to use :command:`easy_install`: | |
210 |
|
217 | |||
211 | .. code-block:: bash |
|
218 | .. code-block:: bash | |
212 |
|
219 | |||
213 | easy_install nose |
|
220 | $ easy_install nose | |
214 |
|
221 | |||
215 | Another way of getting this is to do: |
|
222 | Another way of getting this is to do: | |
216 |
|
223 | |||
217 | .. code-block:: bash |
|
224 | .. code-block:: bash | |
218 |
|
225 | |||
219 | easy_install ipython[test] |
|
226 | $ easy_install ipython[test] | |
220 |
|
227 | |||
221 | For more installation options, see the `nose website |
|
228 | For more installation options, see the `nose website | |
222 |
<http://somethingaboutorange.com/mrl/projects/nose/>`_. |
|
229 | <http://somethingaboutorange.com/mrl/projects/nose/>`_. | |
223 | installed, you can run IPython's test suite using the iptest command: |
|
230 | ||
|
231 | .. warning:: | |||
|
232 | ||||
|
233 | As described above, the :command:`iptest` command currently doesn't work. | |||
|
234 | ||||
|
235 | Once you have nose installed, you can run IPython's test suite using the | |||
|
236 | iptest command: | |||
224 |
|
237 | |||
225 | .. code-block:: bash |
|
238 | .. code-block:: bash | |
226 |
|
239 | |||
227 | iptest |
|
240 | $ iptest | |
228 |
|
241 | |||
229 | pexpect |
|
242 | pexpect | |
230 | ------- |
|
243 | ------- | |
231 |
|
244 | |||
232 | The `pexpect <http://www.noah.org/wiki/Pexpect>`_ package is used in IPython's |
|
245 | The `pexpect <http://www.noah.org/wiki/Pexpect>`_ package is used in IPython's | |
233 | :command:`irunner` script. On Unix platforms (including OS X), just do: |
|
246 | :command:`irunner` script. On Unix platforms (including OS X), just do: | |
234 |
|
247 | |||
235 | .. code-block:: bash |
|
248 | .. code-block:: bash | |
236 |
|
249 | |||
237 | easy_install pexpect |
|
250 | $ easy_install pexpect | |
238 |
|
251 | |||
239 | Windows users are out of luck as pexpect does not run there. |
|
252 | Windows users are out of luck as pexpect does not run there. | |
240 |
|
253 | |||
241 | Dependencies for IPython.kernel (parallel computing) |
|
254 | Dependencies for IPython.kernel (parallel computing) | |
242 | ==================================================== |
|
255 | ==================================================== | |
243 |
|
256 | |||
244 | The IPython kernel provides a nice architecture for parallel computing. The |
|
257 | The IPython kernel provides a nice architecture for parallel computing. The | |
245 | main focus of this architecture is on interactive parallel computing. These |
|
258 | main focus of this architecture is on interactive parallel computing. These | |
246 | features require a number of additional packages: |
|
259 | features require a number of additional packages: | |
247 |
|
260 | |||
248 | * zope.interface (yep, we use interfaces) |
|
261 | * zope.interface (yep, we use interfaces) | |
249 | * Twisted (asynchronous networking framework) |
|
262 | * Twisted (asynchronous networking framework) | |
250 | * Foolscap (a nice, secure network protocol) |
|
263 | * Foolscap (a nice, secure network protocol) | |
251 | * pyOpenSSL (security for network connections) |
|
264 | * pyOpenSSL (security for network connections) | |
252 |
|
265 | |||
253 | On a Unix style platform (including OS X), if you want to use |
|
266 | On a Unix style platform (including OS X), if you want to use | |
254 | :mod:`setuptools`, you can just do: |
|
267 | :mod:`setuptools`, you can just do: | |
255 |
|
268 | |||
256 | .. code-block:: bash |
|
269 | .. code-block:: bash | |
257 |
|
270 | |||
258 | easy_install ipython[kernel] # the first three |
|
271 | $ easy_install ipython[kernel] # the first three | |
259 | easy_install ipython[security] # pyOpenSSL |
|
272 | $ easy_install ipython[security] # pyOpenSSL | |
260 |
|
273 | |||
261 | zope.interface and Twisted |
|
274 | zope.interface and Twisted | |
262 | -------------------------- |
|
275 | -------------------------- | |
263 |
|
276 | |||
264 | Twisted [Twisted]_ and zope.interface [ZopeInterface]_ are used for networking |
|
277 | Twisted [Twisted]_ and zope.interface [ZopeInterface]_ are used for networking | |
265 | related things. On Unix style platforms (including OS X), the simplest way of |
|
278 | related things. On Unix style platforms (including OS X), the simplest way of | |
266 | getting the these is to use :command:`easy_install`: |
|
279 | getting the these is to use :command:`easy_install`: | |
267 |
|
280 | |||
268 | .. code-block:: bash |
|
281 | .. code-block:: bash | |
269 |
|
282 | |||
270 | easy_install zope.interface |
|
283 | $ easy_install zope.interface | |
271 | easy_install Twisted |
|
284 | $ easy_install Twisted | |
272 |
|
285 | |||
273 | Of course, you can also download the source tarballs from the Twisted website |
|
286 | Of course, you can also download the source tarballs from the Twisted website | |
274 | [Twisted]_ and the `zope.interface page at PyPI |
|
287 | [Twisted]_ and the | |
275 |
<http://pypi.python.org/pypi/zope.interface>`_ |
|
288 | `zope.interface page at PyPI <http://pypi.python.org/pypi/zope.interface>`_ | |
276 | setup.py install`` if you prefer. |
|
289 | and do the usual ``python setup.py install`` if you prefer. | |
277 |
|
290 | |||
278 | Windows is a bit different. For zope.interface and Twisted, simply get the |
|
291 | Windows is a bit different. For zope.interface and Twisted, simply get the | |
279 | latest binary ``.exe`` installer from the Twisted website. This installer |
|
292 | latest binary ``.exe`` installer from the Twisted website. This installer | |
280 | includes both zope.interface and Twisted and should just work. |
|
293 | includes both zope.interface and Twisted and should just work. | |
281 |
|
294 | |||
282 | Foolscap |
|
295 | Foolscap | |
283 | -------- |
|
296 | -------- | |
284 |
|
297 | |||
285 | Foolscap [Foolscap]_ uses Twisted to provide a very nice secure RPC protocol that we use to implement our parallel computing features. |
|
298 | Foolscap [Foolscap]_ uses Twisted to provide a very nice secure RPC protocol that we use to implement our parallel computing features. | |
286 |
|
299 | |||
287 | On all platforms a simple: |
|
300 | On all platforms a simple: | |
288 |
|
301 | |||
289 | .. code-block:: bash |
|
302 | .. code-block:: bash | |
290 |
|
303 | |||
291 | easy_install foolscap |
|
304 | $ easy_install foolscap | |
292 |
|
305 | |||
293 | should work. You can also download the source tarballs from the `Foolscap |
|
306 | should work. You can also download the source tarballs from the `Foolscap | |
294 | website <http://foolscap.lothar.com/trac>`_ and do ``python setup.py install`` |
|
307 | website <http://foolscap.lothar.com/trac>`_ and do ``python setup.py install`` | |
295 | if you prefer. |
|
308 | if you prefer. | |
296 |
|
309 | |||
297 | pyOpenSSL |
|
310 | pyOpenSSL | |
298 | --------- |
|
311 | --------- | |
299 |
|
312 | |||
300 | IPython does not work with version 0.7 of pyOpenSSL [pyOpenSSL]_. It is known |
|
313 | IPython does not work with version 0.7 of pyOpenSSL [pyOpenSSL]_. It is known | |
301 | to work with version 0.6 and will likely work with the more recent 0.8 and 0.9 |
|
314 | to work with version 0.6 and will likely work with the more recent 0.8 and 0.9 | |
302 | versions. There are a couple of options for getting this: |
|
315 | versions. There are a couple of options for getting this: | |
303 |
|
316 | |||
304 | 1. Most Linux distributions have packages for pyOpenSSL. |
|
317 | 1. Most Linux distributions have packages for pyOpenSSL. | |
305 | 2. The built-in Python 2.5 on OS X 10.5 already has it installed. |
|
318 | 2. The built-in Python 2.5 on OS X 10.5 already has it installed. | |
306 | 3. There are source tarballs on the pyOpenSSL website. On Unix-like |
|
319 | 3. There are source tarballs on the pyOpenSSL website. On Unix-like | |
307 | platforms, these can be built using ``python seutp.py install``. |
|
320 | platforms, these can be built using ``python seutp.py install``. | |
308 | 4. There is also a binary ``.exe`` Windows installer on the |
|
321 | 4. There is also a binary ``.exe`` Windows installer on the | |
309 | `pyOpenSSL website <http://pyopenssl.sourceforge.net/>`_. |
|
322 | `pyOpenSSL website <http://pyopenssl.sourceforge.net/>`_. | |
310 |
|
323 | |||
311 | Dependencies for IPython.frontend (the IPython GUI) |
|
324 | Dependencies for IPython.frontend (the IPython GUI) | |
312 | =================================================== |
|
325 | =================================================== | |
313 |
|
326 | |||
314 | wxPython |
|
327 | wxPython | |
315 | -------- |
|
328 | -------- | |
316 |
|
329 | |||
317 | Starting with IPython 0.9, IPython has a new :mod:`IPython.frontend` package |
|
330 | Starting with IPython 0.9, IPython has a new :mod:`IPython.frontend` package | |
318 | that has a nice wxPython based IPython GUI. As you would expect, this GUI |
|
331 | that has a nice wxPython based IPython GUI. As you would expect, this GUI | |
319 | requires wxPython. Most Linux distributions have wxPython packages available |
|
332 | requires wxPython. Most Linux distributions have wxPython packages available | |
320 | and the built-in Python on OS X comes with wxPython preinstalled. For Windows, |
|
333 | and the built-in Python on OS X comes with wxPython preinstalled. For Windows, | |
321 | a binary installer is available on the `wxPython website |
|
334 | a binary installer is available on the `wxPython website | |
322 | <http://www.wxpython.org/>`_. |
|
335 | <http://www.wxpython.org/>`_. | |
323 |
|
336 | |||
324 | .. [Twisted] Twisted matrix. http://twistedmatrix.org |
|
337 | .. [Twisted] Twisted matrix. http://twistedmatrix.org | |
325 | .. [ZopeInterface] http://pypi.python.org/pypi/zope.interface |
|
338 | .. [ZopeInterface] http://pypi.python.org/pypi/zope.interface | |
326 | .. [Foolscap] Foolscap network protocol. http://foolscap.lothar.com/trac |
|
339 | .. [Foolscap] Foolscap network protocol. http://foolscap.lothar.com/trac | |
327 | .. [pyOpenSSL] pyOpenSSL. http://pyopenssl.sourceforge.net |
|
340 | .. [pyOpenSSL] pyOpenSSL. http://pyopenssl.sourceforge.net | |
328 |
|
341 |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now