##// END OF EJS Templates
Merging upstream changes from trunk->module-reorg->inputhook.
Brian Granger -
r2176:50484ac5 merge
parent child Browse files
Show More
@@ -1,121 +1,121 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project."""
2 """Release data for the IPython project."""
3
3
4 #*****************************************************************************
4 #*****************************************************************************
5 # Copyright (C) 2008-2009 The IPython Development Team
5 # Copyright (C) 2008-2009 The IPython Development Team
6 # Copyright (C) 2001-2008 Fernando Perez <fperez@colorado.edu>
6 # Copyright (C) 2001-2008 Fernando Perez <fperez@colorado.edu>
7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
8 # <n8gray@caltech.edu>
8 # <n8gray@caltech.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 # Name of the package for release purposes. This is the name which labels
14 # Name of the package for release purposes. This is the name which labels
15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
16 name = 'ipython'
16 name = 'ipython'
17
17
18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
19 # the new substring. We have to avoid using either dashes or underscores,
19 # the new substring. We have to avoid using either dashes or underscores,
20 # because bdist_rpm does not accept dashes (an RPM) convention, and
20 # because bdist_rpm does not accept dashes (an RPM) convention, and
21 # bdist_deb does not accept underscores (a Debian convention).
21 # bdist_deb does not accept underscores (a Debian convention).
22
22
23 development = False # change this to False to do a release
23 development = True # change this to False to do a release
24 version_base = '0.10'
24 version_base = '0.11'
25 branch = 'ipython'
25 branch = 'ipython'
26 revision = '1188'
26 revision = '1205'
27
27
28 if development:
28 if development:
29 if branch == 'ipython':
29 if branch == 'ipython':
30 version = '%s.bzr.r%s' % (version_base, revision)
30 version = '%s.bzr.r%s' % (version_base, revision)
31 else:
31 else:
32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
33 else:
33 else:
34 version = version_base
34 version = version_base
35
35
36
36
37 description = "An interactive computing environment for Python"
37 description = "An interactive computing environment for Python"
38
38
39 long_description = \
39 long_description = \
40 """
40 """
41 The goal of IPython is to create a comprehensive environment for
41 The goal of IPython is to create a comprehensive environment for
42 interactive and exploratory computing. To support this goal, IPython
42 interactive and exploratory computing. To support this goal, IPython
43 has two main components:
43 has two main components:
44
44
45 * An enhanced interactive Python shell.
45 * An enhanced interactive Python shell.
46
46
47 * An architecture for interactive parallel computing.
47 * An architecture for interactive parallel computing.
48
48
49 The enhanced interactive Python shell has the following main features:
49 The enhanced interactive Python shell has the following main features:
50
50
51 * Comprehensive object introspection.
51 * Comprehensive object introspection.
52
52
53 * Input history, persistent across sessions.
53 * Input history, persistent across sessions.
54
54
55 * Caching of output results during a session with automatically generated
55 * Caching of output results during a session with automatically generated
56 references.
56 references.
57
57
58 * Readline based name completion.
58 * Readline based name completion.
59
59
60 * Extensible system of 'magic' commands for controlling the environment and
60 * Extensible system of 'magic' commands for controlling the environment and
61 performing many tasks related either to IPython or the operating system.
61 performing many tasks related either to IPython or the operating system.
62
62
63 * Configuration system with easy switching between different setups (simpler
63 * Configuration system with easy switching between different setups (simpler
64 than changing $PYTHONSTARTUP environment variables every time).
64 than changing $PYTHONSTARTUP environment variables every time).
65
65
66 * Session logging and reloading.
66 * Session logging and reloading.
67
67
68 * Extensible syntax processing for special purpose situations.
68 * Extensible syntax processing for special purpose situations.
69
69
70 * Access to the system shell with user-extensible alias system.
70 * Access to the system shell with user-extensible alias system.
71
71
72 * Easily embeddable in other Python programs and wxPython GUIs.
72 * Easily embeddable in other Python programs and wxPython GUIs.
73
73
74 * Integrated access to the pdb debugger and the Python profiler.
74 * Integrated access to the pdb debugger and the Python profiler.
75
75
76 The parallel computing architecture has the following main features:
76 The parallel computing architecture has the following main features:
77
77
78 * Quickly parallelize Python code from an interactive Python/IPython session.
78 * Quickly parallelize Python code from an interactive Python/IPython session.
79
79
80 * A flexible and dynamic process model that be deployed on anything from
80 * A flexible and dynamic process model that be deployed on anything from
81 multicore workstations to supercomputers.
81 multicore workstations to supercomputers.
82
82
83 * An architecture that supports many different styles of parallelism, from
83 * An architecture that supports many different styles of parallelism, from
84 message passing to task farming.
84 message passing to task farming.
85
85
86 * Both blocking and fully asynchronous interfaces.
86 * Both blocking and fully asynchronous interfaces.
87
87
88 * High level APIs that enable many things to be parallelized in a few lines
88 * High level APIs that enable many things to be parallelized in a few lines
89 of code.
89 of code.
90
90
91 * Share live parallel jobs with other users securely.
91 * Share live parallel jobs with other users securely.
92
92
93 * Dynamically load balanced task farming system.
93 * Dynamically load balanced task farming system.
94
94
95 * Robust error handling in parallel code.
95 * Robust error handling in parallel code.
96
96
97 The latest development version is always available from IPython's `Launchpad
97 The latest development version is always available from IPython's `Launchpad
98 site <http://launchpad.net/ipython>`_.
98 site <http://launchpad.net/ipython>`_.
99 """
99 """
100
100
101 license = 'BSD'
101 license = 'BSD'
102
102
103 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
103 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
109 }
109 }
110
110
111 author = 'The IPython Development Team'
111 author = 'The IPython Development Team'
112
112
113 author_email = 'ipython-dev@scipy.org'
113 author_email = 'ipython-dev@scipy.org'
114
114
115 url = 'http://ipython.scipy.org'
115 url = 'http://ipython.scipy.org'
116
116
117 download_url = 'http://ipython.scipy.org/dist'
117 download_url = 'http://ipython.scipy.org/dist'
118
118
119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
120
120
121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
This diff has been collapsed as it changes many lines, (1081 lines changed) Show them Hide them
@@ -1,1867 +1,2216 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright οΏ½ 2006 Steven J. Bethard <steven.bethard@gmail.com>.
3 # Copyright Β© 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>.
4 #
4 #
5 # Redistribution and use in source and binary forms, with or without
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 # modification, are permitted under the terms of the 3-clause BSD
6 # use this file except in compliance with the License. You may obtain a copy
7 # license. No warranty expressed or implied.
7 # of the License at
8 # For details, see the accompanying file LICENSE.txt.
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
9
16
10 """Command-line parsing library
17 """Command-line parsing library
11
18
12 This module is an optparse-inspired command-line parsing library that:
19 This module is an optparse-inspired command-line parsing library that:
13
20
14 * handles both optional and positional arguments
21 - handles both optional and positional arguments
15 * produces highly informative usage messages
22 - produces highly informative usage messages
16 * supports parsers that dispatch to sub-parsers
23 - supports parsers that dispatch to sub-parsers
17
24
18 The following is a simple usage example that sums integers from the
25 The following is a simple usage example that sums integers from the
19 command-line and writes the result to a file:
26 command-line and writes the result to a file::
20
27
21 parser = argparse.ArgumentParser(
28 parser = argparse.ArgumentParser(
22 description='sum the integers at the command line')
29 description='sum the integers at the command line')
23 parser.add_argument(
30 parser.add_argument(
24 'integers', metavar='int', nargs='+', type=int,
31 'integers', metavar='int', nargs='+', type=int,
25 help='an integer to be summed')
32 help='an integer to be summed')
26 parser.add_argument(
33 parser.add_argument(
27 '--log', default=sys.stdout, type=argparse.FileType('w'),
34 '--log', default=sys.stdout, type=argparse.FileType('w'),
28 help='the file where the sum should be written')
35 help='the file where the sum should be written')
29 args = parser.parse_args()
36 args = parser.parse_args()
30 args.log.write('%s' % sum(args.integers))
37 args.log.write('%s' % sum(args.integers))
31 args.log.close()
38 args.log.close()
32
39
33 The module contains the following public classes:
40 The module contains the following public classes:
34
41
35 ArgumentParser -- The main entry point for command-line parsing. As the
42 - ArgumentParser -- The main entry point for command-line parsing. As the
36 example above shows, the add_argument() method is used to populate
43 example above shows, the add_argument() method is used to populate
37 the parser with actions for optional and positional arguments. Then
44 the parser with actions for optional and positional arguments. Then
38 the parse_args() method is invoked to convert the args at the
45 the parse_args() method is invoked to convert the args at the
39 command-line into an object with attributes.
46 command-line into an object with attributes.
40
47
41 ArgumentError -- The exception raised by ArgumentParser objects when
48 - ArgumentError -- The exception raised by ArgumentParser objects when
42 there are errors with the parser's actions. Errors raised while
49 there are errors with the parser's actions. Errors raised while
43 parsing the command-line are caught by ArgumentParser and emitted
50 parsing the command-line are caught by ArgumentParser and emitted
44 as command-line messages.
51 as command-line messages.
45
52
46 FileType -- A factory for defining types of files to be created. As the
53 - FileType -- A factory for defining types of files to be created. As the
47 example above shows, instances of FileType are typically passed as
54 example above shows, instances of FileType are typically passed as
48 the type= argument of add_argument() calls.
55 the type= argument of add_argument() calls.
49
56
50 Action -- The base class for parser actions. Typically actions are
57 - Action -- The base class for parser actions. Typically actions are
51 selected by passing strings like 'store_true' or 'append_const' to
58 selected by passing strings like 'store_true' or 'append_const' to
52 the action= argument of add_argument(). However, for greater
59 the action= argument of add_argument(). However, for greater
53 customization of ArgumentParser actions, subclasses of Action may
60 customization of ArgumentParser actions, subclasses of Action may
54 be defined and passed as the action= argument.
61 be defined and passed as the action= argument.
55
62
56 HelpFormatter, RawDescriptionHelpFormatter -- Formatter classes which
63 - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
64 ArgumentDefaultsHelpFormatter -- Formatter classes which
57 may be passed as the formatter_class= argument to the
65 may be passed as the formatter_class= argument to the
58 ArgumentParser constructor. HelpFormatter is the default, while
66 ArgumentParser constructor. HelpFormatter is the default,
59 RawDescriptionHelpFormatter tells the parser not to perform any
67 RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
60 line-wrapping on description text.
68 not to change the formatting for help text, and
69 ArgumentDefaultsHelpFormatter adds information about argument defaults
70 to the help.
61
71
62 All other classes in this module are considered implementation details.
72 All other classes in this module are considered implementation details.
63 (Also note that HelpFormatter and RawDescriptionHelpFormatter are only
73 (Also note that HelpFormatter and RawDescriptionHelpFormatter are only
64 considered public as object names -- the API of the formatter objects is
74 considered public as object names -- the API of the formatter objects is
65 still considered an implementation detail.)
75 still considered an implementation detail.)
66 """
76 """
67
77
68 __version__ = '0.8.0'
78 __version__ = '1.0'
69
79 __all__ = [
80 'ArgumentParser',
81 'ArgumentError',
82 'Namespace',
83 'Action',
84 'FileType',
85 'HelpFormatter',
86 'RawDescriptionHelpFormatter',
87 'RawTextHelpFormatter'
88 'ArgumentDefaultsHelpFormatter',
89 ]
90
91
92 import copy as _copy
70 import os as _os
93 import os as _os
71 import re as _re
94 import re as _re
72 import sys as _sys
95 import sys as _sys
73 import textwrap as _textwrap
96 import textwrap as _textwrap
74
97
75 from gettext import gettext as _
98 from gettext import gettext as _
76
99
100 try:
101 _set = set
102 except NameError:
103 from sets import Set as _set
104
105 try:
106 _basestring = basestring
107 except NameError:
108 _basestring = str
109
110 try:
111 _sorted = sorted
112 except NameError:
113
114 def _sorted(iterable, reverse=False):
115 result = list(iterable)
116 result.sort()
117 if reverse:
118 result.reverse()
119 return result
120
121
77 SUPPRESS = '==SUPPRESS=='
122 SUPPRESS = '==SUPPRESS=='
78
123
79 OPTIONAL = '?'
124 OPTIONAL = '?'
80 ZERO_OR_MORE = '*'
125 ZERO_OR_MORE = '*'
81 ONE_OR_MORE = '+'
126 ONE_OR_MORE = '+'
82 PARSER = '==PARSER=='
127 PARSER = '==PARSER=='
83
128
84 # =============================
129 # =============================
85 # Utility functions and classes
130 # Utility functions and classes
86 # =============================
131 # =============================
87
132
88 class _AttributeHolder(object):
133 class _AttributeHolder(object):
89 """Abstract base class that provides __repr__.
134 """Abstract base class that provides __repr__.
90
135
91 The __repr__ method returns a string in the format:
136 The __repr__ method returns a string in the format::
92 ClassName(attr=name, attr=name, ...)
137 ClassName(attr=name, attr=name, ...)
93 The attributes are determined either by a class-level attribute,
138 The attributes are determined either by a class-level attribute,
94 '_kwarg_names', or by inspecting the instance __dict__.
139 '_kwarg_names', or by inspecting the instance __dict__.
95 """
140 """
96
141
97 def __repr__(self):
142 def __repr__(self):
98 type_name = type(self).__name__
143 type_name = type(self).__name__
99 arg_strings = []
144 arg_strings = []
100 for arg in self._get_args():
145 for arg in self._get_args():
101 arg_strings.append(repr(arg))
146 arg_strings.append(repr(arg))
102 for name, value in self._get_kwargs():
147 for name, value in self._get_kwargs():
103 arg_strings.append('%s=%r' % (name, value))
148 arg_strings.append('%s=%r' % (name, value))
104 return '%s(%s)' % (type_name, ', '.join(arg_strings))
149 return '%s(%s)' % (type_name, ', '.join(arg_strings))
105
150
106 def _get_kwargs(self):
151 def _get_kwargs(self):
107 return sorted(self.__dict__.items())
152 return _sorted(self.__dict__.items())
108
153
109 def _get_args(self):
154 def _get_args(self):
110 return []
155 return []
111
156
157
112 def _ensure_value(namespace, name, value):
158 def _ensure_value(namespace, name, value):
113 if getattr(namespace, name, None) is None:
159 if getattr(namespace, name, None) is None:
114 setattr(namespace, name, value)
160 setattr(namespace, name, value)
115 return getattr(namespace, name)
161 return getattr(namespace, name)
116
117
162
118
163
119 # ===============
164 # ===============
120 # Formatting Help
165 # Formatting Help
121 # ===============
166 # ===============
122
167
123 class HelpFormatter(object):
168 class HelpFormatter(object):
169 """Formatter for generating usage messages and argument help strings.
170
171 Only the name of this class is considered a public API. All the methods
172 provided by the class are considered an implementation detail.
173 """
124
174
125 def __init__(self,
175 def __init__(self,
126 prog,
176 prog,
127 indent_increment=2,
177 indent_increment=2,
128 max_help_position=24,
178 max_help_position=24,
129 width=None):
179 width=None):
130
180
131 # default setting for width
181 # default setting for width
132 if width is None:
182 if width is None:
133 try:
183 try:
134 width = int(_os.environ['COLUMNS'])
184 width = int(_os.environ['COLUMNS'])
135 except (KeyError, ValueError):
185 except (KeyError, ValueError):
136 width = 80
186 width = 80
137 width -= 2
187 width -= 2
138
188
139 self._prog = prog
189 self._prog = prog
140 self._indent_increment = indent_increment
190 self._indent_increment = indent_increment
141 self._max_help_position = max_help_position
191 self._max_help_position = max_help_position
142 self._width = width
192 self._width = width
143
193
144 self._current_indent = 0
194 self._current_indent = 0
145 self._level = 0
195 self._level = 0
146 self._action_max_length = 0
196 self._action_max_length = 0
147
197
148 self._root_section = self._Section(self, None)
198 self._root_section = self._Section(self, None)
149 self._current_section = self._root_section
199 self._current_section = self._root_section
150
200
151 self._whitespace_matcher = _re.compile(r'\s+')
201 self._whitespace_matcher = _re.compile(r'\s+')
152 self._long_break_matcher = _re.compile(r'\n\n\n+')
202 self._long_break_matcher = _re.compile(r'\n\n\n+')
153
203
154 # ===============================
204 # ===============================
155 # Section and indentation methods
205 # Section and indentation methods
156 # ===============================
206 # ===============================
157
158 def _indent(self):
207 def _indent(self):
159 self._current_indent += self._indent_increment
208 self._current_indent += self._indent_increment
160 self._level += 1
209 self._level += 1
161
210
162 def _dedent(self):
211 def _dedent(self):
163 self._current_indent -= self._indent_increment
212 self._current_indent -= self._indent_increment
164 assert self._current_indent >= 0, 'Indent decreased below 0.'
213 assert self._current_indent >= 0, 'Indent decreased below 0.'
165 self._level -= 1
214 self._level -= 1
166
215
167 class _Section(object):
216 class _Section(object):
217
168 def __init__(self, formatter, parent, heading=None):
218 def __init__(self, formatter, parent, heading=None):
169 self.formatter = formatter
219 self.formatter = formatter
170 self.parent = parent
220 self.parent = parent
171 self.heading = heading
221 self.heading = heading
172 self.items = []
222 self.items = []
173
223
174 def format_help(self):
224 def format_help(self):
175 # format the indented section
225 # format the indented section
176 if self.parent is not None:
226 if self.parent is not None:
177 self.formatter._indent()
227 self.formatter._indent()
178 join = self.formatter._join_parts
228 join = self.formatter._join_parts
179 for func, args in self.items:
229 for func, args in self.items:
180 func(*args)
230 func(*args)
181 item_help = join(func(*args) for func, args in self.items)
231 item_help = join([func(*args) for func, args in self.items])
182 if self.parent is not None:
232 if self.parent is not None:
183 self.formatter._dedent()
233 self.formatter._dedent()
184
234
185 # return nothing if the section was empty
235 # return nothing if the section was empty
186 if not item_help:
236 if not item_help:
187 return ''
237 return ''
188
238
189 # add the heading if the section was non-empty
239 # add the heading if the section was non-empty
190 if self.heading is not SUPPRESS and self.heading is not None:
240 if self.heading is not SUPPRESS and self.heading is not None:
191 current_indent = self.formatter._current_indent
241 current_indent = self.formatter._current_indent
192 heading = '%*s%s:\n' % (current_indent, '', self.heading)
242 heading = '%*s%s:\n' % (current_indent, '', self.heading)
193 else:
243 else:
194 heading = ''
244 heading = ''
195
245
196 # join the section-initial newline, the heading and the help
246 # join the section-initial newline, the heading and the help
197 return join(['\n', heading, item_help, '\n'])
247 return join(['\n', heading, item_help, '\n'])
198
248
199 def _add_item(self, func, args):
249 def _add_item(self, func, args):
200 self._current_section.items.append((func, args))
250 self._current_section.items.append((func, args))
201
251
202 # ========================
252 # ========================
203 # Message building methods
253 # Message building methods
204 # ========================
254 # ========================
205
206 def start_section(self, heading):
255 def start_section(self, heading):
207 self._indent()
256 self._indent()
208 section = self._Section(self, self._current_section, heading)
257 section = self._Section(self, self._current_section, heading)
209 self._add_item(section.format_help, [])
258 self._add_item(section.format_help, [])
210 self._current_section = section
259 self._current_section = section
211
260
212 def end_section(self):
261 def end_section(self):
213 self._current_section = self._current_section.parent
262 self._current_section = self._current_section.parent
214 self._dedent()
263 self._dedent()
215
264
216 def add_text(self, text):
265 def add_text(self, text):
217 if text is not SUPPRESS and text is not None:
266 if text is not SUPPRESS and text is not None:
218 self._add_item(self._format_text, [text])
267 self._add_item(self._format_text, [text])
219
268
220 def add_usage(self, usage, optionals, positionals, prefix=None):
269 def add_usage(self, usage, actions, groups, prefix=None):
221 if usage is not SUPPRESS:
270 if usage is not SUPPRESS:
222 args = usage, optionals, positionals, prefix
271 args = usage, actions, groups, prefix
223 self._add_item(self._format_usage, args)
272 self._add_item(self._format_usage, args)
224
273
225 def add_argument(self, action):
274 def add_argument(self, action):
226 if action.help is not SUPPRESS:
275 if action.help is not SUPPRESS:
227
276
228 # find all invocations
277 # find all invocations
229 get_invocation = self._format_action_invocation
278 get_invocation = self._format_action_invocation
230 invocations = [get_invocation(action)]
279 invocations = [get_invocation(action)]
231 for subaction in self._iter_indented_subactions(action):
280 for subaction in self._iter_indented_subactions(action):
232 invocations.append(get_invocation(subaction))
281 invocations.append(get_invocation(subaction))
233
282
234 # update the maximum item length
283 # update the maximum item length
235 invocation_length = max(len(s) for s in invocations)
284 invocation_length = max([len(s) for s in invocations])
236 action_length = invocation_length + self._current_indent
285 action_length = invocation_length + self._current_indent
237 self._action_max_length = max(self._action_max_length,
286 self._action_max_length = max(self._action_max_length,
238 action_length)
287 action_length)
239
288
240 # add the item to the list
289 # add the item to the list
241 self._add_item(self._format_action, [action])
290 self._add_item(self._format_action, [action])
242
291
243 def add_arguments(self, actions):
292 def add_arguments(self, actions):
244 for action in actions:
293 for action in actions:
245 self.add_argument(action)
294 self.add_argument(action)
246
295
247 # =======================
296 # =======================
248 # Help-formatting methods
297 # Help-formatting methods
249 # =======================
298 # =======================
250
251 def format_help(self):
299 def format_help(self):
252 help = self._root_section.format_help() % dict(prog=self._prog)
300 help = self._root_section.format_help() % dict(prog=self._prog)
253 if help:
301 if help:
254 help = self._long_break_matcher.sub('\n\n', help)
302 help = self._long_break_matcher.sub('\n\n', help)
255 help = help.strip('\n') + '\n'
303 help = help.strip('\n') + '\n'
256 return help
304 return help
257
305
258 def _join_parts(self, part_strings):
306 def _join_parts(self, part_strings):
259 return ''.join(part
307 return ''.join([part
260 for part in part_strings
308 for part in part_strings
261 if part and part is not SUPPRESS)
309 if part and part is not SUPPRESS])
262
310
263 def _format_usage(self, usage, optionals, positionals, prefix):
311 def _format_usage(self, usage, actions, groups, prefix):
264 if prefix is None:
312 if prefix is None:
265 prefix = _('usage: ')
313 prefix = _('usage: ')
266
314
267 # if no optionals or positionals are available, usage is just prog
315 # if no optionals or positionals are available, usage is just prog
268 if usage is None and not optionals and not positionals:
316 if usage is None and not actions:
269 usage = '%(prog)s'
317 usage = '%(prog)s'
270
318
271 # if optionals and positionals are available, calculate usage
319 # if optionals and positionals are available, calculate usage
272 elif usage is None:
320 elif usage is None:
273 usage = '%(prog)s' % dict(prog=self._prog)
321 usage = '%(prog)s' % dict(prog=self._prog)
274
322
323 # split optionals from positionals
324 optionals = []
325 positionals = []
326 for action in actions:
327 if action.option_strings:
328 optionals.append(action)
329 else:
330 positionals.append(action)
331
275 # determine width of "usage: PROG" and width of text
332 # determine width of "usage: PROG" and width of text
276 prefix_width = len(prefix) + len(usage) + 1
333 prefix_width = len(prefix) + len(usage) + 1
277 prefix_indent = self._current_indent + prefix_width
334 prefix_indent = self._current_indent + prefix_width
278 text_width = self._width - self._current_indent
335 text_width = self._width - self._current_indent
279
336
280 # put them on one line if they're short enough
337 # put them on one line if they're short enough
281 format = self._format_actions_usage
338 format = self._format_actions_usage
282 action_usage = format(optionals + positionals)
339 action_usage = format(optionals + positionals, groups)
283 if prefix_width + len(action_usage) + 1 < text_width:
340 if prefix_width + len(action_usage) + 1 < text_width:
284 usage = '%s %s' % (usage, action_usage)
341 usage = '%s %s' % (usage, action_usage)
285
342
286 # if they're long, wrap optionals and positionals individually
343 # if they're long, wrap optionals and positionals individually
287 else:
344 else:
288 optional_usage = format(optionals)
345 optional_usage = format(optionals, groups)
289 positional_usage = format(positionals)
346 positional_usage = format(positionals, groups)
290 indent = ' ' * prefix_indent
347 indent = ' ' * prefix_indent
291
348
292 # usage is made of PROG, optionals and positionals
349 # usage is made of PROG, optionals and positionals
293 parts = [usage, ' ']
350 parts = [usage, ' ']
294
351
295 # options always get added right after PROG
352 # options always get added right after PROG
296 if optional_usage:
353 if optional_usage:
297 parts.append(_textwrap.fill(
354 parts.append(_textwrap.fill(
298 optional_usage, text_width,
355 optional_usage, text_width,
299 initial_indent=indent,
356 initial_indent=indent,
300 subsequent_indent=indent).lstrip())
357 subsequent_indent=indent).lstrip())
301
358
302 # if there were options, put arguments on the next line
359 # if there were options, put arguments on the next line
303 # otherwise, start them right after PROG
360 # otherwise, start them right after PROG
304 if positional_usage:
361 if positional_usage:
305 part = _textwrap.fill(
362 part = _textwrap.fill(
306 positional_usage, text_width,
363 positional_usage, text_width,
307 initial_indent=indent,
364 initial_indent=indent,
308 subsequent_indent=indent).lstrip()
365 subsequent_indent=indent).lstrip()
309 if optional_usage:
366 if optional_usage:
310 part = '\n' + indent + part
367 part = '\n' + indent + part
311 parts.append(part)
368 parts.append(part)
312 usage = ''.join(parts)
369 usage = ''.join(parts)
313
370
314 # prefix with 'usage:'
371 # prefix with 'usage:'
315 return '%s%s\n\n' % (prefix, usage)
372 return '%s%s\n\n' % (prefix, usage)
316
373
317 def _format_actions_usage(self, actions):
374 def _format_actions_usage(self, actions, groups):
318 parts = []
375 # find group indices and identify actions in groups
319 for action in actions:
376 group_actions = _set()
320 if action.help is SUPPRESS:
377 inserts = {}
378 for group in groups:
379 try:
380 start = actions.index(group._group_actions[0])
381 except ValueError:
321 continue
382 continue
383 else:
384 end = start + len(group._group_actions)
385 if actions[start:end] == group._group_actions:
386 for action in group._group_actions:
387 group_actions.add(action)
388 if not group.required:
389 inserts[start] = '['
390 inserts[end] = ']'
391 else:
392 inserts[start] = '('
393 inserts[end] = ')'
394 for i in range(start + 1, end):
395 inserts[i] = '|'
322
396
323 # produce all arg strings
397 # collect all actions format strings
324 if not action.option_strings:
398 parts = []
325 parts.append(self._format_args(action, action.dest))
399 for i, action in enumerate(actions):
400
401 # suppressed arguments are marked with None
402 # remove | separators for suppressed arguments
403 if action.help is SUPPRESS:
404 parts.append(None)
405 if inserts.get(i) == '|':
406 inserts.pop(i)
407 elif inserts.get(i + 1) == '|':
408 inserts.pop(i + 1)
409
410 # produce all arg strings
411 elif not action.option_strings:
412 part = self._format_args(action, action.dest)
413
414 # if it's in a group, strip the outer []
415 if action in group_actions:
416 if part[0] == '[' and part[-1] == ']':
417 part = part[1:-1]
418
419 # add the action string to the list
420 parts.append(part)
326
421
327 # produce the first way to invoke the option in brackets
422 # produce the first way to invoke the option in brackets
328 else:
423 else:
329 option_string = action.option_strings[0]
424 option_string = action.option_strings[0]
330
425
331 # if the Optional doesn't take a value, format is:
426 # if the Optional doesn't take a value, format is:
332 # -s or --long
427 # -s or --long
333 if action.nargs == 0:
428 if action.nargs == 0:
334 part = '%s' % option_string
429 part = '%s' % option_string
335
430
336 # if the Optional takes a value, format is:
431 # if the Optional takes a value, format is:
337 # -s ARGS or --long ARGS
432 # -s ARGS or --long ARGS
338 else:
433 else:
339 default = action.dest.upper()
434 default = action.dest.upper()
340 args_string = self._format_args(action, default)
435 args_string = self._format_args(action, default)
341 part = '%s %s' % (option_string, args_string)
436 part = '%s %s' % (option_string, args_string)
342
437
343 # make it look optional if it's not required
438 # make it look optional if it's not required or in a group
344 if not action.required:
439 if not action.required and action not in group_actions:
345 part = '[%s]' % part
440 part = '[%s]' % part
441
442 # add the action string to the list
346 parts.append(part)
443 parts.append(part)
347
444
348 return ' '.join(parts)
445 # insert things at the necessary indices
446 for i in _sorted(inserts, reverse=True):
447 parts[i:i] = [inserts[i]]
448
449 # join all the action items with spaces
450 text = ' '.join([item for item in parts if item is not None])
451
452 # clean up separators for mutually exclusive groups
453 open = r'[\[(]'
454 close = r'[\])]'
455 text = _re.sub(r'(%s) ' % open, r'\1', text)
456 text = _re.sub(r' (%s)' % close, r'\1', text)
457 text = _re.sub(r'%s *%s' % (open, close), r'', text)
458 text = _re.sub(r'\(([^|]*)\)', r'\1', text)
459 text = text.strip()
460
461 # return the text
462 return text
349
463
350 def _format_text(self, text):
464 def _format_text(self, text):
351 text_width = self._width - self._current_indent
465 text_width = self._width - self._current_indent
352 indent = ' ' * self._current_indent
466 indent = ' ' * self._current_indent
353 return self._fill_text(text, text_width, indent) + '\n\n'
467 return self._fill_text(text, text_width, indent) + '\n\n'
354
468
355 def _format_action(self, action):
469 def _format_action(self, action):
356 # determine the required width and the entry label
470 # determine the required width and the entry label
357 help_position = min(self._action_max_length + 2,
471 help_position = min(self._action_max_length + 2,
358 self._max_help_position)
472 self._max_help_position)
359 help_width = self._width - help_position
473 help_width = self._width - help_position
360 action_width = help_position - self._current_indent - 2
474 action_width = help_position - self._current_indent - 2
361 action_header = self._format_action_invocation(action)
475 action_header = self._format_action_invocation(action)
362
476
363 # ho nelp; start on same line and add a final newline
477 # ho nelp; start on same line and add a final newline
364 if not action.help:
478 if not action.help:
365 tup = self._current_indent, '', action_header
479 tup = self._current_indent, '', action_header
366 action_header = '%*s%s\n' % tup
480 action_header = '%*s%s\n' % tup
367
481
368 # short action name; start on the same line and pad two spaces
482 # short action name; start on the same line and pad two spaces
369 elif len(action_header) <= action_width:
483 elif len(action_header) <= action_width:
370 tup = self._current_indent, '', action_width, action_header
484 tup = self._current_indent, '', action_width, action_header
371 action_header = '%*s%-*s ' % tup
485 action_header = '%*s%-*s ' % tup
372 indent_first = 0
486 indent_first = 0
373
487
374 # long action name; start on the next line
488 # long action name; start on the next line
375 else:
489 else:
376 tup = self._current_indent, '', action_header
490 tup = self._current_indent, '', action_header
377 action_header = '%*s%s\n' % tup
491 action_header = '%*s%s\n' % tup
378 indent_first = help_position
492 indent_first = help_position
379
493
380 # collect the pieces of the action help
494 # collect the pieces of the action help
381 parts = [action_header]
495 parts = [action_header]
382
496
383 # if there was help for the action, add lines of help text
497 # if there was help for the action, add lines of help text
384 if action.help:
498 if action.help:
385 help_text = self._expand_help(action)
499 help_text = self._expand_help(action)
386 help_lines = self._split_lines(help_text, help_width)
500 help_lines = self._split_lines(help_text, help_width)
387 parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
501 parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
388 for line in help_lines[1:]:
502 for line in help_lines[1:]:
389 parts.append('%*s%s\n' % (help_position, '', line))
503 parts.append('%*s%s\n' % (help_position, '', line))
390
504
391 # or add a newline if the description doesn't end with one
505 # or add a newline if the description doesn't end with one
392 elif not action_header.endswith('\n'):
506 elif not action_header.endswith('\n'):
393 parts.append('\n')
507 parts.append('\n')
394
508
395 # if there are any sub-actions, add their help as well
509 # if there are any sub-actions, add their help as well
396 for subaction in self._iter_indented_subactions(action):
510 for subaction in self._iter_indented_subactions(action):
397 parts.append(self._format_action(subaction))
511 parts.append(self._format_action(subaction))
398
512
399 # return a single string
513 # return a single string
400 return self._join_parts(parts)
514 return self._join_parts(parts)
401
515
402 def _format_action_invocation(self, action):
516 def _format_action_invocation(self, action):
403 if not action.option_strings:
517 if not action.option_strings:
404 return self._format_metavar(action, action.dest)
518 metavar, = self._metavar_formatter(action, action.dest)(1)
519 return metavar
405
520
406 else:
521 else:
407 parts = []
522 parts = []
408
523
409 # if the Optional doesn't take a value, format is:
524 # if the Optional doesn't take a value, format is:
410 # -s, --long
525 # -s, --long
411 if action.nargs == 0:
526 if action.nargs == 0:
412 parts.extend(action.option_strings)
527 parts.extend(action.option_strings)
413
528
414 # if the Optional takes a value, format is:
529 # if the Optional takes a value, format is:
415 # -s ARGS, --long ARGS
530 # -s ARGS, --long ARGS
416 else:
531 else:
417 default = action.dest.upper()
532 default = action.dest.upper()
418 args_string = self._format_args(action, default)
533 args_string = self._format_args(action, default)
419 for option_string in action.option_strings:
534 for option_string in action.option_strings:
420 parts.append('%s %s' % (option_string, args_string))
535 parts.append('%s %s' % (option_string, args_string))
421
536
422 return ', '.join(parts)
537 return ', '.join(parts)
423
538
424 def _format_metavar(self, action, default_metavar):
539 def _metavar_formatter(self, action, default_metavar):
425 if action.metavar is not None:
540 if action.metavar is not None:
426 name = action.metavar
541 result = action.metavar
427 elif action.choices is not None:
542 elif action.choices is not None:
428 choice_strs = (str(choice) for choice in action.choices)
543 choice_strs = [str(choice) for choice in action.choices]
429 name = '{%s}' % ','.join(choice_strs)
544 result = '{%s}' % ','.join(choice_strs)
430 else:
545 else:
431 name = default_metavar
546 result = default_metavar
432 return name
547
548 def format(tuple_size):
549 if isinstance(result, tuple):
550 return result
551 else:
552 return (result, ) * tuple_size
553 return format
433
554
434 def _format_args(self, action, default_metavar):
555 def _format_args(self, action, default_metavar):
435 name = self._format_metavar(action, default_metavar)
556 get_metavar = self._metavar_formatter(action, default_metavar)
436 if action.nargs is None:
557 if action.nargs is None:
437 result = name
558 result = '%s' % get_metavar(1)
438 elif action.nargs == OPTIONAL:
559 elif action.nargs == OPTIONAL:
439 result = '[%s]' % name
560 result = '[%s]' % get_metavar(1)
440 elif action.nargs == ZERO_OR_MORE:
561 elif action.nargs == ZERO_OR_MORE:
441 result = '[%s [%s ...]]' % (name, name)
562 result = '[%s [%s ...]]' % get_metavar(2)
442 elif action.nargs == ONE_OR_MORE:
563 elif action.nargs == ONE_OR_MORE:
443 result = '%s [%s ...]' % (name, name)
564 result = '%s [%s ...]' % get_metavar(2)
444 elif action.nargs is PARSER:
565 elif action.nargs is PARSER:
445 result = '%s ...' % name
566 result = '%s ...' % get_metavar(1)
446 else:
567 else:
447 result = ' '.join([name] * action.nargs)
568 formats = ['%s' for _ in range(action.nargs)]
569 result = ' '.join(formats) % get_metavar(action.nargs)
448 return result
570 return result
449
571
450 def _expand_help(self, action):
572 def _expand_help(self, action):
451 params = dict(vars(action), prog=self._prog)
573 params = dict(vars(action), prog=self._prog)
452 for name, value in params.items():
574 for name in list(params):
453 if value is SUPPRESS:
575 if params[name] is SUPPRESS:
454 del params[name]
576 del params[name]
455 if params.get('choices') is not None:
577 if params.get('choices') is not None:
456 choices_str = ', '.join(str(c) for c in params['choices'])
578 choices_str = ', '.join([str(c) for c in params['choices']])
457 params['choices'] = choices_str
579 params['choices'] = choices_str
458 return action.help % params
580 return self._get_help_string(action) % params
459
581
460 def _iter_indented_subactions(self, action):
582 def _iter_indented_subactions(self, action):
461 try:
583 try:
462 get_subactions = action._get_subactions
584 get_subactions = action._get_subactions
463 except AttributeError:
585 except AttributeError:
464 pass
586 pass
465 else:
587 else:
466 self._indent()
588 self._indent()
467 for subaction in get_subactions():
589 for subaction in get_subactions():
468 yield subaction
590 yield subaction
469 self._dedent()
591 self._dedent()
470
592
471 def _split_lines(self, text, width):
593 def _split_lines(self, text, width):
472 text = self._whitespace_matcher.sub(' ', text).strip()
594 text = self._whitespace_matcher.sub(' ', text).strip()
473 return _textwrap.wrap(text, width)
595 return _textwrap.wrap(text, width)
474
596
475 def _fill_text(self, text, width, indent):
597 def _fill_text(self, text, width, indent):
476 text = self._whitespace_matcher.sub(' ', text).strip()
598 text = self._whitespace_matcher.sub(' ', text).strip()
477 return _textwrap.fill(text, width, initial_indent=indent,
599 return _textwrap.fill(text, width, initial_indent=indent,
478 subsequent_indent=indent)
600 subsequent_indent=indent)
479
601
602 def _get_help_string(self, action):
603 return action.help
604
605
480 class RawDescriptionHelpFormatter(HelpFormatter):
606 class RawDescriptionHelpFormatter(HelpFormatter):
481
607 """Help message formatter which retains any formatting in descriptions.
608
609 Only the name of this class is considered a public API. All the methods
610 provided by the class are considered an implementation detail.
611 """
612
482 def _fill_text(self, text, width, indent):
613 def _fill_text(self, text, width, indent):
483 return ''.join(indent + line for line in text.splitlines(True))
614 return ''.join([indent + line for line in text.splitlines(True)])
615
484
616
485 class RawTextHelpFormatter(RawDescriptionHelpFormatter):
617 class RawTextHelpFormatter(RawDescriptionHelpFormatter):
486
618 """Help message formatter which retains formatting of all help text.
619
620 Only the name of this class is considered a public API. All the methods
621 provided by the class are considered an implementation detail.
622 """
623
487 def _split_lines(self, text, width):
624 def _split_lines(self, text, width):
488 return text.splitlines()
625 return text.splitlines()
489
626
627
628 class ArgumentDefaultsHelpFormatter(HelpFormatter):
629 """Help message formatter which adds default values to argument help.
630
631 Only the name of this class is considered a public API. All the methods
632 provided by the class are considered an implementation detail.
633 """
634
635 def _get_help_string(self, action):
636 help = action.help
637 if '%(default)' not in action.help:
638 if action.default is not SUPPRESS:
639 defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
640 if action.option_strings or action.nargs in defaulting_nargs:
641 help += ' (default: %(default)s)'
642 return help
643
644
490 # =====================
645 # =====================
491 # Options and Arguments
646 # Options and Arguments
492 # =====================
647 # =====================
493
648
494 class ArgumentError(Exception):
649 def _get_action_name(argument):
495 """ArgumentError(message, argument)
650 if argument is None:
651 return None
652 elif argument.option_strings:
653 return '/'.join(argument.option_strings)
654 elif argument.metavar not in (None, SUPPRESS):
655 return argument.metavar
656 elif argument.dest not in (None, SUPPRESS):
657 return argument.dest
658 else:
659 return None
496
660
497 Raised whenever there was an error creating or using an argument
661
498 (optional or positional).
662 class ArgumentError(Exception):
663 """An error from creating or using an argument (optional or positional).
499
664
500 The string value of this exception is the message, augmented with
665 The string value of this exception is the message, augmented with
501 information about the argument that caused it.
666 information about the argument that caused it.
502 """
667 """
503
668
504 def __init__(self, argument, message):
669 def __init__(self, argument, message):
505 if argument.option_strings:
670 self.argument_name = _get_action_name(argument)
506 self.argument_name = '/'.join(argument.option_strings)
507 elif argument.metavar not in (None, SUPPRESS):
508 self.argument_name = argument.metavar
509 elif argument.dest not in (None, SUPPRESS):
510 self.argument_name = argument.dest
511 else:
512 self.argument_name = None
513 self.message = message
671 self.message = message
514
672
515 def __str__(self):
673 def __str__(self):
516 if self.argument_name is None:
674 if self.argument_name is None:
517 format = '%(message)s'
675 format = '%(message)s'
518 else:
676 else:
519 format = 'argument %(argument_name)s: %(message)s'
677 format = 'argument %(argument_name)s: %(message)s'
520 return format % dict(message=self.message,
678 return format % dict(message=self.message,
521 argument_name=self.argument_name)
679 argument_name=self.argument_name)
522
680
523 # ==============
681 # ==============
524 # Action classes
682 # Action classes
525 # ==============
683 # ==============
526
684
527 class Action(_AttributeHolder):
685 class Action(_AttributeHolder):
528 """Action(*strings, **options)
686 """Information about how to convert command line strings to Python objects.
529
687
530 Action objects hold the information necessary to convert a
688 Action objects are used by an ArgumentParser to represent the information
531 set of command-line arguments (possibly including an initial option
689 needed to parse a single argument from one or more strings from the
532 string) into the desired Python object(s).
690 command line. The keyword arguments to the Action constructor are also
691 all attributes of Action instances.
533
692
534 Keyword Arguments:
693 Keyword Arguments:
535
694
536 option_strings -- A list of command-line option strings which
695 - option_strings -- A list of command-line option strings which
537 should be associated with this action.
696 should be associated with this action.
538
697
539 dest -- The name of the attribute to hold the created object(s)
698 - dest -- The name of the attribute to hold the created object(s)
540
699
541 nargs -- The number of command-line arguments that should be consumed.
700 - nargs -- The number of command-line arguments that should be
542 By default, one argument will be consumed and a single value will
701 consumed. By default, one argument will be consumed and a single
543 be produced. Other values include:
702 value will be produced. Other values include:
544 * N (an integer) consumes N arguments (and produces a list)
703 - N (an integer) consumes N arguments (and produces a list)
545 * '?' consumes zero or one arguments
704 - '?' consumes zero or one arguments
546 * '*' consumes zero or more arguments (and produces a list)
705 - '*' consumes zero or more arguments (and produces a list)
547 * '+' consumes one or more arguments (and produces a list)
706 - '+' consumes one or more arguments (and produces a list)
548 Note that the difference between the default and nargs=1 is that
707 Note that the difference between the default and nargs=1 is that
549 with the default, a single value will be produced, while with
708 with the default, a single value will be produced, while with
550 nargs=1, a list containing a single value will be produced.
709 nargs=1, a list containing a single value will be produced.
551
710
552 const -- The value to be produced if the option is specified and the
711 - const -- The value to be produced if the option is specified and the
553 option uses an action that takes no values.
712 option uses an action that takes no values.
554
713
555 default -- The value to be produced if the option is not specified.
714 - default -- The value to be produced if the option is not specified.
556
715
557 type -- The type which the command-line arguments should be converted
716 - type -- The type which the command-line arguments should be converted
558 to, should be one of 'string', 'int', 'float', 'complex' or a
717 to, should be one of 'string', 'int', 'float', 'complex' or a
559 callable object that accepts a single string argument. If None,
718 callable object that accepts a single string argument. If None,
560 'string' is assumed.
719 'string' is assumed.
561
720
562 choices -- A container of values that should be allowed. If not None,
721 - choices -- A container of values that should be allowed. If not None,
563 after a command-line argument has been converted to the appropriate
722 after a command-line argument has been converted to the appropriate
564 type, an exception will be raised if it is not a member of this
723 type, an exception will be raised if it is not a member of this
565 collection.
724 collection.
566
725
567 required -- True if the action must always be specified at the command
726 - required -- True if the action must always be specified at the
568 line. This is only meaningful for optional command-line arguments.
727 command line. This is only meaningful for optional command-line
569
728 arguments.
570 help -- The help string describing the argument.
571
572 metavar -- The name to be used for the option's argument with the help
573 string. If None, the 'dest' value will be used as the name.
574 """
575
729
730 - help -- The help string describing the argument.
731
732 - metavar -- The name to be used for the option's argument with the
733 help string. If None, the 'dest' value will be used as the name.
734 """
576
735
577 def __init__(self,
736 def __init__(self,
578 option_strings,
737 option_strings,
579 dest,
738 dest,
580 nargs=None,
739 nargs=None,
581 const=None,
740 const=None,
582 default=None,
741 default=None,
583 type=None,
742 type=None,
584 choices=None,
743 choices=None,
585 required=False,
744 required=False,
586 help=None,
745 help=None,
587 metavar=None):
746 metavar=None):
588 self.option_strings = option_strings
747 self.option_strings = option_strings
589 self.dest = dest
748 self.dest = dest
590 self.nargs = nargs
749 self.nargs = nargs
591 self.const = const
750 self.const = const
592 self.default = default
751 self.default = default
593 self.type = type
752 self.type = type
594 self.choices = choices
753 self.choices = choices
595 self.required = required
754 self.required = required
596 self.help = help
755 self.help = help
597 self.metavar = metavar
756 self.metavar = metavar
598
757
599 def _get_kwargs(self):
758 def _get_kwargs(self):
600 names = [
759 names = [
601 'option_strings',
760 'option_strings',
602 'dest',
761 'dest',
603 'nargs',
762 'nargs',
604 'const',
763 'const',
605 'default',
764 'default',
606 'type',
765 'type',
607 'choices',
766 'choices',
608 'help',
767 'help',
609 'metavar'
768 'metavar',
610 ]
769 ]
611 return [(name, getattr(self, name)) for name in names]
770 return [(name, getattr(self, name)) for name in names]
612
771
613 def __call__(self, parser, namespace, values, option_string=None):
772 def __call__(self, parser, namespace, values, option_string=None):
614 raise NotImplementedError(_('.__call__() not defined'))
773 raise NotImplementedError(_('.__call__() not defined'))
615
774
775
616 class _StoreAction(Action):
776 class _StoreAction(Action):
777
617 def __init__(self,
778 def __init__(self,
618 option_strings,
779 option_strings,
619 dest,
780 dest,
620 nargs=None,
781 nargs=None,
621 const=None,
782 const=None,
622 default=None,
783 default=None,
623 type=None,
784 type=None,
624 choices=None,
785 choices=None,
625 required=False,
786 required=False,
626 help=None,
787 help=None,
627 metavar=None):
788 metavar=None):
628 if nargs == 0:
789 if nargs == 0:
629 raise ValueError('nargs must be > 0')
790 raise ValueError('nargs must be > 0')
630 if const is not None and nargs != OPTIONAL:
791 if const is not None and nargs != OPTIONAL:
631 raise ValueError('nargs must be %r to supply const' % OPTIONAL)
792 raise ValueError('nargs must be %r to supply const' % OPTIONAL)
632 super(_StoreAction, self).__init__(
793 super(_StoreAction, self).__init__(
633 option_strings=option_strings,
794 option_strings=option_strings,
634 dest=dest,
795 dest=dest,
635 nargs=nargs,
796 nargs=nargs,
636 const=const,
797 const=const,
637 default=default,
798 default=default,
638 type=type,
799 type=type,
639 choices=choices,
800 choices=choices,
640 required=required,
801 required=required,
641 help=help,
802 help=help,
642 metavar=metavar)
803 metavar=metavar)
643
804
644 def __call__(self, parser, namespace, values, option_string=None):
805 def __call__(self, parser, namespace, values, option_string=None):
645 setattr(namespace, self.dest, values)
806 setattr(namespace, self.dest, values)
646
807
808
647 class _StoreConstAction(Action):
809 class _StoreConstAction(Action):
810
648 def __init__(self,
811 def __init__(self,
649 option_strings,
812 option_strings,
650 dest,
813 dest,
651 const,
814 const,
652 default=None,
815 default=None,
653 required=False,
816 required=False,
654 help=None,
817 help=None,
655 metavar=None):
818 metavar=None):
656 super(_StoreConstAction, self).__init__(
819 super(_StoreConstAction, self).__init__(
657 option_strings=option_strings,
820 option_strings=option_strings,
658 dest=dest,
821 dest=dest,
659 nargs=0,
822 nargs=0,
660 const=const,
823 const=const,
661 default=default,
824 default=default,
662 required=required,
825 required=required,
663 help=help)
826 help=help)
664
827
665 def __call__(self, parser, namespace, values, option_string=None):
828 def __call__(self, parser, namespace, values, option_string=None):
666 setattr(namespace, self.dest, self.const)
829 setattr(namespace, self.dest, self.const)
667
830
831
668 class _StoreTrueAction(_StoreConstAction):
832 class _StoreTrueAction(_StoreConstAction):
833
669 def __init__(self,
834 def __init__(self,
670 option_strings,
835 option_strings,
671 dest,
836 dest,
672 default=False,
837 default=False,
673 required=False,
838 required=False,
674 help=None):
839 help=None):
675 super(_StoreTrueAction, self).__init__(
840 super(_StoreTrueAction, self).__init__(
676 option_strings=option_strings,
841 option_strings=option_strings,
677 dest=dest,
842 dest=dest,
678 const=True,
843 const=True,
679 default=default,
844 default=default,
680 required=required,
845 required=required,
681 help=help)
846 help=help)
682
847
848
683 class _StoreFalseAction(_StoreConstAction):
849 class _StoreFalseAction(_StoreConstAction):
850
684 def __init__(self,
851 def __init__(self,
685 option_strings,
852 option_strings,
686 dest,
853 dest,
687 default=True,
854 default=True,
688 required=False,
855 required=False,
689 help=None):
856 help=None):
690 super(_StoreFalseAction, self).__init__(
857 super(_StoreFalseAction, self).__init__(
691 option_strings=option_strings,
858 option_strings=option_strings,
692 dest=dest,
859 dest=dest,
693 const=False,
860 const=False,
694 default=default,
861 default=default,
695 required=required,
862 required=required,
696 help=help)
863 help=help)
697
864
865
698 class _AppendAction(Action):
866 class _AppendAction(Action):
867
699 def __init__(self,
868 def __init__(self,
700 option_strings,
869 option_strings,
701 dest,
870 dest,
702 nargs=None,
871 nargs=None,
703 const=None,
872 const=None,
704 default=None,
873 default=None,
705 type=None,
874 type=None,
706 choices=None,
875 choices=None,
707 required=False,
876 required=False,
708 help=None,
877 help=None,
709 metavar=None):
878 metavar=None):
710 if nargs == 0:
879 if nargs == 0:
711 raise ValueError('nargs must be > 0')
880 raise ValueError('nargs must be > 0')
712 if const is not None and nargs != OPTIONAL:
881 if const is not None and nargs != OPTIONAL:
713 raise ValueError('nargs must be %r to supply const' % OPTIONAL)
882 raise ValueError('nargs must be %r to supply const' % OPTIONAL)
714 super(_AppendAction, self).__init__(
883 super(_AppendAction, self).__init__(
715 option_strings=option_strings,
884 option_strings=option_strings,
716 dest=dest,
885 dest=dest,
717 nargs=nargs,
886 nargs=nargs,
718 const=const,
887 const=const,
719 default=default,
888 default=default,
720 type=type,
889 type=type,
721 choices=choices,
890 choices=choices,
722 required=required,
891 required=required,
723 help=help,
892 help=help,
724 metavar=metavar)
893 metavar=metavar)
725
894
726 def __call__(self, parser, namespace, values, option_string=None):
895 def __call__(self, parser, namespace, values, option_string=None):
727 _ensure_value(namespace, self.dest, []).append(values)
896 items = _copy.copy(_ensure_value(namespace, self.dest, []))
897 items.append(values)
898 setattr(namespace, self.dest, items)
899
728
900
729 class _AppendConstAction(Action):
901 class _AppendConstAction(Action):
902
730 def __init__(self,
903 def __init__(self,
731 option_strings,
904 option_strings,
732 dest,
905 dest,
733 const,
906 const,
734 default=None,
907 default=None,
735 required=False,
908 required=False,
736 help=None,
909 help=None,
737 metavar=None):
910 metavar=None):
738 super(_AppendConstAction, self).__init__(
911 super(_AppendConstAction, self).__init__(
739 option_strings=option_strings,
912 option_strings=option_strings,
740 dest=dest,
913 dest=dest,
741 nargs=0,
914 nargs=0,
742 const=const,
915 const=const,
743 default=default,
916 default=default,
744 required=required,
917 required=required,
745 help=help,
918 help=help,
746 metavar=metavar)
919 metavar=metavar)
747
920
748 def __call__(self, parser, namespace, values, option_string=None):
921 def __call__(self, parser, namespace, values, option_string=None):
749 _ensure_value(namespace, self.dest, []).append(self.const)
922 items = _copy.copy(_ensure_value(namespace, self.dest, []))
923 items.append(self.const)
924 setattr(namespace, self.dest, items)
925
750
926
751 class _CountAction(Action):
927 class _CountAction(Action):
928
752 def __init__(self,
929 def __init__(self,
753 option_strings,
930 option_strings,
754 dest,
931 dest,
755 default=None,
932 default=None,
756 required=False,
933 required=False,
757 help=None):
934 help=None):
758 super(_CountAction, self).__init__(
935 super(_CountAction, self).__init__(
759 option_strings=option_strings,
936 option_strings=option_strings,
760 dest=dest,
937 dest=dest,
761 nargs=0,
938 nargs=0,
762 default=default,
939 default=default,
763 required=required,
940 required=required,
764 help=help)
941 help=help)
765
942
766 def __call__(self, parser, namespace, values, option_string=None):
943 def __call__(self, parser, namespace, values, option_string=None):
767 new_count = _ensure_value(namespace, self.dest, 0) + 1
944 new_count = _ensure_value(namespace, self.dest, 0) + 1
768 setattr(namespace, self.dest, new_count)
945 setattr(namespace, self.dest, new_count)
769
946
947
770 class _HelpAction(Action):
948 class _HelpAction(Action):
949
771 def __init__(self,
950 def __init__(self,
772 option_strings,
951 option_strings,
773 dest=SUPPRESS,
952 dest=SUPPRESS,
774 default=SUPPRESS,
953 default=SUPPRESS,
775 help=None):
954 help=None):
776 super(_HelpAction, self).__init__(
955 super(_HelpAction, self).__init__(
777 option_strings=option_strings,
956 option_strings=option_strings,
778 dest=dest,
957 dest=dest,
779 default=default,
958 default=default,
780 nargs=0,
959 nargs=0,
781 help=help)
960 help=help)
782
961
783 def __call__(self, parser, namespace, values, option_string=None):
962 def __call__(self, parser, namespace, values, option_string=None):
784 parser.print_help()
963 parser.print_help()
785 parser.exit()
964 parser.exit()
786
965
966
787 class _VersionAction(Action):
967 class _VersionAction(Action):
968
788 def __init__(self,
969 def __init__(self,
789 option_strings,
970 option_strings,
790 dest=SUPPRESS,
971 dest=SUPPRESS,
791 default=SUPPRESS,
972 default=SUPPRESS,
792 help=None):
973 help=None):
793 super(_VersionAction, self).__init__(
974 super(_VersionAction, self).__init__(
794 option_strings=option_strings,
975 option_strings=option_strings,
795 dest=dest,
976 dest=dest,
796 default=default,
977 default=default,
797 nargs=0,
978 nargs=0,
798 help=help)
979 help=help)
799
980
800 def __call__(self, parser, namespace, values, option_string=None):
981 def __call__(self, parser, namespace, values, option_string=None):
801 parser.print_version()
982 parser.print_version()
802 parser.exit()
983 parser.exit()
803
984
985
804 class _SubParsersAction(Action):
986 class _SubParsersAction(Action):
805
987
806 class _ChoicesPseudoAction(Action):
988 class _ChoicesPseudoAction(Action):
989
807 def __init__(self, name, help):
990 def __init__(self, name, help):
808 sup = super(_SubParsersAction._ChoicesPseudoAction, self)
991 sup = super(_SubParsersAction._ChoicesPseudoAction, self)
809 sup.__init__(option_strings=[], dest=name, help=help)
992 sup.__init__(option_strings=[], dest=name, help=help)
810
993
811
812 def __init__(self,
994 def __init__(self,
813 option_strings,
995 option_strings,
814 prog,
996 prog,
815 parser_class,
997 parser_class,
816 dest=SUPPRESS,
998 dest=SUPPRESS,
817 help=None,
999 help=None,
818 metavar=None):
1000 metavar=None):
819
1001
820 self._prog_prefix = prog
1002 self._prog_prefix = prog
821 self._parser_class = parser_class
1003 self._parser_class = parser_class
822 self._name_parser_map = {}
1004 self._name_parser_map = {}
823 self._choices_actions = []
1005 self._choices_actions = []
824
1006
825 super(_SubParsersAction, self).__init__(
1007 super(_SubParsersAction, self).__init__(
826 option_strings=option_strings,
1008 option_strings=option_strings,
827 dest=dest,
1009 dest=dest,
828 nargs=PARSER,
1010 nargs=PARSER,
829 choices=self._name_parser_map,
1011 choices=self._name_parser_map,
830 help=help,
1012 help=help,
831 metavar=metavar)
1013 metavar=metavar)
832
1014
833 def add_parser(self, name, **kwargs):
1015 def add_parser(self, name, **kwargs):
834 # set prog from the existing prefix
1016 # set prog from the existing prefix
835 if kwargs.get('prog') is None:
1017 if kwargs.get('prog') is None:
836 kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
1018 kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
837
1019
838 # create a pseudo-action to hold the choice help
1020 # create a pseudo-action to hold the choice help
839 if 'help' in kwargs:
1021 if 'help' in kwargs:
840 help = kwargs.pop('help')
1022 help = kwargs.pop('help')
841 choice_action = self._ChoicesPseudoAction(name, help)
1023 choice_action = self._ChoicesPseudoAction(name, help)
842 self._choices_actions.append(choice_action)
1024 self._choices_actions.append(choice_action)
843
1025
844 # create the parser and add it to the map
1026 # create the parser and add it to the map
845 parser = self._parser_class(**kwargs)
1027 parser = self._parser_class(**kwargs)
846 self._name_parser_map[name] = parser
1028 self._name_parser_map[name] = parser
847 return parser
1029 return parser
848
1030
849 def _get_subactions(self):
1031 def _get_subactions(self):
850 return self._choices_actions
1032 return self._choices_actions
851
1033
852 def __call__(self, parser, namespace, values, option_string=None):
1034 def __call__(self, parser, namespace, values, option_string=None):
853 parser_name = values[0]
1035 parser_name = values[0]
854 arg_strings = values[1:]
1036 arg_strings = values[1:]
855
1037
856 # set the parser name if requested
1038 # set the parser name if requested
857 if self.dest is not SUPPRESS:
1039 if self.dest is not SUPPRESS:
858 setattr(namespace, self.dest, parser_name)
1040 setattr(namespace, self.dest, parser_name)
859
1041
860 # select the parser
1042 # select the parser
861 try:
1043 try:
862 parser = self._name_parser_map[parser_name]
1044 parser = self._name_parser_map[parser_name]
863 except KeyError:
1045 except KeyError:
864 tup = parser_name, ', '.join(self._name_parser_map)
1046 tup = parser_name, ', '.join(self._name_parser_map)
865 msg = _('unknown parser %r (choices: %s)' % tup)
1047 msg = _('unknown parser %r (choices: %s)' % tup)
866 raise ArgumentError(self, msg)
1048 raise ArgumentError(self, msg)
867
1049
868 # parse all the remaining options into the namespace
1050 # parse all the remaining options into the namespace
869 parser.parse_args(arg_strings, namespace)
1051 parser.parse_args(arg_strings, namespace)
870
1052
871
1053
872 # ==============
1054 # ==============
873 # Type classes
1055 # Type classes
874 # ==============
1056 # ==============
875
1057
876 class FileType(object):
1058 class FileType(object):
877 """Factory for creating file object types
1059 """Factory for creating file object types
878
1060
879 Instances of FileType are typically passed as type= arguments to the
1061 Instances of FileType are typically passed as type= arguments to the
880 ArgumentParser add_argument() method.
1062 ArgumentParser add_argument() method.
881
1063
882 Keyword Arguments:
1064 Keyword Arguments:
883 mode -- A string indicating how the file is to be opened. Accepts the
1065 - mode -- A string indicating how the file is to be opened. Accepts the
884 same values as the builtin open() function.
1066 same values as the builtin open() function.
885 bufsize -- The file's desired buffer size. Accepts the same values as
1067 - bufsize -- The file's desired buffer size. Accepts the same values as
886 the builtin open() function.
1068 the builtin open() function.
887 """
1069 """
1070
888 def __init__(self, mode='r', bufsize=None):
1071 def __init__(self, mode='r', bufsize=None):
889 self._mode = mode
1072 self._mode = mode
890 self._bufsize = bufsize
1073 self._bufsize = bufsize
891
1074
892 def __call__(self, string):
1075 def __call__(self, string):
893 # the special argument "-" means sys.std{in,out}
1076 # the special argument "-" means sys.std{in,out}
894 if string == '-':
1077 if string == '-':
895 if self._mode == 'r':
1078 if 'r' in self._mode:
896 return _sys.stdin
1079 return _sys.stdin
897 elif self._mode == 'w':
1080 elif 'w' in self._mode:
898 return _sys.stdout
1081 return _sys.stdout
899 else:
1082 else:
900 msg = _('argument "-" with mode %r' % self._mode)
1083 msg = _('argument "-" with mode %r' % self._mode)
901 raise ValueError(msg)
1084 raise ValueError(msg)
902
1085
903 # all other arguments are used as file names
1086 # all other arguments are used as file names
904 if self._bufsize:
1087 if self._bufsize:
905 return open(string, self._mode, self._bufsize)
1088 return open(string, self._mode, self._bufsize)
906 else:
1089 else:
907 return open(string, self._mode)
1090 return open(string, self._mode)
908
1091
1092 def __repr__(self):
1093 args = [self._mode, self._bufsize]
1094 args_str = ', '.join([repr(arg) for arg in args if arg is not None])
1095 return '%s(%s)' % (type(self).__name__, args_str)
909
1096
910 # ===========================
1097 # ===========================
911 # Optional and Positional Parsing
1098 # Optional and Positional Parsing
912 # ===========================
1099 # ===========================
913
1100
914 class Namespace(_AttributeHolder):
1101 class Namespace(_AttributeHolder):
1102 """Simple object for storing attributes.
1103
1104 Implements equality by attribute names and values, and provides a simple
1105 string representation.
1106 """
915
1107
916 def __init__(self, **kwargs):
1108 def __init__(self, **kwargs):
917 for name, value in kwargs.iteritems():
1109 for name in kwargs:
918 setattr(self, name, value)
1110 setattr(self, name, kwargs[name])
919
1111
920 def __eq__(self, other):
1112 def __eq__(self, other):
921 return vars(self) == vars(other)
1113 return vars(self) == vars(other)
922
1114
923 def __ne__(self, other):
1115 def __ne__(self, other):
924 return not (self == other)
1116 return not (self == other)
925
1117
926
1118
927 class _ActionsContainer(object):
1119 class _ActionsContainer(object):
1120
928 def __init__(self,
1121 def __init__(self,
929 description,
1122 description,
930 prefix_chars,
1123 prefix_chars,
931 argument_default,
1124 argument_default,
932 conflict_handler):
1125 conflict_handler):
933 super(_ActionsContainer, self).__init__()
1126 super(_ActionsContainer, self).__init__()
934
1127
935 self.description = description
1128 self.description = description
936 self.argument_default = argument_default
1129 self.argument_default = argument_default
937 self.prefix_chars = prefix_chars
1130 self.prefix_chars = prefix_chars
938 self.conflict_handler = conflict_handler
1131 self.conflict_handler = conflict_handler
939
1132
940 # set up registries
1133 # set up registries
941 self._registries = {}
1134 self._registries = {}
942
1135
943 # register actions
1136 # register actions
944 self.register('action', None, _StoreAction)
1137 self.register('action', None, _StoreAction)
945 self.register('action', 'store', _StoreAction)
1138 self.register('action', 'store', _StoreAction)
946 self.register('action', 'store_const', _StoreConstAction)
1139 self.register('action', 'store_const', _StoreConstAction)
947 self.register('action', 'store_true', _StoreTrueAction)
1140 self.register('action', 'store_true', _StoreTrueAction)
948 self.register('action', 'store_false', _StoreFalseAction)
1141 self.register('action', 'store_false', _StoreFalseAction)
949 self.register('action', 'append', _AppendAction)
1142 self.register('action', 'append', _AppendAction)
950 self.register('action', 'append_const', _AppendConstAction)
1143 self.register('action', 'append_const', _AppendConstAction)
951 self.register('action', 'count', _CountAction)
1144 self.register('action', 'count', _CountAction)
952 self.register('action', 'help', _HelpAction)
1145 self.register('action', 'help', _HelpAction)
953 self.register('action', 'version', _VersionAction)
1146 self.register('action', 'version', _VersionAction)
954 self.register('action', 'parsers', _SubParsersAction)
1147 self.register('action', 'parsers', _SubParsersAction)
955
1148
956 # raise an exception if the conflict handler is invalid
1149 # raise an exception if the conflict handler is invalid
957 self._get_handler()
1150 self._get_handler()
958
1151
959 # action storage
1152 # action storage
960 self._optional_actions_list = []
1153 self._actions = []
961 self._positional_actions_list = []
1154 self._option_string_actions = {}
962 self._positional_actions_full_list = []
1155
963 self._option_strings = {}
1156 # groups
1157 self._action_groups = []
1158 self._mutually_exclusive_groups = []
964
1159
965 # defaults storage
1160 # defaults storage
966 self._defaults = {}
1161 self._defaults = {}
967
1162
1163 # determines whether an "option" looks like a negative number
1164 self._negative_number_matcher = _re.compile(r'^-\d+|-\d*.\d+$')
1165
1166 # whether or not there are any optionals that look like negative
1167 # numbers -- uses a list so it can be shared and edited
1168 self._has_negative_number_optionals = []
1169
968 # ====================
1170 # ====================
969 # Registration methods
1171 # Registration methods
970 # ====================
1172 # ====================
971
972 def register(self, registry_name, value, object):
1173 def register(self, registry_name, value, object):
973 registry = self._registries.setdefault(registry_name, {})
1174 registry = self._registries.setdefault(registry_name, {})
974 registry[value] = object
1175 registry[value] = object
975
1176
976 def _registry_get(self, registry_name, value, default=None):
1177 def _registry_get(self, registry_name, value, default=None):
977 return self._registries[registry_name].get(value, default)
1178 return self._registries[registry_name].get(value, default)
978
1179
979 # ==================================
1180 # ==================================
980 # Namespace default settings methods
1181 # Namespace default settings methods
981 # ==================================
1182 # ==================================
982
983 def set_defaults(self, **kwargs):
1183 def set_defaults(self, **kwargs):
984 self._defaults.update(kwargs)
1184 self._defaults.update(kwargs)
985
1185
986 # if these defaults match any existing arguments, replace
1186 # if these defaults match any existing arguments, replace
987 # the previous default on the object with the new one
1187 # the previous default on the object with the new one
988 for action_list in [self._option_strings.values(),
1188 for action in self._actions:
989 self._positional_actions_full_list]:
1189 if action.dest in kwargs:
990 for action in action_list:
1190 action.default = kwargs[action.dest]
991 if action.dest in kwargs:
992 action.default = kwargs[action.dest]
993
1191
994 # =======================
1192 # =======================
995 # Adding argument actions
1193 # Adding argument actions
996 # =======================
1194 # =======================
997
998 def add_argument(self, *args, **kwargs):
1195 def add_argument(self, *args, **kwargs):
999 """
1196 """
1000 add_argument(dest, ..., name=value, ...)
1197 add_argument(dest, ..., name=value, ...)
1001 add_argument(option_string, option_string, ..., name=value, ...)
1198 add_argument(option_string, option_string, ..., name=value, ...)
1002 """
1199 """
1003
1200
1004 # if no positional args are supplied or only one is supplied and
1201 # if no positional args are supplied or only one is supplied and
1005 # it doesn't look like an option string, parse a positional
1202 # it doesn't look like an option string, parse a positional
1006 # argument
1203 # argument
1007 chars = self.prefix_chars
1204 chars = self.prefix_chars
1008 if not args or len(args) == 1 and args[0][0] not in chars:
1205 if not args or len(args) == 1 and args[0][0] not in chars:
1009 kwargs = self._get_positional_kwargs(*args, **kwargs)
1206 kwargs = self._get_positional_kwargs(*args, **kwargs)
1010
1207
1011 # otherwise, we're adding an optional argument
1208 # otherwise, we're adding an optional argument
1012 else:
1209 else:
1013 kwargs = self._get_optional_kwargs(*args, **kwargs)
1210 kwargs = self._get_optional_kwargs(*args, **kwargs)
1014
1211
1015 # if no default was supplied, use the parser-level default
1212 # if no default was supplied, use the parser-level default
1016 if 'default' not in kwargs:
1213 if 'default' not in kwargs:
1017 dest = kwargs['dest']
1214 dest = kwargs['dest']
1018 if dest in self._defaults:
1215 if dest in self._defaults:
1019 kwargs['default'] = self._defaults[dest]
1216 kwargs['default'] = self._defaults[dest]
1020 elif self.argument_default is not None:
1217 elif self.argument_default is not None:
1021 kwargs['default'] = self.argument_default
1218 kwargs['default'] = self.argument_default
1022
1219
1023 # create the action object, and add it to the parser
1220 # create the action object, and add it to the parser
1024 action_class = self._pop_action_class(kwargs)
1221 action_class = self._pop_action_class(kwargs)
1025 action = action_class(**kwargs)
1222 action = action_class(**kwargs)
1026 return self._add_action(action)
1223 return self._add_action(action)
1027
1224
1225 def add_argument_group(self, *args, **kwargs):
1226 group = _ArgumentGroup(self, *args, **kwargs)
1227 self._action_groups.append(group)
1228 return group
1229
1230 def add_mutually_exclusive_group(self, **kwargs):
1231 group = _MutuallyExclusiveGroup(self, **kwargs)
1232 self._mutually_exclusive_groups.append(group)
1233 return group
1234
1028 def _add_action(self, action):
1235 def _add_action(self, action):
1029 # resolve any conflicts
1236 # resolve any conflicts
1030 self._check_conflict(action)
1237 self._check_conflict(action)
1031
1238
1032 # add to optional or positional list
1239 # add to actions list
1033 if action.option_strings:
1240 self._actions.append(action)
1034 self._optional_actions_list.append(action)
1035 else:
1036 self._positional_actions_list.append(action)
1037 self._positional_actions_full_list.append(action)
1038 action.container = self
1241 action.container = self
1039
1242
1040 # index the action by any option strings it has
1243 # index the action by any option strings it has
1041 for option_string in action.option_strings:
1244 for option_string in action.option_strings:
1042 self._option_strings[option_string] = action
1245 self._option_string_actions[option_string] = action
1246
1247 # set the flag if any option strings look like negative numbers
1248 for option_string in action.option_strings:
1249 if self._negative_number_matcher.match(option_string):
1250 if not self._has_negative_number_optionals:
1251 self._has_negative_number_optionals.append(True)
1043
1252
1044 # return the created action
1253 # return the created action
1045 return action
1254 return action
1046
1255
1256 def _remove_action(self, action):
1257 self._actions.remove(action)
1258
1047 def _add_container_actions(self, container):
1259 def _add_container_actions(self, container):
1048 for action in container._optional_actions_list:
1260 # collect groups by titles
1049 self._add_action(action)
1261 title_group_map = {}
1050 for action in container._positional_actions_list:
1262 for group in self._action_groups:
1051 self._add_action(action)
1263 if group.title in title_group_map:
1264 msg = _('cannot merge actions - two groups are named %r')
1265 raise ValueError(msg % (group.title))
1266 title_group_map[group.title] = group
1267
1268 # map each action to its group
1269 group_map = {}
1270 for group in container._action_groups:
1271
1272 # if a group with the title exists, use that, otherwise
1273 # create a new group matching the container's group
1274 if group.title not in title_group_map:
1275 title_group_map[group.title] = self.add_argument_group(
1276 title=group.title,
1277 description=group.description,
1278 conflict_handler=group.conflict_handler)
1279
1280 # map the actions to their new group
1281 for action in group._group_actions:
1282 group_map[action] = title_group_map[group.title]
1283
1284 # add all actions to this container or their group
1285 for action in container._actions:
1286 group_map.get(action, self)._add_action(action)
1052
1287
1053 def _get_positional_kwargs(self, dest, **kwargs):
1288 def _get_positional_kwargs(self, dest, **kwargs):
1054 # make sure required is not specified
1289 # make sure required is not specified
1055 if 'required' in kwargs:
1290 if 'required' in kwargs:
1056 msg = _("'required' is an invalid argument for positionals")
1291 msg = _("'required' is an invalid argument for positionals")
1057 raise TypeError(msg)
1292 raise TypeError(msg)
1058
1293
1294 # mark positional arguments as required if at least one is
1295 # always required
1296 if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
1297 kwargs['required'] = True
1298 if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
1299 kwargs['required'] = True
1300
1059 # return the keyword arguments with no option strings
1301 # return the keyword arguments with no option strings
1060 return dict(kwargs, dest=dest, option_strings=[])
1302 return dict(kwargs, dest=dest, option_strings=[])
1061
1303
1062 def _get_optional_kwargs(self, *args, **kwargs):
1304 def _get_optional_kwargs(self, *args, **kwargs):
1063 # determine short and long option strings
1305 # determine short and long option strings
1064 option_strings = []
1306 option_strings = []
1065 long_option_strings = []
1307 long_option_strings = []
1066 for option_string in args:
1308 for option_string in args:
1067 # error on one-or-fewer-character option strings
1309 # error on one-or-fewer-character option strings
1068 if len(option_string) < 2:
1310 if len(option_string) < 2:
1069 msg = _('invalid option string %r: '
1311 msg = _('invalid option string %r: '
1070 'must be at least two characters long')
1312 'must be at least two characters long')
1071 raise ValueError(msg % option_string)
1313 raise ValueError(msg % option_string)
1072
1314
1073 # error on strings that don't start with an appropriate prefix
1315 # error on strings that don't start with an appropriate prefix
1074 if not option_string[0] in self.prefix_chars:
1316 if not option_string[0] in self.prefix_chars:
1075 msg = _('invalid option string %r: '
1317 msg = _('invalid option string %r: '
1076 'must start with a character %r')
1318 'must start with a character %r')
1077 tup = option_string, self.prefix_chars
1319 tup = option_string, self.prefix_chars
1078 raise ValueError(msg % tup)
1320 raise ValueError(msg % tup)
1079
1321
1080 # error on strings that are all prefix characters
1322 # error on strings that are all prefix characters
1081 if not (set(option_string) - set(self.prefix_chars)):
1323 if not (_set(option_string) - _set(self.prefix_chars)):
1082 msg = _('invalid option string %r: '
1324 msg = _('invalid option string %r: '
1083 'must contain characters other than %r')
1325 'must contain characters other than %r')
1084 tup = option_string, self.prefix_chars
1326 tup = option_string, self.prefix_chars
1085 raise ValueError(msg % tup)
1327 raise ValueError(msg % tup)
1086
1328
1087 # strings starting with two prefix characters are long options
1329 # strings starting with two prefix characters are long options
1088 option_strings.append(option_string)
1330 option_strings.append(option_string)
1089 if option_string[0] in self.prefix_chars:
1331 if option_string[0] in self.prefix_chars:
1090 if option_string[1] in self.prefix_chars:
1332 if option_string[1] in self.prefix_chars:
1091 long_option_strings.append(option_string)
1333 long_option_strings.append(option_string)
1092
1334
1093 # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
1335 # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
1094 dest = kwargs.pop('dest', None)
1336 dest = kwargs.pop('dest', None)
1095 if dest is None:
1337 if dest is None:
1096 if long_option_strings:
1338 if long_option_strings:
1097 dest_option_string = long_option_strings[0]
1339 dest_option_string = long_option_strings[0]
1098 else:
1340 else:
1099 dest_option_string = option_strings[0]
1341 dest_option_string = option_strings[0]
1100 dest = dest_option_string.lstrip(self.prefix_chars)
1342 dest = dest_option_string.lstrip(self.prefix_chars)
1101 dest = dest.replace('-', '_')
1343 dest = dest.replace('-', '_')
1102
1344
1103 # return the updated keyword arguments
1345 # return the updated keyword arguments
1104 return dict(kwargs, dest=dest, option_strings=option_strings)
1346 return dict(kwargs, dest=dest, option_strings=option_strings)
1105
1347
1106 def _pop_action_class(self, kwargs, default=None):
1348 def _pop_action_class(self, kwargs, default=None):
1107 action = kwargs.pop('action', default)
1349 action = kwargs.pop('action', default)
1108 return self._registry_get('action', action, action)
1350 return self._registry_get('action', action, action)
1109
1351
1110 def _get_handler(self):
1352 def _get_handler(self):
1111 # determine function from conflict handler string
1353 # determine function from conflict handler string
1112 handler_func_name = '_handle_conflict_%s' % self.conflict_handler
1354 handler_func_name = '_handle_conflict_%s' % self.conflict_handler
1113 try:
1355 try:
1114 return getattr(self, handler_func_name)
1356 return getattr(self, handler_func_name)
1115 except AttributeError:
1357 except AttributeError:
1116 msg = _('invalid conflict_resolution value: %r')
1358 msg = _('invalid conflict_resolution value: %r')
1117 raise ValueError(msg % self.conflict_handler)
1359 raise ValueError(msg % self.conflict_handler)
1118
1360
1119 def _check_conflict(self, action):
1361 def _check_conflict(self, action):
1120
1362
1121 # find all options that conflict with this option
1363 # find all options that conflict with this option
1122 confl_optionals = []
1364 confl_optionals = []
1123 for option_string in action.option_strings:
1365 for option_string in action.option_strings:
1124 if option_string in self._option_strings:
1366 if option_string in self._option_string_actions:
1125 confl_optional = self._option_strings[option_string]
1367 confl_optional = self._option_string_actions[option_string]
1126 confl_optionals.append((option_string, confl_optional))
1368 confl_optionals.append((option_string, confl_optional))
1127
1369
1128 # resolve any conflicts
1370 # resolve any conflicts
1129 if confl_optionals:
1371 if confl_optionals:
1130 conflict_handler = self._get_handler()
1372 conflict_handler = self._get_handler()
1131 conflict_handler(action, confl_optionals)
1373 conflict_handler(action, confl_optionals)
1132
1374
1133 def _handle_conflict_error(self, action, conflicting_actions):
1375 def _handle_conflict_error(self, action, conflicting_actions):
1134 message = _('conflicting option string(s): %s')
1376 message = _('conflicting option string(s): %s')
1135 conflict_string = ', '.join(option_string
1377 conflict_string = ', '.join([option_string
1136 for option_string, action
1378 for option_string, action
1137 in conflicting_actions)
1379 in conflicting_actions])
1138 raise ArgumentError(action, message % conflict_string)
1380 raise ArgumentError(action, message % conflict_string)
1139
1381
1140 def _handle_conflict_resolve(self, action, conflicting_actions):
1382 def _handle_conflict_resolve(self, action, conflicting_actions):
1141
1383
1142 # remove all conflicting options
1384 # remove all conflicting options
1143 for option_string, action in conflicting_actions:
1385 for option_string, action in conflicting_actions:
1144
1386
1145 # remove the conflicting option
1387 # remove the conflicting option
1146 action.option_strings.remove(option_string)
1388 action.option_strings.remove(option_string)
1147 self._option_strings.pop(option_string, None)
1389 self._option_string_actions.pop(option_string, None)
1148
1390
1149 # if the option now has no option string, remove it from the
1391 # if the option now has no option string, remove it from the
1150 # container holding it
1392 # container holding it
1151 if not action.option_strings:
1393 if not action.option_strings:
1152 action.container._optional_actions_list.remove(action)
1394 action.container._remove_action(action)
1153
1395
1154
1396
1155 class _ArgumentGroup(_ActionsContainer):
1397 class _ArgumentGroup(_ActionsContainer):
1156
1398
1157 def __init__(self, container, title=None, description=None, **kwargs):
1399 def __init__(self, container, title=None, description=None, **kwargs):
1158 # add any missing keyword arguments by checking the container
1400 # add any missing keyword arguments by checking the container
1159 update = kwargs.setdefault
1401 update = kwargs.setdefault
1160 update('conflict_handler', container.conflict_handler)
1402 update('conflict_handler', container.conflict_handler)
1161 update('prefix_chars', container.prefix_chars)
1403 update('prefix_chars', container.prefix_chars)
1162 update('argument_default', container.argument_default)
1404 update('argument_default', container.argument_default)
1163 super_init = super(_ArgumentGroup, self).__init__
1405 super_init = super(_ArgumentGroup, self).__init__
1164 super_init(description=description, **kwargs)
1406 super_init(description=description, **kwargs)
1165
1407
1408 # group attributes
1166 self.title = title
1409 self.title = title
1410 self._group_actions = []
1411
1412 # share most attributes with the container
1167 self._registries = container._registries
1413 self._registries = container._registries
1168 self._positional_actions_full_list = container._positional_actions_full_list
1414 self._actions = container._actions
1169 self._option_strings = container._option_strings
1415 self._option_string_actions = container._option_string_actions
1170 self._defaults = container._defaults
1416 self._defaults = container._defaults
1417 self._has_negative_number_optionals = \
1418 container._has_negative_number_optionals
1419
1420 def _add_action(self, action):
1421 action = super(_ArgumentGroup, self)._add_action(action)
1422 self._group_actions.append(action)
1423 return action
1424
1425 def _remove_action(self, action):
1426 super(_ArgumentGroup, self)._remove_action(action)
1427 self._group_actions.remove(action)
1428
1429
1430 class _MutuallyExclusiveGroup(_ArgumentGroup):
1431
1432 def __init__(self, container, required=False):
1433 super(_MutuallyExclusiveGroup, self).__init__(container)
1434 self.required = required
1435 self._container = container
1436
1437 def _add_action(self, action):
1438 if action.required:
1439 msg = _('mutually exclusive arguments must be optional')
1440 raise ValueError(msg)
1441 action = self._container._add_action(action)
1442 self._group_actions.append(action)
1443 return action
1444
1445 def _remove_action(self, action):
1446 self._container._remove_action(action)
1447 self._group_actions.remove(action)
1171
1448
1172
1449
1173 class ArgumentParser(_AttributeHolder, _ActionsContainer):
1450 class ArgumentParser(_AttributeHolder, _ActionsContainer):
1451 """Object for parsing command line strings into Python objects.
1452
1453 Keyword Arguments:
1454 - prog -- The name of the program (default: sys.argv[0])
1455 - usage -- A usage message (default: auto-generated from arguments)
1456 - description -- A description of what the program does
1457 - epilog -- Text following the argument descriptions
1458 - version -- Add a -v/--version option with the given version string
1459 - parents -- Parsers whose arguments should be copied into this one
1460 - formatter_class -- HelpFormatter class for printing help messages
1461 - prefix_chars -- Characters that prefix optional arguments
1462 - fromfile_prefix_chars -- Characters that prefix files containing
1463 additional arguments
1464 - argument_default -- The default value for all arguments
1465 - conflict_handler -- String indicating how to handle conflicts
1466 - add_help -- Add a -h/-help option
1467 """
1174
1468
1175 def __init__(self,
1469 def __init__(self,
1176 prog=None,
1470 prog=None,
1177 usage=None,
1471 usage=None,
1178 description=None,
1472 description=None,
1179 epilog=None,
1473 epilog=None,
1180 version=None,
1474 version=None,
1181 parents=[],
1475 parents=[],
1182 formatter_class=HelpFormatter,
1476 formatter_class=HelpFormatter,
1183 prefix_chars='-',
1477 prefix_chars='-',
1478 fromfile_prefix_chars=None,
1184 argument_default=None,
1479 argument_default=None,
1185 conflict_handler='error',
1480 conflict_handler='error',
1186 add_help=True):
1481 add_help=True):
1187
1482
1188 superinit = super(ArgumentParser, self).__init__
1483 superinit = super(ArgumentParser, self).__init__
1189 superinit(description=description,
1484 superinit(description=description,
1190 prefix_chars=prefix_chars,
1485 prefix_chars=prefix_chars,
1191 argument_default=argument_default,
1486 argument_default=argument_default,
1192 conflict_handler=conflict_handler)
1487 conflict_handler=conflict_handler)
1193
1488
1194 # default setting for prog
1489 # default setting for prog
1195 if prog is None:
1490 if prog is None:
1196 prog = _os.path.basename(_sys.argv[0])
1491 prog = _os.path.basename(_sys.argv[0])
1197
1492
1198 self.prog = prog
1493 self.prog = prog
1199 self.usage = usage
1494 self.usage = usage
1200 self.epilog = epilog
1495 self.epilog = epilog
1201 self.version = version
1496 self.version = version
1202 self.formatter_class = formatter_class
1497 self.formatter_class = formatter_class
1498 self.fromfile_prefix_chars = fromfile_prefix_chars
1203 self.add_help = add_help
1499 self.add_help = add_help
1204
1500
1205 self._argument_group_class = _ArgumentGroup
1501 add_group = self.add_argument_group
1206 self._has_subparsers = False
1502 self._positionals = add_group(_('positional arguments'))
1207 self._argument_groups = []
1503 self._optionals = add_group(_('optional arguments'))
1504 self._subparsers = None
1208
1505
1209 # register types
1506 # register types
1210 def identity(string):
1507 def identity(string):
1211 return string
1508 return string
1212 self.register('type', None, identity)
1509 self.register('type', None, identity)
1213
1510
1214 # add help and version arguments if necessary
1511 # add help and version arguments if necessary
1215 # (using explicit default to override global argument_default)
1512 # (using explicit default to override global argument_default)
1216 if self.add_help:
1513 if self.add_help:
1217 self.add_argument(
1514 self.add_argument(
1218 '-h', '--help', action='help', default=SUPPRESS,
1515 '-h', '--help', action='help', default=SUPPRESS,
1219 help=_('show this help message and exit'))
1516 help=_('show this help message and exit'))
1220 if self.version:
1517 if self.version:
1221 self.add_argument(
1518 self.add_argument(
1222 '-v', '--version', action='version', default=SUPPRESS,
1519 '-v', '--version', action='version', default=SUPPRESS,
1223 help=_("show program's version number and exit"))
1520 help=_("show program's version number and exit"))
1224
1521
1225 # add parent arguments and defaults
1522 # add parent arguments and defaults
1226 for parent in parents:
1523 for parent in parents:
1227 self._add_container_actions(parent)
1524 self._add_container_actions(parent)
1228 try:
1525 try:
1229 defaults = parent._defaults
1526 defaults = parent._defaults
1230 except AttributeError:
1527 except AttributeError:
1231 pass
1528 pass
1232 else:
1529 else:
1233 self._defaults.update(defaults)
1530 self._defaults.update(defaults)
1234
1531
1235 # determines whether an "option" looks like a negative number
1236 self._negative_number_matcher = _re.compile(r'^-\d+|-\d*.\d+$')
1237
1238
1239 # =======================
1532 # =======================
1240 # Pretty __repr__ methods
1533 # Pretty __repr__ methods
1241 # =======================
1534 # =======================
1242
1243 def _get_kwargs(self):
1535 def _get_kwargs(self):
1244 names = [
1536 names = [
1245 'prog',
1537 'prog',
1246 'usage',
1538 'usage',
1247 'description',
1539 'description',
1248 'version',
1540 'version',
1249 'formatter_class',
1541 'formatter_class',
1250 'conflict_handler',
1542 'conflict_handler',
1251 'add_help',
1543 'add_help',
1252 ]
1544 ]
1253 return [(name, getattr(self, name)) for name in names]
1545 return [(name, getattr(self, name)) for name in names]
1254
1546
1255 # ==================================
1547 # ==================================
1256 # Optional/Positional adding methods
1548 # Optional/Positional adding methods
1257 # ==================================
1549 # ==================================
1258
1259 def add_argument_group(self, *args, **kwargs):
1260 group = self._argument_group_class(self, *args, **kwargs)
1261 self._argument_groups.append(group)
1262 return group
1263
1264 def add_subparsers(self, **kwargs):
1550 def add_subparsers(self, **kwargs):
1265 if self._has_subparsers:
1551 if self._subparsers is not None:
1266 self.error(_('cannot have multiple subparser arguments'))
1552 self.error(_('cannot have multiple subparser arguments'))
1267
1553
1268 # add the parser class to the arguments if it's not present
1554 # add the parser class to the arguments if it's not present
1269 kwargs.setdefault('parser_class', type(self))
1555 kwargs.setdefault('parser_class', type(self))
1270
1556
1557 if 'title' in kwargs or 'description' in kwargs:
1558 title = _(kwargs.pop('title', 'subcommands'))
1559 description = _(kwargs.pop('description', None))
1560 self._subparsers = self.add_argument_group(title, description)
1561 else:
1562 self._subparsers = self._positionals
1563
1271 # prog defaults to the usage message of this parser, skipping
1564 # prog defaults to the usage message of this parser, skipping
1272 # optional arguments and with no "usage:" prefix
1565 # optional arguments and with no "usage:" prefix
1273 if kwargs.get('prog') is None:
1566 if kwargs.get('prog') is None:
1274 formatter = self._get_formatter()
1567 formatter = self._get_formatter()
1275 formatter.add_usage(self.usage, [],
1568 positionals = self._get_positional_actions()
1276 self._get_positional_actions(), '')
1569 groups = self._mutually_exclusive_groups
1570 formatter.add_usage(self.usage, positionals, groups, '')
1277 kwargs['prog'] = formatter.format_help().strip()
1571 kwargs['prog'] = formatter.format_help().strip()
1278
1572
1279 # create the parsers action and add it to the positionals list
1573 # create the parsers action and add it to the positionals list
1280 parsers_class = self._pop_action_class(kwargs, 'parsers')
1574 parsers_class = self._pop_action_class(kwargs, 'parsers')
1281 action = parsers_class(option_strings=[], **kwargs)
1575 action = parsers_class(option_strings=[], **kwargs)
1282 self._positional_actions_list.append(action)
1576 self._subparsers._add_action(action)
1283 self._positional_actions_full_list.append(action)
1284 self._has_subparsers = True
1285
1577
1286 # return the created parsers action
1578 # return the created parsers action
1287 return action
1579 return action
1288
1580
1289 def _add_container_actions(self, container):
1581 def _add_action(self, action):
1290 super(ArgumentParser, self)._add_container_actions(container)
1582 if action.option_strings:
1291 try:
1583 self._optionals._add_action(action)
1292 groups = container._argument_groups
1293 except AttributeError:
1294 pass
1295 else:
1584 else:
1296 for group in groups:
1585 self._positionals._add_action(action)
1297 new_group = self.add_argument_group(
1586 return action
1298 title=group.title,
1299 description=group.description,
1300 conflict_handler=group.conflict_handler)
1301 new_group._add_container_actions(group)
1302
1587
1303 def _get_optional_actions(self):
1588 def _get_optional_actions(self):
1304 actions = []
1589 return [action
1305 actions.extend(self._optional_actions_list)
1590 for action in self._actions
1306 for argument_group in self._argument_groups:
1591 if action.option_strings]
1307 actions.extend(argument_group._optional_actions_list)
1308 return actions
1309
1592
1310 def _get_positional_actions(self):
1593 def _get_positional_actions(self):
1311 return list(self._positional_actions_full_list)
1594 return [action
1312
1595 for action in self._actions
1596 if not action.option_strings]
1313
1597
1314 # =====================================
1598 # =====================================
1315 # Command line argument parsing methods
1599 # Command line argument parsing methods
1316 # =====================================
1600 # =====================================
1317
1318 def parse_args(self, args=None, namespace=None):
1601 def parse_args(self, args=None, namespace=None):
1602 args, argv = self.parse_known_args(args, namespace)
1603 if argv:
1604 msg = _('unrecognized arguments: %s')
1605 self.error(msg % ' '.join(argv))
1606 return args
1607
1608 def parse_known_args(self, args=None, namespace=None):
1319 # args default to the system args
1609 # args default to the system args
1320 if args is None:
1610 if args is None:
1321 args = _sys.argv[1:]
1611 args = _sys.argv[1:]
1322
1612
1323 # default Namespace built from parser defaults
1613 # default Namespace built from parser defaults
1324 if namespace is None:
1614 if namespace is None:
1325 namespace = Namespace()
1615 namespace = Namespace()
1326
1616
1327 # add any action defaults that aren't present
1617 # add any action defaults that aren't present
1328 optional_actions = self._get_optional_actions()
1618 for action in self._actions:
1329 positional_actions = self._get_positional_actions()
1330 for action in optional_actions + positional_actions:
1331 if action.dest is not SUPPRESS:
1619 if action.dest is not SUPPRESS:
1332 if not hasattr(namespace, action.dest):
1620 if not hasattr(namespace, action.dest):
1333 if action.default is not SUPPRESS:
1621 if action.default is not SUPPRESS:
1334 default = action.default
1622 default = action.default
1335 if isinstance(action.default, basestring):
1623 if isinstance(action.default, _basestring):
1336 default = self._get_value(action, default)
1624 default = self._get_value(action, default)
1337 setattr(namespace, action.dest, default)
1625 setattr(namespace, action.dest, default)
1338
1626
1339 # add any parser defaults that aren't present
1627 # add any parser defaults that aren't present
1340 for dest, value in self._defaults.iteritems():
1628 for dest in self._defaults:
1341 if not hasattr(namespace, dest):
1629 if not hasattr(namespace, dest):
1342 setattr(namespace, dest, value)
1630 setattr(namespace, dest, self._defaults[dest])
1343
1631
1344 # parse the arguments and exit if there are any errors
1632 # parse the arguments and exit if there are any errors
1345 try:
1633 try:
1346 result = self._parse_args(args, namespace)
1634 return self._parse_known_args(args, namespace)
1347 except ArgumentError, err:
1635 except ArgumentError:
1636 err = _sys.exc_info()[1]
1348 self.error(str(err))
1637 self.error(str(err))
1349
1638
1350 # make sure all required optionals are present
1639 def _parse_known_args(self, arg_strings, namespace):
1351 for action in self._get_optional_actions():
1640 # replace arg strings that are file references
1352 if action.required:
1641 if self.fromfile_prefix_chars is not None:
1353 if getattr(result, action.dest, None) is None:
1642 arg_strings = self._read_args_from_files(arg_strings)
1354 opt_strs = '/'.join(action.option_strings)
1643
1355 msg = _('option %s is required' % opt_strs)
1644 # map all mutually exclusive arguments to the other arguments
1356 self.error(msg)
1645 # they can't occur with
1357
1646 action_conflicts = {}
1358 # return the parsed arguments
1647 for mutex_group in self._mutually_exclusive_groups:
1359 return result
1648 group_actions = mutex_group._group_actions
1360
1649 for i, mutex_action in enumerate(mutex_group._group_actions):
1361 def _parse_args(self, arg_strings, namespace):
1650 conflicts = action_conflicts.setdefault(mutex_action, [])
1651 conflicts.extend(group_actions[:i])
1652 conflicts.extend(group_actions[i + 1:])
1362
1653
1363 # find all option indices, and determine the arg_string_pattern
1654 # find all option indices, and determine the arg_string_pattern
1364 # which has an 'O' if there is an option at an index,
1655 # which has an 'O' if there is an option at an index,
1365 # an 'A' if there is an argument, or a '-' if there is a '--'
1656 # an 'A' if there is an argument, or a '-' if there is a '--'
1366 option_string_indices = {}
1657 option_string_indices = {}
1367 arg_string_pattern_parts = []
1658 arg_string_pattern_parts = []
1368 arg_strings_iter = iter(arg_strings)
1659 arg_strings_iter = iter(arg_strings)
1369 for i, arg_string in enumerate(arg_strings_iter):
1660 for i, arg_string in enumerate(arg_strings_iter):
1370
1661
1371 # all args after -- are non-options
1662 # all args after -- are non-options
1372 if arg_string == '--':
1663 if arg_string == '--':
1373 arg_string_pattern_parts.append('-')
1664 arg_string_pattern_parts.append('-')
1374 for arg_string in arg_strings_iter:
1665 for arg_string in arg_strings_iter:
1375 arg_string_pattern_parts.append('A')
1666 arg_string_pattern_parts.append('A')
1376
1667
1377 # otherwise, add the arg to the arg strings
1668 # otherwise, add the arg to the arg strings
1378 # and note the index if it was an option
1669 # and note the index if it was an option
1379 else:
1670 else:
1380 option_tuple = self._parse_optional(arg_string)
1671 option_tuple = self._parse_optional(arg_string)
1381 if option_tuple is None:
1672 if option_tuple is None:
1382 pattern = 'A'
1673 pattern = 'A'
1383 else:
1674 else:
1384 option_string_indices[i] = option_tuple
1675 option_string_indices[i] = option_tuple
1385 pattern = 'O'
1676 pattern = 'O'
1386 arg_string_pattern_parts.append(pattern)
1677 arg_string_pattern_parts.append(pattern)
1387
1678
1388 # join the pieces together to form the pattern
1679 # join the pieces together to form the pattern
1389 arg_strings_pattern = ''.join(arg_string_pattern_parts)
1680 arg_strings_pattern = ''.join(arg_string_pattern_parts)
1390
1681
1391 # converts arg strings to the appropriate and then takes the action
1682 # converts arg strings to the appropriate and then takes the action
1683 seen_actions = _set()
1684 seen_non_default_actions = _set()
1685
1392 def take_action(action, argument_strings, option_string=None):
1686 def take_action(action, argument_strings, option_string=None):
1687 seen_actions.add(action)
1393 argument_values = self._get_values(action, argument_strings)
1688 argument_values = self._get_values(action, argument_strings)
1689
1690 # error if this argument is not allowed with other previously
1691 # seen arguments, assuming that actions that use the default
1692 # value don't really count as "present"
1693 if argument_values is not action.default:
1694 seen_non_default_actions.add(action)
1695 for conflict_action in action_conflicts.get(action, []):
1696 if conflict_action in seen_non_default_actions:
1697 msg = _('not allowed with argument %s')
1698 action_name = _get_action_name(conflict_action)
1699 raise ArgumentError(action, msg % action_name)
1700
1394 # take the action if we didn't receive a SUPPRESS value
1701 # take the action if we didn't receive a SUPPRESS value
1395 # (e.g. from a default)
1702 # (e.g. from a default)
1396 if argument_values is not SUPPRESS:
1703 if argument_values is not SUPPRESS:
1397 action(self, namespace, argument_values, option_string)
1704 action(self, namespace, argument_values, option_string)
1398
1705
1399 # function to convert arg_strings into an optional action
1706 # function to convert arg_strings into an optional action
1400 def consume_optional(start_index):
1707 def consume_optional(start_index):
1401
1708
1402 # determine the optional action and parse any explicit
1709 # get the optional identified at this index
1403 # argument out of the option string
1404 option_tuple = option_string_indices[start_index]
1710 option_tuple = option_string_indices[start_index]
1405 action, option_string, explicit_arg = option_tuple
1711 action, option_string, explicit_arg = option_tuple
1406
1712
1407 # loop because single-dash options can be chained
1713 # identify additional optionals in the same arg string
1408 # (e.g. -xyz is the same as -x -y -z if no args are required)
1714 # (e.g. -xyz is the same as -x -y -z if no args are required)
1409 match_argument = self._match_argument
1715 match_argument = self._match_argument
1410 action_tuples = []
1716 action_tuples = []
1411 while True:
1717 while True:
1412
1718
1413 # if we found no optional action, raise an error
1719 # if we found no optional action, skip it
1414 if action is None:
1720 if action is None:
1415 self.error(_('no such option: %s') % option_string)
1721 extras.append(arg_strings[start_index])
1722 return start_index + 1
1416
1723
1417 # if there is an explicit argument, try to match the
1724 # if there is an explicit argument, try to match the
1418 # optional's string arguments to only this
1725 # optional's string arguments to only this
1419 if explicit_arg is not None:
1726 if explicit_arg is not None:
1420 arg_count = match_argument(action, 'A')
1727 arg_count = match_argument(action, 'A')
1421
1728
1422 # if the action is a single-dash option and takes no
1729 # if the action is a single-dash option and takes no
1423 # arguments, try to parse more single-dash options out
1730 # arguments, try to parse more single-dash options out
1424 # of the tail of the option string
1731 # of the tail of the option string
1425 chars = self.prefix_chars
1732 chars = self.prefix_chars
1426 if arg_count == 0 and option_string[1] not in chars:
1733 if arg_count == 0 and option_string[1] not in chars:
1427 action_tuples.append((action, [], option_string))
1734 action_tuples.append((action, [], option_string))
1428 parse_optional = self._parse_optional
1429 for char in self.prefix_chars:
1735 for char in self.prefix_chars:
1430 option_string = char + explicit_arg
1736 option_string = char + explicit_arg[0]
1431 option_tuple = parse_optional(option_string)
1737 explicit_arg = explicit_arg[1:] or None
1432 if option_tuple[0] is not None:
1738 optionals_map = self._option_string_actions
1739 if option_string in optionals_map:
1740 action = optionals_map[option_string]
1433 break
1741 break
1434 else:
1742 else:
1435 msg = _('ignored explicit argument %r')
1743 msg = _('ignored explicit argument %r')
1436 raise ArgumentError(action, msg % explicit_arg)
1744 raise ArgumentError(action, msg % explicit_arg)
1437
1745
1438 # set the action, etc. for the next loop iteration
1439 action, option_string, explicit_arg = option_tuple
1440
1441 # if the action expect exactly one argument, we've
1746 # if the action expect exactly one argument, we've
1442 # successfully matched the option; exit the loop
1747 # successfully matched the option; exit the loop
1443 elif arg_count == 1:
1748 elif arg_count == 1:
1444 stop = start_index + 1
1749 stop = start_index + 1
1445 args = [explicit_arg]
1750 args = [explicit_arg]
1446 action_tuples.append((action, args, option_string))
1751 action_tuples.append((action, args, option_string))
1447 break
1752 break
1448
1753
1449 # error if a double-dash option did not use the
1754 # error if a double-dash option did not use the
1450 # explicit argument
1755 # explicit argument
1451 else:
1756 else:
1452 msg = _('ignored explicit argument %r')
1757 msg = _('ignored explicit argument %r')
1453 raise ArgumentError(action, msg % explicit_arg)
1758 raise ArgumentError(action, msg % explicit_arg)
1454
1759
1455 # if there is no explicit argument, try to match the
1760 # if there is no explicit argument, try to match the
1456 # optional's string arguments with the following strings
1761 # optional's string arguments with the following strings
1457 # if successful, exit the loop
1762 # if successful, exit the loop
1458 else:
1763 else:
1459 start = start_index + 1
1764 start = start_index + 1
1460 selected_patterns = arg_strings_pattern[start:]
1765 selected_patterns = arg_strings_pattern[start:]
1461 arg_count = match_argument(action, selected_patterns)
1766 arg_count = match_argument(action, selected_patterns)
1462 stop = start + arg_count
1767 stop = start + arg_count
1463 args = arg_strings[start:stop]
1768 args = arg_strings[start:stop]
1464 action_tuples.append((action, args, option_string))
1769 action_tuples.append((action, args, option_string))
1465 break
1770 break
1466
1771
1467 # add the Optional to the list and return the index at which
1772 # add the Optional to the list and return the index at which
1468 # the Optional's string args stopped
1773 # the Optional's string args stopped
1469 assert action_tuples
1774 assert action_tuples
1470 for action, args, option_string in action_tuples:
1775 for action, args, option_string in action_tuples:
1471 take_action(action, args, option_string)
1776 take_action(action, args, option_string)
1472 return stop
1777 return stop
1473
1778
1474 # the list of Positionals left to be parsed; this is modified
1779 # the list of Positionals left to be parsed; this is modified
1475 # by consume_positionals()
1780 # by consume_positionals()
1476 positionals = self._get_positional_actions()
1781 positionals = self._get_positional_actions()
1477
1782
1478 # function to convert arg_strings into positional actions
1783 # function to convert arg_strings into positional actions
1479 def consume_positionals(start_index):
1784 def consume_positionals(start_index):
1480 # match as many Positionals as possible
1785 # match as many Positionals as possible
1481 match_partial = self._match_arguments_partial
1786 match_partial = self._match_arguments_partial
1482 selected_pattern = arg_strings_pattern[start_index:]
1787 selected_pattern = arg_strings_pattern[start_index:]
1483 arg_counts = match_partial(positionals, selected_pattern)
1788 arg_counts = match_partial(positionals, selected_pattern)
1484
1789
1485 # slice off the appropriate arg strings for each Positional
1790 # slice off the appropriate arg strings for each Positional
1486 # and add the Positional and its args to the list
1791 # and add the Positional and its args to the list
1487 for action, arg_count in zip(positionals, arg_counts):
1792 for action, arg_count in zip(positionals, arg_counts):
1488 args = arg_strings[start_index: start_index + arg_count]
1793 args = arg_strings[start_index: start_index + arg_count]
1489 start_index += arg_count
1794 start_index += arg_count
1490 take_action(action, args)
1795 take_action(action, args)
1491
1796
1492 # slice off the Positionals that we just parsed and return the
1797 # slice off the Positionals that we just parsed and return the
1493 # index at which the Positionals' string args stopped
1798 # index at which the Positionals' string args stopped
1494 positionals[:] = positionals[len(arg_counts):]
1799 positionals[:] = positionals[len(arg_counts):]
1495 return start_index
1800 return start_index
1496
1801
1497 # consume Positionals and Optionals alternately, until we have
1802 # consume Positionals and Optionals alternately, until we have
1498 # passed the last option string
1803 # passed the last option string
1804 extras = []
1499 start_index = 0
1805 start_index = 0
1500 if option_string_indices:
1806 if option_string_indices:
1501 max_option_string_index = max(option_string_indices)
1807 max_option_string_index = max(option_string_indices)
1502 else:
1808 else:
1503 max_option_string_index = -1
1809 max_option_string_index = -1
1504 while start_index <= max_option_string_index:
1810 while start_index <= max_option_string_index:
1505
1811
1506 # consume any Positionals preceding the next option
1812 # consume any Positionals preceding the next option
1507 next_option_string_index = min(
1813 next_option_string_index = min([
1508 index
1814 index
1509 for index in option_string_indices
1815 for index in option_string_indices
1510 if index >= start_index)
1816 if index >= start_index])
1511 if start_index != next_option_string_index:
1817 if start_index != next_option_string_index:
1512 positionals_end_index = consume_positionals(start_index)
1818 positionals_end_index = consume_positionals(start_index)
1513
1819
1514 # only try to parse the next optional if we didn't consume
1820 # only try to parse the next optional if we didn't consume
1515 # the option string during the positionals parsing
1821 # the option string during the positionals parsing
1516 if positionals_end_index > start_index:
1822 if positionals_end_index > start_index:
1517 start_index = positionals_end_index
1823 start_index = positionals_end_index
1518 continue
1824 continue
1519 else:
1825 else:
1520 start_index = positionals_end_index
1826 start_index = positionals_end_index
1521
1827
1522 # if we consumed all the positionals we could and we're not
1828 # if we consumed all the positionals we could and we're not
1523 # at the index of an option string, there were unparseable
1829 # at the index of an option string, there were extra arguments
1524 # arguments
1525 if start_index not in option_string_indices:
1830 if start_index not in option_string_indices:
1526 msg = _('extra arguments found: %s')
1831 strings = arg_strings[start_index:next_option_string_index]
1527 extras = arg_strings[start_index:next_option_string_index]
1832 extras.extend(strings)
1528 self.error(msg % ' '.join(extras))
1833 start_index = next_option_string_index
1529
1834
1530 # consume the next optional and any arguments for it
1835 # consume the next optional and any arguments for it
1531 start_index = consume_optional(start_index)
1836 start_index = consume_optional(start_index)
1532
1837
1533 # consume any positionals following the last Optional
1838 # consume any positionals following the last Optional
1534 stop_index = consume_positionals(start_index)
1839 stop_index = consume_positionals(start_index)
1535
1840
1536 # if we didn't consume all the argument strings, there were too
1841 # if we didn't consume all the argument strings, there were extras
1537 # many supplied
1842 extras.extend(arg_strings[stop_index:])
1538 if stop_index != len(arg_strings):
1539 extras = arg_strings[stop_index:]
1540 self.error(_('extra arguments found: %s') % ' '.join(extras))
1541
1843
1542 # if we didn't use all the Positional objects, there were too few
1844 # if we didn't use all the Positional objects, there were too few
1543 # arg strings supplied.
1845 # arg strings supplied.
1544 if positionals:
1846 if positionals:
1545 self.error(_('too few arguments'))
1847 self.error(_('too few arguments'))
1546
1848
1547 # return the updated namespace
1849 # make sure all required actions were present
1548 return namespace
1850 for action in self._actions:
1851 if action.required:
1852 if action not in seen_actions:
1853 name = _get_action_name(action)
1854 self.error(_('argument %s is required') % name)
1855
1856 # make sure all required groups had one option present
1857 for group in self._mutually_exclusive_groups:
1858 if group.required:
1859 for action in group._group_actions:
1860 if action in seen_non_default_actions:
1861 break
1862
1863 # if no actions were used, report the error
1864 else:
1865 names = [_get_action_name(action)
1866 for action in group._group_actions
1867 if action.help is not SUPPRESS]
1868 msg = _('one of the arguments %s is required')
1869 self.error(msg % ' '.join(names))
1870
1871 # return the updated namespace and the extra arguments
1872 return namespace, extras
1873
1874 def _read_args_from_files(self, arg_strings):
1875 # expand arguments referencing files
1876 new_arg_strings = []
1877 for arg_string in arg_strings:
1878
1879 # for regular arguments, just add them back into the list
1880 if arg_string[0] not in self.fromfile_prefix_chars:
1881 new_arg_strings.append(arg_string)
1882
1883 # replace arguments referencing files with the file content
1884 else:
1885 try:
1886 args_file = open(arg_string[1:])
1887 try:
1888 arg_strings = args_file.read().splitlines()
1889 arg_strings = self._read_args_from_files(arg_strings)
1890 new_arg_strings.extend(arg_strings)
1891 finally:
1892 args_file.close()
1893 except IOError:
1894 err = _sys.exc_info()[1]
1895 self.error(str(err))
1896
1897 # return the modified argument list
1898 return new_arg_strings
1549
1899
1550 def _match_argument(self, action, arg_strings_pattern):
1900 def _match_argument(self, action, arg_strings_pattern):
1551 # match the pattern for this action to the arg strings
1901 # match the pattern for this action to the arg strings
1552 nargs_pattern = self._get_nargs_pattern(action)
1902 nargs_pattern = self._get_nargs_pattern(action)
1553 match = _re.match(nargs_pattern, arg_strings_pattern)
1903 match = _re.match(nargs_pattern, arg_strings_pattern)
1554
1904
1555 # raise an exception if we weren't able to find a match
1905 # raise an exception if we weren't able to find a match
1556 if match is None:
1906 if match is None:
1557 nargs_errors = {
1907 nargs_errors = {
1558 None:_('expected one argument'),
1908 None: _('expected one argument'),
1559 OPTIONAL:_('expected at most one argument'),
1909 OPTIONAL: _('expected at most one argument'),
1560 ONE_OR_MORE:_('expected at least one argument')
1910 ONE_OR_MORE: _('expected at least one argument'),
1561 }
1911 }
1562 default = _('expected %s argument(s)') % action.nargs
1912 default = _('expected %s argument(s)') % action.nargs
1563 msg = nargs_errors.get(action.nargs, default)
1913 msg = nargs_errors.get(action.nargs, default)
1564 raise ArgumentError(action, msg)
1914 raise ArgumentError(action, msg)
1565
1915
1566 # return the number of arguments matched
1916 # return the number of arguments matched
1567 return len(match.group(1))
1917 return len(match.group(1))
1568
1918
1569 def _match_arguments_partial(self, actions, arg_strings_pattern):
1919 def _match_arguments_partial(self, actions, arg_strings_pattern):
1570 # progressively shorten the actions list by slicing off the
1920 # progressively shorten the actions list by slicing off the
1571 # final actions until we find a match
1921 # final actions until we find a match
1572 result = []
1922 result = []
1573 for i in xrange(len(actions), 0, -1):
1923 for i in range(len(actions), 0, -1):
1574 actions_slice = actions[:i]
1924 actions_slice = actions[:i]
1575 pattern = ''.join(self._get_nargs_pattern(action)
1925 pattern = ''.join([self._get_nargs_pattern(action)
1576 for action in actions_slice)
1926 for action in actions_slice])
1577 match = _re.match(pattern, arg_strings_pattern)
1927 match = _re.match(pattern, arg_strings_pattern)
1578 if match is not None:
1928 if match is not None:
1579 result.extend(len(string) for string in match.groups())
1929 result.extend([len(string) for string in match.groups()])
1580 break
1930 break
1581
1931
1582 # return the list of arg string counts
1932 # return the list of arg string counts
1583 return result
1933 return result
1584
1934
1585 def _parse_optional(self, arg_string):
1935 def _parse_optional(self, arg_string):
1936 # if it's an empty string, it was meant to be a positional
1937 if not arg_string:
1938 return None
1939
1586 # if it doesn't start with a prefix, it was meant to be positional
1940 # if it doesn't start with a prefix, it was meant to be positional
1587 if not arg_string[0] in self.prefix_chars:
1941 if not arg_string[0] in self.prefix_chars:
1588 return None
1942 return None
1589
1943
1590 # if it's just dashes, it was meant to be positional
1944 # if it's just dashes, it was meant to be positional
1591 if not arg_string.strip('-'):
1945 if not arg_string.strip('-'):
1592 return None
1946 return None
1593
1947
1594 # if the option string is present in the parser, return the action
1948 # if the option string is present in the parser, return the action
1595 if arg_string in self._option_strings:
1949 if arg_string in self._option_string_actions:
1596 action = self._option_strings[arg_string]
1950 action = self._option_string_actions[arg_string]
1597 return action, arg_string, None
1951 return action, arg_string, None
1598
1952
1599 # search through all possible prefixes of the option string
1953 # search through all possible prefixes of the option string
1600 # and all actions in the parser for possible interpretations
1954 # and all actions in the parser for possible interpretations
1601 option_tuples = []
1955 option_tuples = self._get_option_tuples(arg_string)
1602 prefix_tuples = self._get_option_prefix_tuples(arg_string)
1603 for option_string in self._option_strings:
1604 for option_prefix, explicit_arg in prefix_tuples:
1605 if option_string.startswith(option_prefix):
1606 action = self._option_strings[option_string]
1607 tup = action, option_string, explicit_arg
1608 option_tuples.append(tup)
1609 break
1610
1956
1611 # if multiple actions match, the option string was ambiguous
1957 # if multiple actions match, the option string was ambiguous
1612 if len(option_tuples) > 1:
1958 if len(option_tuples) > 1:
1613 options = ', '.join(opt_str for _, opt_str, _ in option_tuples)
1959 options = ', '.join([option_string
1960 for action, option_string, explicit_arg in option_tuples])
1614 tup = arg_string, options
1961 tup = arg_string, options
1615 self.error(_('ambiguous option: %s could match %s') % tup)
1962 self.error(_('ambiguous option: %s could match %s') % tup)
1616
1963
1617 # if exactly one action matched, this segmentation is good,
1964 # if exactly one action matched, this segmentation is good,
1618 # so return the parsed action
1965 # so return the parsed action
1619 elif len(option_tuples) == 1:
1966 elif len(option_tuples) == 1:
1620 option_tuple, = option_tuples
1967 option_tuple, = option_tuples
1621 return option_tuple
1968 return option_tuple
1622
1969
1623 # if it was not found as an option, but it looks like a negative
1970 # if it was not found as an option, but it looks like a negative
1624 # number, it was meant to be positional
1971 # number, it was meant to be positional
1972 # unless there are negative-number-like options
1625 if self._negative_number_matcher.match(arg_string):
1973 if self._negative_number_matcher.match(arg_string):
1974 if not self._has_negative_number_optionals:
1975 return None
1976
1977 # if it contains a space, it was meant to be a positional
1978 if ' ' in arg_string:
1626 return None
1979 return None
1627
1980
1628 # it was meant to be an optional but there is no such option
1981 # it was meant to be an optional but there is no such option
1629 # in this parser (though it might be a valid option in a subparser)
1982 # in this parser (though it might be a valid option in a subparser)
1630 return None, arg_string, None
1983 return None, arg_string, None
1631
1984
1632 def _get_option_prefix_tuples(self, option_string):
1985 def _get_option_tuples(self, option_string):
1633 result = []
1986 result = []
1634
1987
1635 # option strings starting with two prefix characters are only
1988 # option strings starting with two prefix characters are only
1636 # split at the '='
1989 # split at the '='
1637 chars = self.prefix_chars
1990 chars = self.prefix_chars
1638 if option_string[0] in chars and option_string[1] in chars:
1991 if option_string[0] in chars and option_string[1] in chars:
1639 if '=' in option_string:
1992 if '=' in option_string:
1640 option_prefix, explicit_arg = option_string.split('=', 1)
1993 option_prefix, explicit_arg = option_string.split('=', 1)
1641 else:
1994 else:
1642 option_prefix = option_string
1995 option_prefix = option_string
1643 explicit_arg = None
1996 explicit_arg = None
1644 tup = option_prefix, explicit_arg
1997 for option_string in self._option_string_actions:
1645 result.append(tup)
1998 if option_string.startswith(option_prefix):
1999 action = self._option_string_actions[option_string]
2000 tup = action, option_string, explicit_arg
2001 result.append(tup)
2002
2003 # single character options can be concatenated with their arguments
2004 # but multiple character options always have to have their argument
2005 # separate
2006 elif option_string[0] in chars and option_string[1] not in chars:
2007 option_prefix = option_string
2008 explicit_arg = None
2009 short_option_prefix = option_string[:2]
2010 short_explicit_arg = option_string[2:]
2011
2012 for option_string in self._option_string_actions:
2013 if option_string == short_option_prefix:
2014 action = self._option_string_actions[option_string]
2015 tup = action, option_string, short_explicit_arg
2016 result.append(tup)
2017 elif option_string.startswith(option_prefix):
2018 action = self._option_string_actions[option_string]
2019 tup = action, option_string, explicit_arg
2020 result.append(tup)
1646
2021
1647 # option strings starting with a single prefix character are
2022 # shouldn't ever get here
1648 # split at all indices
1649 else:
2023 else:
1650 for first_index, char in enumerate(option_string):
2024 self.error(_('unexpected option string: %s') % option_string)
1651 if char not in self.prefix_chars:
1652 break
1653 for i in xrange(len(option_string), first_index, -1):
1654 tup = option_string[:i], option_string[i:] or None
1655 result.append(tup)
1656
2025
1657 # return the collected prefix tuples
2026 # return the collected option tuples
1658 return result
2027 return result
1659
2028
1660 def _get_nargs_pattern(self, action):
2029 def _get_nargs_pattern(self, action):
1661 # in all examples below, we have to allow for '--' args
2030 # in all examples below, we have to allow for '--' args
1662 # which are represented as '-' in the pattern
2031 # which are represented as '-' in the pattern
1663 nargs = action.nargs
2032 nargs = action.nargs
1664
2033
1665 # the default (None) is assumed to be a single argument
2034 # the default (None) is assumed to be a single argument
1666 if nargs is None:
2035 if nargs is None:
1667 nargs_pattern = '(-*A-*)'
2036 nargs_pattern = '(-*A-*)'
1668
2037
1669 # allow zero or one arguments
2038 # allow zero or one arguments
1670 elif nargs == OPTIONAL:
2039 elif nargs == OPTIONAL:
1671 nargs_pattern = '(-*A?-*)'
2040 nargs_pattern = '(-*A?-*)'
1672
2041
1673 # allow zero or more arguments
2042 # allow zero or more arguments
1674 elif nargs == ZERO_OR_MORE:
2043 elif nargs == ZERO_OR_MORE:
1675 nargs_pattern = '(-*[A-]*)'
2044 nargs_pattern = '(-*[A-]*)'
1676
2045
1677 # allow one or more arguments
2046 # allow one or more arguments
1678 elif nargs == ONE_OR_MORE:
2047 elif nargs == ONE_OR_MORE:
1679 nargs_pattern = '(-*A[A-]*)'
2048 nargs_pattern = '(-*A[A-]*)'
1680
2049
1681 # allow one argument followed by any number of options or arguments
2050 # allow one argument followed by any number of options or arguments
1682 elif nargs is PARSER:
2051 elif nargs is PARSER:
1683 nargs_pattern = '(-*A[-AO]*)'
2052 nargs_pattern = '(-*A[-AO]*)'
1684
2053
1685 # all others should be integers
2054 # all others should be integers
1686 else:
2055 else:
1687 nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
2056 nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
1688
2057
1689 # if this is an optional action, -- is not allowed
2058 # if this is an optional action, -- is not allowed
1690 if action.option_strings:
2059 if action.option_strings:
1691 nargs_pattern = nargs_pattern.replace('-*', '')
2060 nargs_pattern = nargs_pattern.replace('-*', '')
1692 nargs_pattern = nargs_pattern.replace('-', '')
2061 nargs_pattern = nargs_pattern.replace('-', '')
1693
2062
1694 # return the pattern
2063 # return the pattern
1695 return nargs_pattern
2064 return nargs_pattern
1696
2065
1697 # ========================
2066 # ========================
1698 # Value conversion methods
2067 # Value conversion methods
1699 # ========================
2068 # ========================
1700
1701 def _get_values(self, action, arg_strings):
2069 def _get_values(self, action, arg_strings):
1702 # for everything but PARSER args, strip out '--'
2070 # for everything but PARSER args, strip out '--'
1703 if action.nargs is not PARSER:
2071 if action.nargs is not PARSER:
1704 arg_strings = [s for s in arg_strings if s != '--']
2072 arg_strings = [s for s in arg_strings if s != '--']
1705
2073
1706 # optional argument produces a default when not present
2074 # optional argument produces a default when not present
1707 if not arg_strings and action.nargs == OPTIONAL:
2075 if not arg_strings and action.nargs == OPTIONAL:
1708 if action.option_strings:
2076 if action.option_strings:
1709 value = action.const
2077 value = action.const
1710 else:
2078 else:
1711 value = action.default
2079 value = action.default
1712 if isinstance(value, basestring):
2080 if isinstance(value, _basestring):
1713 value = self._get_value(action, value)
2081 value = self._get_value(action, value)
1714 self._check_value(action, value)
2082 self._check_value(action, value)
1715
2083
1716 # when nargs='*' on a positional, if there were no command-line
2084 # when nargs='*' on a positional, if there were no command-line
1717 # args, use the default if it is anything other than None
2085 # args, use the default if it is anything other than None
1718 elif (not arg_strings and action.nargs == ZERO_OR_MORE and
2086 elif (not arg_strings and action.nargs == ZERO_OR_MORE and
1719 not action.option_strings):
2087 not action.option_strings):
1720 if action.default is not None:
2088 if action.default is not None:
1721 value = action.default
2089 value = action.default
1722 else:
2090 else:
1723 value = arg_strings
2091 value = arg_strings
1724 self._check_value(action, value)
2092 self._check_value(action, value)
1725
2093
1726 # single argument or optional argument produces a single value
2094 # single argument or optional argument produces a single value
1727 elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
2095 elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
1728 arg_string, = arg_strings
2096 arg_string, = arg_strings
1729 value = self._get_value(action, arg_string)
2097 value = self._get_value(action, arg_string)
1730 self._check_value(action, value)
2098 self._check_value(action, value)
1731
2099
1732 # PARSER arguments convert all values, but check only the first
2100 # PARSER arguments convert all values, but check only the first
1733 elif action.nargs is PARSER:
2101 elif action.nargs is PARSER:
1734 value = list(self._get_value(action, v) for v in arg_strings)
2102 value = [self._get_value(action, v) for v in arg_strings]
1735 self._check_value(action, value[0])
2103 self._check_value(action, value[0])
1736
2104
1737 # all other types of nargs produce a list
2105 # all other types of nargs produce a list
1738 else:
2106 else:
1739 value = list(self._get_value(action, v) for v in arg_strings)
2107 value = [self._get_value(action, v) for v in arg_strings]
1740 for v in value:
2108 for v in value:
1741 self._check_value(action, v)
2109 self._check_value(action, v)
1742
2110
1743 # return the converted value
2111 # return the converted value
1744 return value
2112 return value
1745
2113
1746 def _get_value(self, action, arg_string):
2114 def _get_value(self, action, arg_string):
1747 type_func = self._registry_get('type', action.type, action.type)
2115 type_func = self._registry_get('type', action.type, action.type)
1748 if not callable(type_func):
2116 if not hasattr(type_func, '__call__'):
1749 msg = _('%r is not callable')
2117 msg = _('%r is not callable')
1750 raise ArgumentError(action, msg % type_func)
2118 raise ArgumentError(action, msg % type_func)
1751
2119
1752 # convert the value to the appropriate type
2120 # convert the value to the appropriate type
1753 try:
2121 try:
1754 result = type_func(arg_string)
2122 result = type_func(arg_string)
1755
2123
1756 # TypeErrors or ValueErrors indicate errors
2124 # TypeErrors or ValueErrors indicate errors
1757 except (TypeError, ValueError):
2125 except (TypeError, ValueError):
1758 name = getattr(action.type, '__name__', repr(action.type))
2126 name = getattr(action.type, '__name__', repr(action.type))
1759 msg = _('invalid %s value: %r')
2127 msg = _('invalid %s value: %r')
1760 raise ArgumentError(action, msg % (name, arg_string))
2128 raise ArgumentError(action, msg % (name, arg_string))
1761
2129
1762 # return the converted value
2130 # return the converted value
1763 return result
2131 return result
1764
2132
1765 def _check_value(self, action, value):
2133 def _check_value(self, action, value):
1766 # converted value must be one of the choices (if specified)
2134 # converted value must be one of the choices (if specified)
1767 if action.choices is not None and value not in action.choices:
2135 if action.choices is not None and value not in action.choices:
1768 tup = value, ', '.join(map(repr, action.choices))
2136 tup = value, ', '.join(map(repr, action.choices))
1769 msg = _('invalid choice: %r (choose from %s)') % tup
2137 msg = _('invalid choice: %r (choose from %s)') % tup
1770 raise ArgumentError(action, msg)
2138 raise ArgumentError(action, msg)
1771
2139
1772
1773
1774 # =======================
2140 # =======================
1775 # Help-formatting methods
2141 # Help-formatting methods
1776 # =======================
2142 # =======================
1777
1778 def format_usage(self):
2143 def format_usage(self):
1779 formatter = self._get_formatter()
2144 formatter = self._get_formatter()
1780 formatter.add_usage(self.usage,
2145 formatter.add_usage(self.usage, self._actions,
1781 self._get_optional_actions(),
2146 self._mutually_exclusive_groups)
1782 self._get_positional_actions())
1783 return formatter.format_help()
2147 return formatter.format_help()
1784
2148
1785 def format_help(self):
2149 def format_help(self):
1786 formatter = self._get_formatter()
2150 formatter = self._get_formatter()
1787
2151
1788 # usage
2152 # usage
1789 formatter.add_usage(self.usage,
2153 formatter.add_usage(self.usage, self._actions,
1790 self._get_optional_actions(),
2154 self._mutually_exclusive_groups)
1791 self._get_positional_actions())
1792
2155
1793 # description
2156 # description
1794 formatter.add_text(self.description)
2157 formatter.add_text(self.description)
1795
2158
1796 # positionals
2159 # positionals, optionals and user-defined groups
1797 formatter.start_section(_('positional arguments'))
2160 for action_group in self._action_groups:
1798 formatter.add_arguments(self._positional_actions_list)
2161 formatter.start_section(action_group.title)
1799 formatter.end_section()
2162 formatter.add_text(action_group.description)
1800
2163 formatter.add_arguments(action_group._group_actions)
1801 # optionals
1802 formatter.start_section(_('optional arguments'))
1803 formatter.add_arguments(self._optional_actions_list)
1804 formatter.end_section()
1805
1806 # user-defined groups
1807 for argument_group in self._argument_groups:
1808 formatter.start_section(argument_group.title)
1809 formatter.add_text(argument_group.description)
1810 formatter.add_arguments(argument_group._positional_actions_list)
1811 formatter.add_arguments(argument_group._optional_actions_list)
1812 formatter.end_section()
2164 formatter.end_section()
1813
2165
1814 # epilog
2166 # epilog
1815 formatter.add_text(self.epilog)
2167 formatter.add_text(self.epilog)
1816
2168
1817 # determine help from format above
2169 # determine help from format above
1818 return formatter.format_help()
2170 return formatter.format_help()
1819
2171
1820 def format_version(self):
2172 def format_version(self):
1821 formatter = self._get_formatter()
2173 formatter = self._get_formatter()
1822 formatter.add_text(self.version)
2174 formatter.add_text(self.version)
1823 return formatter.format_help()
2175 return formatter.format_help()
1824
2176
1825 def _get_formatter(self):
2177 def _get_formatter(self):
1826 return self.formatter_class(prog=self.prog)
2178 return self.formatter_class(prog=self.prog)
1827
2179
1828 # =====================
2180 # =====================
1829 # Help-printing methods
2181 # Help-printing methods
1830 # =====================
2182 # =====================
1831
1832 def print_usage(self, file=None):
2183 def print_usage(self, file=None):
1833 self._print_message(self.format_usage(), file)
2184 self._print_message(self.format_usage(), file)
1834
2185
1835 def print_help(self, file=None):
2186 def print_help(self, file=None):
1836 self._print_message(self.format_help(), file)
2187 self._print_message(self.format_help(), file)
1837
2188
1838 def print_version(self, file=None):
2189 def print_version(self, file=None):
1839 self._print_message(self.format_version(), file)
2190 self._print_message(self.format_version(), file)
1840
2191
1841 def _print_message(self, message, file=None):
2192 def _print_message(self, message, file=None):
1842 if message:
2193 if message:
1843 if file is None:
2194 if file is None:
1844 file = _sys.stderr
2195 file = _sys.stderr
1845 file.write(message)
2196 file.write(message)
1846
2197
1847
1848 # ===============
2198 # ===============
1849 # Exiting methods
2199 # Exiting methods
1850 # ===============
2200 # ===============
1851
1852 def exit(self, status=0, message=None):
2201 def exit(self, status=0, message=None):
1853 if message:
2202 if message:
1854 _sys.stderr.write(message)
2203 _sys.stderr.write(message)
1855 _sys.exit(status)
2204 _sys.exit(status)
1856
2205
1857 def error(self, message):
2206 def error(self, message):
1858 """error(message: string)
2207 """error(message: string)
1859
2208
1860 Prints a usage message incorporating the message to stderr and
2209 Prints a usage message incorporating the message to stderr and
1861 exits.
2210 exits.
1862
2211
1863 If you override this in a subclass, it should not return -- it
2212 If you override this in a subclass, it should not return -- it
1864 should either exit or raise an exception.
2213 should either exit or raise an exception.
1865 """
2214 """
1866 self.print_usage(_sys.stderr)
2215 self.print_usage(_sys.stderr)
1867 self.exit(2, _('%s: error: %s\n') % (self.prog, message))
2216 self.exit(2, _('%s: error: %s\n') % (self.prog, message))
@@ -1,374 +1,377 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """Test template for complete engine object"""
3 """Test template for complete engine object"""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 import cPickle as pickle
18 import cPickle as pickle
19
19
20 from twisted.internet import defer, reactor
20 from twisted.internet import defer, reactor
21 from twisted.python import failure
21 from twisted.python import failure
22 from twisted.application import service
22 from twisted.application import service
23 import zope.interface as zi
23 import zope.interface as zi
24
24
25 from IPython.kernel import newserialized
25 from IPython.kernel import newserialized
26 from IPython.kernel import error
26 from IPython.kernel import error
27 from IPython.kernel.pickleutil import can, uncan
27 from IPython.kernel.pickleutil import can, uncan
28 import IPython.kernel.engineservice as es
28 import IPython.kernel.engineservice as es
29 from IPython.kernel.core.interpreter import Interpreter
29 from IPython.kernel.core.interpreter import Interpreter
30 from IPython.testing.parametric import Parametric, parametric
30 from IPython.testing.parametric import Parametric, parametric
31
31
32 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
33 # Tests
33 # Tests
34 #-------------------------------------------------------------------------------
34 #-------------------------------------------------------------------------------
35
35
36
36
37 # A sequence of valid commands run through execute
37 # A sequence of valid commands run through execute
38 validCommands = ['a=5',
38 validCommands = ['a=5',
39 'b=10',
39 'b=10',
40 'a=5; b=10; c=a+b',
40 'a=5; b=10; c=a+b',
41 'import math; 2.0*math.pi',
41 'import math; 2.0*math.pi',
42 """def f():
42 """def f():
43 result = 0.0
43 result = 0.0
44 for i in range(10):
44 for i in range(10):
45 result += i
45 result += i
46 """,
46 """,
47 'if 1<2: a=5',
47 'if 1<2: a=5',
48 """import time
48 """import time
49 time.sleep(0.1)""",
49 time.sleep(0.1)""",
50 """from math import cos;
50 """from math import cos;
51 x = 1.0*cos(0.5)""", # Semicolons lead to Discard ast nodes that should be discarded
51 x = 1.0*cos(0.5)""", # Semicolons lead to Discard ast nodes that should be discarded
52 """s = 1
52 """s = 1
53 s = set()
53 s = set()
54 """, # Trailing whitespace should be allowed.
54 """, # Trailing whitespace should be allowed.
55 """import math
55 """import math
56 math.cos(1.0)""", # Test a method call with a discarded return value
56 math.cos(1.0)""", # Test a method call with a discarded return value
57 """x=1.0234
57 """x=1.0234
58 a=5; b=10""", # Test an embedded semicolon
58 a=5; b=10""", # Test an embedded semicolon
59 """x=1.0234
59 """x=1.0234
60 a=5; b=10;""" # Test both an embedded and trailing semicolon
60 a=5; b=10;""" # Test both an embedded and trailing semicolon
61 ]
61 ]
62
62
63 # A sequence of commands that raise various exceptions
63 # A sequence of commands that raise various exceptions
64 invalidCommands = [('a=1/0',ZeroDivisionError),
64 invalidCommands = [('a=1/0',ZeroDivisionError),
65 ('print v',NameError),
65 ('print v',NameError),
66 ('l=[];l[0]',IndexError),
66 ('l=[];l[0]',IndexError),
67 ("d={};d['a']",KeyError),
67 ("d={};d['a']",KeyError),
68 ("assert 1==0",AssertionError),
68 ("assert 1==0",AssertionError),
69 ("import abababsdbfsbaljasdlja",ImportError),
69 ("import abababsdbfsbaljasdlja",ImportError),
70 ("raise Exception()",Exception)]
70 ("raise Exception()",Exception)]
71
71
72 def testf(x):
72 def testf(x):
73 return 2.0*x
73 return 2.0*x
74
74
75 globala = 99
75 globala = 99
76
76
77 def testg(x):
77 def testg(x):
78 return globala*x
78 return globala*x
79
79
80 class IEngineCoreTestCase(object):
80 class IEngineCoreTestCase(object):
81 """Test an IEngineCore implementer."""
81 """Test an IEngineCore implementer."""
82
82
83 def createShell(self):
83 def createShell(self):
84 return Interpreter()
84 return Interpreter()
85
85
86 def catchQueueCleared(self, f):
86 def catchQueueCleared(self, f):
87 try:
87 try:
88 f.raiseException()
88 f.raiseException()
89 except error.QueueCleared:
89 except error.QueueCleared:
90 pass
90 pass
91
91
92 def testIEngineCoreInterface(self):
92 def testIEngineCoreInterface(self):
93 """Does self.engine claim to implement IEngineCore?"""
93 """Does self.engine claim to implement IEngineCore?"""
94 self.assert_(es.IEngineCore.providedBy(self.engine))
94 self.assert_(es.IEngineCore.providedBy(self.engine))
95
95
96 def testIEngineCoreInterfaceMethods(self):
96 def testIEngineCoreInterfaceMethods(self):
97 """Does self.engine have the methods and attributes in IEngineCore."""
97 """Does self.engine have the methods and attributes in IEngineCore."""
98 for m in list(es.IEngineCore):
98 for m in list(es.IEngineCore):
99 self.assert_(hasattr(self.engine, m))
99 self.assert_(hasattr(self.engine, m))
100
100
101 def testIEngineCoreDeferreds(self):
101 def testIEngineCoreDeferreds(self):
102 d = self.engine.execute('a=5')
102 d = self.engine.execute('a=5')
103 d.addCallback(lambda _: self.engine.pull('a'))
103 d.addCallback(lambda _: self.engine.pull('a'))
104 d.addCallback(lambda _: self.engine.get_result())
104 d.addCallback(lambda _: self.engine.get_result())
105 d.addCallback(lambda _: self.engine.keys())
105 d.addCallback(lambda _: self.engine.keys())
106 d.addCallback(lambda _: self.engine.push(dict(a=10)))
106 d.addCallback(lambda _: self.engine.push(dict(a=10)))
107 return d
107 return d
108
108
109 def runTestExecute(self, cmd):
109 def runTestExecute(self, cmd):
110 self.shell = Interpreter()
110 self.shell = Interpreter()
111 actual = self.shell.execute(cmd)
111 actual = self.shell.execute(cmd)
112 def compare(computed):
112 def compare(computed):
113 actual['id'] = computed['id']
113 actual['id'] = computed['id']
114 self.assertEquals(actual, computed)
114 self.assertEquals(actual, computed)
115 d = self.engine.execute(cmd)
115 d = self.engine.execute(cmd)
116 d.addCallback(compare)
116 d.addCallback(compare)
117 return d
117 return d
118
118
119 @parametric
119 @parametric
120 def testExecute(cls):
120 def testExecute(cls):
121 return [(cls.runTestExecute, cmd) for cmd in validCommands]
121 return [(cls.runTestExecute, cmd) for cmd in validCommands]
122
122
123 def runTestExecuteFailures(self, cmd, exc):
123 def runTestExecuteFailures(self, cmd, exc):
124 def compare(f):
124 def compare(f):
125 self.assertRaises(exc, f.raiseException)
125 self.assertRaises(exc, f.raiseException)
126 d = self.engine.execute(cmd)
126 d = self.engine.execute(cmd)
127 d.addErrback(compare)
127 d.addErrback(compare)
128 return d
128 return d
129
129
130 @parametric
130 @parametric
131 def testExecuteFailuresEngineService(cls):
131 def testExecuteFailuresEngineService(cls):
132 return [(cls.runTestExecuteFailures, cmd, exc)
132 return [(cls.runTestExecuteFailures, cmd, exc)
133 for cmd, exc in invalidCommands]
133 for cmd, exc in invalidCommands]
134
134
135 def runTestPushPull(self, o):
135 def runTestPushPull(self, o):
136 d = self.engine.push(dict(a=o))
136 d = self.engine.push(dict(a=o))
137 d.addCallback(lambda r: self.engine.pull('a'))
137 d.addCallback(lambda r: self.engine.pull('a'))
138 d.addCallback(lambda r: self.assertEquals(o,r))
138 d.addCallback(lambda r: self.assertEquals(o,r))
139 return d
139 return d
140
140
141 @parametric
141 @parametric
142 def testPushPull(cls):
142 def testPushPull(cls):
143 objs = [10,"hi there",1.2342354,{"p":(1,2)},None]
143 objs = [10,"hi there",1.2342354,{"p":(1,2)},None]
144 return [(cls.runTestPushPull, o) for o in objs]
144 return [(cls.runTestPushPull, o) for o in objs]
145
145
146 def testPullNameError(self):
146 def testPullNameError(self):
147 d = self.engine.push(dict(a=5))
147 d = self.engine.push(dict(a=5))
148 d.addCallback(lambda _:self.engine.reset())
148 d.addCallback(lambda _:self.engine.reset())
149 d.addCallback(lambda _: self.engine.pull("a"))
149 d.addCallback(lambda _: self.engine.pull("a"))
150 d.addErrback(lambda f: self.assertRaises(NameError, f.raiseException))
150 d.addErrback(lambda f: self.assertRaises(NameError, f.raiseException))
151 return d
151 return d
152
152
153 def testPushPullFailures(self):
153 def testPushPullFailures(self):
154 d = self.engine.pull('a')
154 d = self.engine.pull('a')
155 d.addErrback(lambda f: self.assertRaises(NameError, f.raiseException))
155 d.addErrback(lambda f: self.assertRaises(NameError, f.raiseException))
156 d.addCallback(lambda _: self.engine.execute('l = lambda x: x'))
156 d.addCallback(lambda _: self.engine.execute('l = lambda x: x'))
157 d.addCallback(lambda _: self.engine.pull('l'))
157 d.addCallback(lambda _: self.engine.pull('l'))
158 d.addErrback(lambda f: self.assertRaises(pickle.PicklingError, f.raiseException))
158 d.addErrback(lambda f: self.assertRaises(pickle.PicklingError, f.raiseException))
159 d.addCallback(lambda _: self.engine.push(dict(l=lambda x: x)))
159 d.addCallback(lambda _: self.engine.push(dict(l=lambda x: x)))
160 d.addErrback(lambda f: self.assertRaises(pickle.PicklingError, f.raiseException))
160 d.addErrback(lambda f: self.assertRaises(pickle.PicklingError, f.raiseException))
161 return d
161 return d
162
162
163 def testPushPullArray(self):
163 def testPushPullArray(self):
164 try:
164 try:
165 import numpy
165 import numpy
166 except:
166 except:
167 return
167 return
168 a = numpy.random.random(1000)
168 a = numpy.random.random(1000)
169 d = self.engine.push(dict(a=a))
169 d = self.engine.push(dict(a=a))
170 d.addCallback(lambda _: self.engine.pull('a'))
170 d.addCallback(lambda _: self.engine.pull('a'))
171 d.addCallback(lambda b: b==a)
171 d.addCallback(lambda b: b==a)
172 d.addCallback(lambda c: c.all())
172 d.addCallback(lambda c: c.all())
173 return self.assertDeferredEquals(d, True)
173 return self.assertDeferredEquals(d, True)
174
174
175 def testPushFunction(self):
175 def testPushFunction(self):
176
176
177 d = self.engine.push_function(dict(f=testf))
177 d = self.engine.push_function(dict(f=testf))
178 d.addCallback(lambda _: self.engine.execute('result = f(10)'))
178 d.addCallback(lambda _: self.engine.execute('result = f(10)'))
179 d.addCallback(lambda _: self.engine.pull('result'))
179 d.addCallback(lambda _: self.engine.pull('result'))
180 d.addCallback(lambda r: self.assertEquals(r, testf(10)))
180 d.addCallback(lambda r: self.assertEquals(r, testf(10)))
181 return d
181 return d
182
182
183 def testPullFunction(self):
183 def testPullFunction(self):
184 d = self.engine.push_function(dict(f=testf, g=testg))
184 d = self.engine.push_function(dict(f=testf, g=testg))
185 d.addCallback(lambda _: self.engine.pull_function(('f','g')))
185 d.addCallback(lambda _: self.engine.pull_function(('f','g')))
186 d.addCallback(lambda r: self.assertEquals(r[0](10), testf(10)))
186 d.addCallback(lambda r: self.assertEquals(r[0](10), testf(10)))
187 return d
187 return d
188
188
189 def testPushFunctionGlobal(self):
189 def testPushFunctionGlobal(self):
190 """Make sure that pushed functions pick up the user's namespace for globals."""
190 """Make sure that pushed functions pick up the user's namespace for globals."""
191 d = self.engine.push(dict(globala=globala))
191 d = self.engine.push(dict(globala=globala))
192 d.addCallback(lambda _: self.engine.push_function(dict(g=testg)))
192 d.addCallback(lambda _: self.engine.push_function(dict(g=testg)))
193 d.addCallback(lambda _: self.engine.execute('result = g(10)'))
193 d.addCallback(lambda _: self.engine.execute('result = g(10)'))
194 d.addCallback(lambda _: self.engine.pull('result'))
194 d.addCallback(lambda _: self.engine.pull('result'))
195 d.addCallback(lambda r: self.assertEquals(r, testg(10)))
195 d.addCallback(lambda r: self.assertEquals(r, testg(10)))
196 return d
196 return d
197
197
198 def testGetResultFailure(self):
198 def testGetResultFailure(self):
199 d = self.engine.get_result(None)
199 d = self.engine.get_result(None)
200 d.addErrback(lambda f: self.assertRaises(IndexError, f.raiseException))
200 d.addErrback(lambda f: self.assertRaises(IndexError, f.raiseException))
201 d.addCallback(lambda _: self.engine.get_result(10))
201 d.addCallback(lambda _: self.engine.get_result(10))
202 d.addErrback(lambda f: self.assertRaises(IndexError, f.raiseException))
202 d.addErrback(lambda f: self.assertRaises(IndexError, f.raiseException))
203 return d
203 return d
204
204
205 def runTestGetResult(self, cmd):
205 def runTestGetResult(self, cmd):
206 self.shell = Interpreter()
206 self.shell = Interpreter()
207 actual = self.shell.execute(cmd)
207 actual = self.shell.execute(cmd)
208 def compare(computed):
208 def compare(computed):
209 actual['id'] = computed['id']
209 actual['id'] = computed['id']
210 self.assertEquals(actual, computed)
210 self.assertEquals(actual, computed)
211 d = self.engine.execute(cmd)
211 d = self.engine.execute(cmd)
212 d.addCallback(lambda r: self.engine.get_result(r['number']))
212 d.addCallback(lambda r: self.engine.get_result(r['number']))
213 d.addCallback(compare)
213 d.addCallback(compare)
214 return d
214 return d
215
215
216 @parametric
216 @parametric
217 def testGetResult(cls):
217 def testGetResult(cls):
218 return [(cls.runTestGetResult, cmd) for cmd in validCommands]
218 return [(cls.runTestGetResult, cmd) for cmd in validCommands]
219
219
220 def testGetResultDefault(self):
220 def testGetResultDefault(self):
221 cmd = 'a=5'
221 cmd = 'a=5'
222 shell = self.createShell()
222 shell = self.createShell()
223 shellResult = shell.execute(cmd)
223 shellResult = shell.execute(cmd)
224 def popit(dikt, key):
224 def popit(dikt, key):
225 dikt.pop(key)
225 dikt.pop(key)
226 return dikt
226 return dikt
227 d = self.engine.execute(cmd)
227 d = self.engine.execute(cmd)
228 d.addCallback(lambda _: self.engine.get_result())
228 d.addCallback(lambda _: self.engine.get_result())
229 d.addCallback(lambda r: self.assertEquals(shellResult, popit(r,'id')))
229 d.addCallback(lambda r: self.assertEquals(shellResult, popit(r,'id')))
230 return d
230 return d
231
231
232 def testKeys(self):
232 def testKeys(self):
233 d = self.engine.keys()
233 d = self.engine.keys()
234 d.addCallback(lambda s: isinstance(s, list))
234 d.addCallback(lambda s: isinstance(s, list))
235 d.addCallback(lambda r: self.assertEquals(r, True))
235 d.addCallback(lambda r: self.assertEquals(r, True))
236 return d
236 return d
237
237
238 Parametric(IEngineCoreTestCase)
238 Parametric(IEngineCoreTestCase)
239
239
240 class IEngineSerializedTestCase(object):
240 class IEngineSerializedTestCase(object):
241 """Test an IEngineCore implementer."""
241 """Test an IEngineCore implementer."""
242
242
243 def testIEngineSerializedInterface(self):
243 def testIEngineSerializedInterface(self):
244 """Does self.engine claim to implement IEngineCore?"""
244 """Does self.engine claim to implement IEngineCore?"""
245 self.assert_(es.IEngineSerialized.providedBy(self.engine))
245 self.assert_(es.IEngineSerialized.providedBy(self.engine))
246
246
247 def testIEngineSerializedInterfaceMethods(self):
247 def testIEngineSerializedInterfaceMethods(self):
248 """Does self.engine have the methods and attributes in IEngineCore."""
248 """Does self.engine have the methods and attributes in IEngineCore."""
249 for m in list(es.IEngineSerialized):
249 for m in list(es.IEngineSerialized):
250 self.assert_(hasattr(self.engine, m))
250 self.assert_(hasattr(self.engine, m))
251
251
252 def testIEngineSerializedDeferreds(self):
252 def testIEngineSerializedDeferreds(self):
253 dList = []
253 dList = []
254 d = self.engine.push_serialized(dict(key=newserialized.serialize(12345)))
254 d = self.engine.push_serialized(dict(key=newserialized.serialize(12345)))
255 self.assert_(isinstance(d, defer.Deferred))
255 self.assert_(isinstance(d, defer.Deferred))
256 dList.append(d)
256 dList.append(d)
257 d = self.engine.pull_serialized('key')
257 d = self.engine.pull_serialized('key')
258 self.assert_(isinstance(d, defer.Deferred))
258 self.assert_(isinstance(d, defer.Deferred))
259 dList.append(d)
259 dList.append(d)
260 D = defer.DeferredList(dList)
260 D = defer.DeferredList(dList)
261 return D
261 return D
262
262
263 def testPushPullSerialized(self):
263 def testPushPullSerialized(self):
264 objs = [10,"hi there",1.2342354,{"p":(1,2)}]
264 objs = [10,"hi there",1.2342354,{"p":(1,2)}]
265 d = defer.succeed(None)
265 d = defer.succeed(None)
266 for o in objs:
266 for o in objs:
267 self.engine.push_serialized(dict(key=newserialized.serialize(o)))
267 self.engine.push_serialized(dict(key=newserialized.serialize(o)))
268 value = self.engine.pull_serialized('key')
268 value = self.engine.pull_serialized('key')
269 value.addCallback(lambda serial: newserialized.IUnSerialized(serial).getObject())
269 value.addCallback(lambda serial: newserialized.IUnSerialized(serial).getObject())
270 d = self.assertDeferredEquals(value,o,d)
270 d = self.assertDeferredEquals(value,o,d)
271 return d
271 return d
272
272
273 def testPullSerializedFailures(self):
273 def testPullSerializedFailures(self):
274 d = self.engine.pull_serialized('a')
274 d = self.engine.pull_serialized('a')
275 d.addErrback(lambda f: self.assertRaises(NameError, f.raiseException))
275 d.addErrback(lambda f: self.assertRaises(NameError, f.raiseException))
276 d.addCallback(lambda _: self.engine.execute('l = lambda x: x'))
276 d.addCallback(lambda _: self.engine.execute('l = lambda x: x'))
277 d.addCallback(lambda _: self.engine.pull_serialized('l'))
277 d.addCallback(lambda _: self.engine.pull_serialized('l'))
278 d.addErrback(lambda f: self.assertRaises(pickle.PicklingError, f.raiseException))
278 d.addErrback(lambda f: self.assertRaises(pickle.PicklingError, f.raiseException))
279 return d
279 return d
280
280
281 Parametric(IEngineSerializedTestCase)
281 Parametric(IEngineSerializedTestCase)
282
282
283 class IEngineQueuedTestCase(object):
283 class IEngineQueuedTestCase(object):
284 """Test an IEngineQueued implementer."""
284 """Test an IEngineQueued implementer."""
285
285
286 def testIEngineQueuedInterface(self):
286 def testIEngineQueuedInterface(self):
287 """Does self.engine claim to implement IEngineQueued?"""
287 """Does self.engine claim to implement IEngineQueued?"""
288 self.assert_(es.IEngineQueued.providedBy(self.engine))
288 self.assert_(es.IEngineQueued.providedBy(self.engine))
289
289
290 def testIEngineQueuedInterfaceMethods(self):
290 def testIEngineQueuedInterfaceMethods(self):
291 """Does self.engine have the methods and attributes in IEngineQueued."""
291 """Does self.engine have the methods and attributes in IEngineQueued."""
292 for m in list(es.IEngineQueued):
292 for m in list(es.IEngineQueued):
293 self.assert_(hasattr(self.engine, m))
293 self.assert_(hasattr(self.engine, m))
294
294
295 def testIEngineQueuedDeferreds(self):
295 def testIEngineQueuedDeferreds(self):
296 dList = []
296 dList = []
297 d = self.engine.clear_queue()
297 d = self.engine.clear_queue()
298 self.assert_(isinstance(d, defer.Deferred))
298 self.assert_(isinstance(d, defer.Deferred))
299 dList.append(d)
299 dList.append(d)
300 d = self.engine.queue_status()
300 d = self.engine.queue_status()
301 self.assert_(isinstance(d, defer.Deferred))
301 self.assert_(isinstance(d, defer.Deferred))
302 dList.append(d)
302 dList.append(d)
303 D = defer.DeferredList(dList)
303 D = defer.DeferredList(dList)
304 return D
304 return D
305
305
306 def testClearQueue(self):
306 def testClearQueue(self):
307 result = self.engine.clear_queue()
307 result = self.engine.clear_queue()
308 d1 = self.assertDeferredEquals(result, None)
308 d1 = self.assertDeferredEquals(result, None)
309 d1.addCallback(lambda _: self.engine.queue_status())
309 d1.addCallback(lambda _: self.engine.queue_status())
310 d2 = self.assertDeferredEquals(d1, {'queue':[], 'pending':'None'})
310 d2 = self.assertDeferredEquals(d1, {'queue':[], 'pending':'None'})
311 return d2
311 return d2
312
312
313 def testQueueStatus(self):
313 def testQueueStatus(self):
314 result = self.engine.queue_status()
314 result = self.engine.queue_status()
315 result.addCallback(lambda r: 'queue' in r and 'pending' in r)
315 result.addCallback(lambda r: 'queue' in r and 'pending' in r)
316 d = self.assertDeferredEquals(result, True)
316 d = self.assertDeferredEquals(result, True)
317 return d
317 return d
318
318
319 Parametric(IEngineQueuedTestCase)
319 Parametric(IEngineQueuedTestCase)
320
320
321 class IEnginePropertiesTestCase(object):
321 class IEnginePropertiesTestCase(object):
322 """Test an IEngineProperties implementor."""
322 """Test an IEngineProperties implementor."""
323
323
324 def testIEnginePropertiesInterface(self):
324 def testIEnginePropertiesInterface(self):
325 """Does self.engine claim to implement IEngineProperties?"""
325 """Does self.engine claim to implement IEngineProperties?"""
326 self.assert_(es.IEngineProperties.providedBy(self.engine))
326 self.assert_(es.IEngineProperties.providedBy(self.engine))
327
327
328 def testIEnginePropertiesInterfaceMethods(self):
328 def testIEnginePropertiesInterfaceMethods(self):
329 """Does self.engine have the methods and attributes in IEngineProperties."""
329 """Does self.engine have the methods and attributes in IEngineProperties."""
330 for m in list(es.IEngineProperties):
330 for m in list(es.IEngineProperties):
331 self.assert_(hasattr(self.engine, m))
331 self.assert_(hasattr(self.engine, m))
332
332
333 def testGetSetProperties(self):
333 def testGetSetProperties(self):
334 dikt = dict(a=5, b='asdf', c=True, d=None, e=range(5))
334 dikt = dict(a=5, b='asdf', c=True, d=None, e=range(5))
335 d = self.engine.set_properties(dikt)
335 d = self.engine.set_properties(dikt)
336 d.addCallback(lambda r: self.engine.get_properties())
336 d.addCallback(lambda r: self.engine.get_properties())
337 d = self.assertDeferredEquals(d, dikt)
337 d = self.assertDeferredEquals(d, dikt)
338 d.addCallback(lambda r: self.engine.get_properties(('c',)))
338 d.addCallback(lambda r: self.engine.get_properties(('c',)))
339 d = self.assertDeferredEquals(d, {'c': dikt['c']})
339 d = self.assertDeferredEquals(d, {'c': dikt['c']})
340 d.addCallback(lambda r: self.engine.set_properties(dict(c=False)))
340 d.addCallback(lambda r: self.engine.set_properties(dict(c=False)))
341 d.addCallback(lambda r: self.engine.get_properties(('c', 'd')))
341 d.addCallback(lambda r: self.engine.get_properties(('c', 'd')))
342 d = self.assertDeferredEquals(d, dict(c=False, d=None))
342 d = self.assertDeferredEquals(d, dict(c=False, d=None))
343 return d
343 return d
344
344
345 def testClearProperties(self):
345 def testClearProperties(self):
346 dikt = dict(a=5, b='asdf', c=True, d=None, e=range(5))
346 dikt = dict(a=5, b='asdf', c=True, d=None, e=range(5))
347 d = self.engine.set_properties(dikt)
347 d = self.engine.set_properties(dikt)
348 d.addCallback(lambda r: self.engine.clear_properties())
348 d.addCallback(lambda r: self.engine.clear_properties())
349 d.addCallback(lambda r: self.engine.get_properties())
349 d.addCallback(lambda r: self.engine.get_properties())
350 d = self.assertDeferredEquals(d, {})
350 d = self.assertDeferredEquals(d, {})
351 return d
351 return d
352
352
353 def testDelHasProperties(self):
353 def testDelHasProperties(self):
354 dikt = dict(a=5, b='asdf', c=True, d=None, e=range(5))
354 dikt = dict(a=5, b='asdf', c=True, d=None, e=range(5))
355 d = self.engine.set_properties(dikt)
355 d = self.engine.set_properties(dikt)
356 d.addCallback(lambda r: self.engine.del_properties(('b','e')))
356 d.addCallback(lambda r: self.engine.del_properties(('b','e')))
357 d.addCallback(lambda r: self.engine.has_properties(('a','b','c','d','e')))
357 d.addCallback(lambda r: self.engine.has_properties(('a','b','c','d','e')))
358 d = self.assertDeferredEquals(d, [True, False, True, True, False])
358 d = self.assertDeferredEquals(d, [True, False, True, True, False])
359 return d
359 return d
360
360
361 def testStrictDict(self):
361 def testStrictDict(self):
362 s = """from IPython.kernel.engineservice import get_engine
362 s = """from IPython.kernel.engineservice import get_engine; p = get_engine(%s).properties"""%self.engine.id
363 p = get_engine(%s).properties"""%self.engine.id
364 d = self.engine.execute(s)
363 d = self.engine.execute(s)
364 # These 3 lines cause a weird testing error on some platforms (OS X).
365 # I am leaving them here in case they are masking some really
366 # weird reactor issue. For now I will just keep my eye on this.
365 d.addCallback(lambda r: self.engine.execute("p['a'] = lambda _:None"))
367 d.addCallback(lambda r: self.engine.execute("p['a'] = lambda _:None"))
366 d.addErrback(lambda f: self.assertRaises(error.InvalidProperty,
368 d.addErrback(lambda f: self.assertRaises(error.InvalidProperty,
367 f.raiseException))
369 f.raiseException))
370 # Below here seems to be fine
368 d.addCallback(lambda r: self.engine.execute("p['a'] = range(5)"))
371 d.addCallback(lambda r: self.engine.execute("p['a'] = range(5)"))
369 d.addCallback(lambda r: self.engine.execute("p['a'].append(5)"))
372 d.addCallback(lambda r: self.engine.execute("p['a'].append(5)"))
370 d.addCallback(lambda r: self.engine.get_properties('a'))
373 d.addCallback(lambda r: self.engine.get_properties('a'))
371 d = self.assertDeferredEquals(d, dict(a=range(5)))
374 d = self.assertDeferredEquals(d, dict(a=range(5)))
372 return d
375 return d
373
376
374 Parametric(IEnginePropertiesTestCase)
377 Parametric(IEnginePropertiesTestCase)
@@ -1,577 +1,544 b''
1 .. Developers should add in this file, during each release cycle, information
1 .. Developers should add in this file, during each release cycle, information
2 .. about important changes they've made, in a summary format that's meant for
2 .. about important changes they've made, in a summary format that's meant for
3 .. end users. For each release we normally have three sections: features, bug
3 .. end users. For each release we normally have three sections: features, bug
4 .. fixes and api breakage.
4 .. fixes and api breakage.
5 .. Please remember to credit the authors of the contributions by name,
5 .. Please remember to credit the authors of the contributions by name,
6 .. especially when they are new users or developers who do not regularly
6 .. especially when they are new users or developers who do not regularly
7 .. participate in IPython's development.
7 .. participate in IPython's development.
8
8
9 .. _changes:
9 .. _changes:
10
10
11 ==========
11 ==========
12 What's new
12 What's new
13 ==========
13 ==========
14
14
15 .. contents::
16 ..
17 1 Release dev
18 1.1 New features
19 1.2 Bug fixes
20 1.3 Backwards incompatible changes
21 2 Release 0.10
22 2.1 New features
23 2.2 Bug fixes
24 2.3 Backwards incompatible changes
25 3 Release 0.9.1
26 4 Release 0.9
27 4.1 New features
28 4.2 Bug fixes
29 4.3 Backwards incompatible changes
30 4.4 Changes merged in from IPython1
31 4.4.1 New features
32 4.4.2 Bug fixes
33 4.4.3 Backwards incompatible changes
34 5 Release 0.8.4
35 6 Release 0.8.3
36 7 Release 0.8.2
37 8 Older releases
38 ..
39
40 Release dev
41 ===========
42
43 New features
44 ------------
45
46 Bug fixes
47 ---------
48
49 Backwards incompatible changes
50 ------------------------------
51
52
53 Release 0.10
15 Release 0.10
54 ============
16 ============
55
17
56 This release brings months of slow but steady development, and will be the last
18 This release brings months of slow but steady development, and will be the last
57 before a major restructuring and cleanup of IPython's internals that is already
19 before a major restructuring and cleanup of IPython's internals that is already
58 under way. For this reason, we hope that 0.10 will be a stable and robust
20 under way. For this reason, we hope that 0.10 will be a stable and robust
59 release so that while users adapt to some of the API changes that will come
21 release so that while users adapt to some of the API changes that will come
60 with the refactoring that will become IPython 0.11, they can safely use 0.10 in
22 with the refactoring that will become IPython 0.11, they can safely use 0.10 in
61 all existing projects with minimal changes (if any).
23 all existing projects with minimal changes (if any).
62
24
63 IPython 0.10 is now a medium-sized project, with roughly (as reported by David
25 IPython 0.10 is now a medium-sized project, with roughly (as reported by David
64 Wheeler's :command:`sloccount` utility) 40750 lines of Python code, and a diff
26 Wheeler's :command:`sloccount` utility) 40750 lines of Python code, and a diff
65 between 0.9.1 and this release that contains almost 28000 lines of code and
27 between 0.9.1 and this release that contains almost 28000 lines of code and
66 documentation. Our documentation, in PDF format, is a 495-page long PDF
28 documentation. Our documentation, in PDF format, is a 495-page long PDF
67 document (also available in HTML format, both generated from the same sources).
29 document (also available in HTML format, both generated from the same sources).
68
30
69 Many users and developers contributed code, features, bug reports and ideas to
31 Many users and developers contributed code, features, bug reports and ideas to
70 this release. Please do not hesitate in contacting us if we've failed to
32 this release. Please do not hesitate in contacting us if we've failed to
71 acknowledge your contribution here. In particular, for this release we have
33 acknowledge your contribution here. In particular, for this release we have
72 contribution from the following people, a mix of new and regular names (in
34 contribution from the following people, a mix of new and regular names (in
73 alphabetical order by first name):
35 alphabetical order by first name):
74
36
75 * Alexander Clausen: fix #341726.
37 * Alexander Clausen: fix #341726.
76 * Brian Granger: lots of work everywhere (features, bug fixes, etc).
38 * Brian Granger: lots of work everywhere (features, bug fixes, etc).
77 * Daniel Ashbrook: bug report on MemoryError during compilation, now fixed.
39 * Daniel Ashbrook: bug report on MemoryError during compilation, now fixed.
78 * Darren Dale: improvements to documentation build system, feedback, design
40 * Darren Dale: improvements to documentation build system, feedback, design
79 ideas.
41 ideas.
80 * Fernando Perez: various places.
42 * Fernando Perez: various places.
81 * GaΓ«l Varoquaux: core code, ipythonx GUI, design discussions, etc. Lots...
43 * GaΓ«l Varoquaux: core code, ipythonx GUI, design discussions, etc. Lots...
82 * John Hunter: suggestions, bug fixes, feedback.
44 * John Hunter: suggestions, bug fixes, feedback.
83 * Jorgen Stenarson: work on many fronts, tests, fixes, win32 support, etc.
45 * Jorgen Stenarson: work on many fronts, tests, fixes, win32 support, etc.
84 * Laurent DufrΓ©chou: many improvements to ipython-wx standalone app.
46 * Laurent DufrΓ©chou: many improvements to ipython-wx standalone app.
85 * Lukasz Pankowski: prefilter, `%edit`, demo improvements.
47 * Lukasz Pankowski: prefilter, `%edit`, demo improvements.
86 * Matt Foster: TextMate support in `%edit`.
48 * Matt Foster: TextMate support in `%edit`.
87 * Nathaniel Smith: fix #237073.
49 * Nathaniel Smith: fix #237073.
88 * Pauli Virtanen: fixes and improvements to extensions, documentation.
50 * Pauli Virtanen: fixes and improvements to extensions, documentation.
89 * Prabhu Ramachandran: improvements to `%timeit`.
51 * Prabhu Ramachandran: improvements to `%timeit`.
90 * Robert Kern: several extensions.
52 * Robert Kern: several extensions.
91 * Sameer D'Costa: help on critical bug #269966.
53 * Sameer D'Costa: help on critical bug #269966.
92 * Stephan Peijnik: feedback on Debian compliance and many man pages.
54 * Stephan Peijnik: feedback on Debian compliance and many man pages.
55 * Steven Bethard: we are now shipping his :mod:`argparse` module.
93 * Tom Fetherston: many improvements to :mod:`IPython.demo` module.
56 * Tom Fetherston: many improvements to :mod:`IPython.demo` module.
94 * Ville Vainio: lots of work everywhere (features, bug fixes, etc).
57 * Ville Vainio: lots of work everywhere (features, bug fixes, etc).
95 * Vishal Vasta: ssh support in ipcluster.
58 * Vishal Vasta: ssh support in ipcluster.
96 * Walter Doerwald: work on the :mod:`IPython.ipipe` system.
59 * Walter Doerwald: work on the :mod:`IPython.ipipe` system.
97
60
98 Below we give an overview of new features, bug fixes and backwards-incompatible
61 Below we give an overview of new features, bug fixes and backwards-incompatible
99 changes. For a detailed account of every change made, feel free to view the
62 changes. For a detailed account of every change made, feel free to view the
100 project log with :command:`bzr log`.
63 project log with :command:`bzr log`.
101
64
102 New features
65 New features
103 ------------
66 ------------
104
67
105 * New `%paste` magic automatically extracts current contents of clipboard and
68 * New `%paste` magic automatically extracts current contents of clipboard and
106 pastes it directly, while correctly handling code that is indented or
69 pastes it directly, while correctly handling code that is indented or
107 prepended with `>>>` or `...` python prompt markers. A very useful new
70 prepended with `>>>` or `...` python prompt markers. A very useful new
108 feature contributed by Robert Kern.
71 feature contributed by Robert Kern.
109
72
110 * IPython 'demos', created with the :mod:`IPython.demo` module, can now be
73 * IPython 'demos', created with the :mod:`IPython.demo` module, can now be
111 created from files on disk or strings in memory. Other fixes and
74 created from files on disk or strings in memory. Other fixes and
112 improvements to the demo system, by Tom Fetherston.
75 improvements to the demo system, by Tom Fetherston.
113
76
114 * Added :func:`find_cmd` function to :mod:`IPython.platutils` module, to find
77 * Added :func:`find_cmd` function to :mod:`IPython.platutils` module, to find
115 commands in a cross-platform manner.
78 commands in a cross-platform manner.
116
79
117 * Many improvements and fixes to GaΓ«l Varoquaux's :command:`ipythonx`, a
80 * Many improvements and fixes to GaΓ«l Varoquaux's :command:`ipythonx`, a
118 WX-based lightweight IPython instance that can be easily embedded in other WX
81 WX-based lightweight IPython instance that can be easily embedded in other WX
119 applications. These improvements have made it possible to now have an
82 applications. These improvements have made it possible to now have an
120 embedded IPython in Mayavi and other tools.
83 embedded IPython in Mayavi and other tools.
121
84
122 * :class:`MultiengineClient` objects now have a :meth:`benchmark` method.
85 * :class:`MultiengineClient` objects now have a :meth:`benchmark` method.
123
86
124 * The manual now includes a full set of auto-generated API documents from the
87 * The manual now includes a full set of auto-generated API documents from the
125 code sources, using Sphinx and some of our own support code. We are now
88 code sources, using Sphinx and some of our own support code. We are now
126 using the `Numpy Documentation Standard`_ for all docstrings, and we have
89 using the `Numpy Documentation Standard`_ for all docstrings, and we have
127 tried to update as many existing ones as possible to this format.
90 tried to update as many existing ones as possible to this format.
128
91
129 .. _Numpy Documentation Standard: http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard
130
131 * The new :mod:`IPython.Extensions.ipy_pretty` extension by Robert Kern
92 * The new :mod:`IPython.Extensions.ipy_pretty` extension by Robert Kern
132 provides configurable pretty-printing.
93 provides configurable pretty-printing.
133
94
134 * Many improvements to the :command:`ipython-wx` standalone WX-based IPython
95 * Many improvements to the :command:`ipython-wx` standalone WX-based IPython
135 application by Laurent DufrΓ©chou. It can optionally run in a thread, and
96 application by Laurent DufrΓ©chou. It can optionally run in a thread, and
136 this can be toggled at runtime (allowing the loading of Matplotlib in a
97 this can be toggled at runtime (allowing the loading of Matplotlib in a
137 running session without ill effects).
98 running session without ill effects).
138
99
139 * IPython includes a copy of Steven Bethard's argparse_ in the
100 * IPython includes a copy of Steven Bethard's argparse_ in the
140 :mod:`IPython.external` package, so we can use it internally and it is also
101 :mod:`IPython.external` package, so we can use it internally and it is also
141 available to any IPython user. By installing it in this manner, we ensure
102 available to any IPython user. By installing it in this manner, we ensure
142 zero conflicts with any system-wide installation you may already have while
103 zero conflicts with any system-wide installation you may already have while
143 minimizing external dependencies for new users.
104 minimizing external dependencies for new users. In IPython 0.10, We ship
105 argparse version 1.0.
144
106
145 * An improved and much more robust test suite, that runs groups of tests in
107 * An improved and much more robust test suite, that runs groups of tests in
146 separate subprocesses using either Nose or Twisted's :command:`trial` runner
108 separate subprocesses using either Nose or Twisted's :command:`trial` runner
147 to ensure proper management of Twisted-using code. The test suite degrades
109 to ensure proper management of Twisted-using code. The test suite degrades
148 gracefully if optional dependencies are not available, so that the
110 gracefully if optional dependencies are not available, so that the
149 :command:`iptest` command can be run with only Nose installed and nothing
111 :command:`iptest` command can be run with only Nose installed and nothing
150 else. We also have more and cleaner test decorators to better select tests
112 else. We also have more and cleaner test decorators to better select tests
151 depending on runtime conditions, do setup/teardown, etc.
113 depending on runtime conditions, do setup/teardown, etc.
152
114
153 * The new ipcluster now has a fully working ssh mode that should work on
115 * The new ipcluster now has a fully working ssh mode that should work on
154 Linux, Unix and OS X. Thanks to Vishal Vatsa for implementing this!
116 Linux, Unix and OS X. Thanks to Vishal Vatsa for implementing this!
155
117
156 * The wonderful TextMate editor can now be used with %edit on OS X. Thanks
118 * The wonderful TextMate editor can now be used with %edit on OS X. Thanks
157 to Matt Foster for this patch.
119 to Matt Foster for this patch.
158
120
159 * The documentation regarding parallel uses of IPython, including MPI and PBS,
121 * The documentation regarding parallel uses of IPython, including MPI and PBS,
160 has been significantly updated and improved.
122 has been significantly updated and improved.
161
123
162 * The developer guidelines in the documentation have been updated to explain
124 * The developer guidelines in the documentation have been updated to explain
163 our workflow using :command:`bzr` and Launchpad.
125 our workflow using :command:`bzr` and Launchpad.
164
126
165 * Fully refactored :command:`ipcluster` command line program for starting
127 * Fully refactored :command:`ipcluster` command line program for starting
166 IPython clusters. This new version is a complete rewrite and 1) is fully
128 IPython clusters. This new version is a complete rewrite and 1) is fully
167 cross platform (we now use Twisted's process management), 2) has much
129 cross platform (we now use Twisted's process management), 2) has much
168 improved performance, 3) uses subcommands for different types of clusters, 4)
130 improved performance, 3) uses subcommands for different types of clusters, 4)
169 uses argparse for parsing command line options, 5) has better support for
131 uses argparse for parsing command line options, 5) has better support for
170 starting clusters using :command:`mpirun`, 6) has experimental support for
132 starting clusters using :command:`mpirun`, 6) has experimental support for
171 starting engines using PBS. It can also reuse FURL files, by appropriately
133 starting engines using PBS. It can also reuse FURL files, by appropriately
172 passing options to its subcommands. However, this new version of ipcluster
134 passing options to its subcommands. However, this new version of ipcluster
173 should be considered a technology preview. We plan on changing the API in
135 should be considered a technology preview. We plan on changing the API in
174 significant ways before it is final.
136 significant ways before it is final.
175
137
176 * The :mod:`argparse` module has been added to :mod:`IPython.external`.
177
178 * Full description of the security model added to the docs.
138 * Full description of the security model added to the docs.
179
139
180 * cd completer: show bookmarks if no other completions are available.
140 * cd completer: show bookmarks if no other completions are available.
181
141
182 * sh profile: easy way to give 'title' to prompt: assign to variable
142 * sh profile: easy way to give 'title' to prompt: assign to variable
183 '_prompt_title'. It looks like this::
143 '_prompt_title'. It looks like this::
184
144
185 [~]|1> _prompt_title = 'sudo!'
145 [~]|1> _prompt_title = 'sudo!'
186 sudo![~]|2>
146 sudo![~]|2>
187
147
188 * %edit: If you do '%edit pasted_block', pasted_block variable gets updated
148 * %edit: If you do '%edit pasted_block', pasted_block variable gets updated
189 with new data (so repeated editing makes sense)
149 with new data (so repeated editing makes sense)
190
150
151 .. _Numpy Documentation Standard: http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard
152
153 .. _argparse: http://code.google.com/p/argparse/
154
191 Bug fixes
155 Bug fixes
192 ---------
156 ---------
193
157
194 * Fix #368719, removed top-level debian/ directory to make the job of Debian
158 * Fix #368719, removed top-level debian/ directory to make the job of Debian
195 packagers easier.
159 packagers easier.
196
160
197 * Fix #291143 by including man pages contributed by Stephan Peijnik from the
161 * Fix #291143 by including man pages contributed by Stephan Peijnik from the
198 Debian project.
162 Debian project.
199
163
200 * Fix #358202, effectively a race condition, by properly synchronizing file
164 * Fix #358202, effectively a race condition, by properly synchronizing file
201 creation at cluster startup time.
165 creation at cluster startup time.
202
166
203 * `%timeit` now handles correctly functions that take a long time to execute
167 * `%timeit` now handles correctly functions that take a long time to execute
204 even the first time, by not repeating them.
168 even the first time, by not repeating them.
205
169
206 * Fix #239054, releasing of references after exiting.
170 * Fix #239054, releasing of references after exiting.
207
171
208 * Fix #341726, thanks to Alexander Clausen.
172 * Fix #341726, thanks to Alexander Clausen.
209
173
210 * Fix #269966. This long-standing and very difficult bug (which is actually a
174 * Fix #269966. This long-standing and very difficult bug (which is actually a
211 problem in Python itself) meant long-running sessions would inevitably grow
175 problem in Python itself) meant long-running sessions would inevitably grow
212 in memory size, often with catastrophic consequences if users had large
176 in memory size, often with catastrophic consequences if users had large
213 objects in their scripts. Now, using `%run` repeatedly should not cause any
177 objects in their scripts. Now, using `%run` repeatedly should not cause any
214 memory leaks. Special thanks to John Hunter and Sameer D'Costa for their
178 memory leaks. Special thanks to John Hunter and Sameer D'Costa for their
215 help with this bug.
179 help with this bug.
216
180
217 * Fix #295371, bug in `%history`.
181 * Fix #295371, bug in `%history`.
218
182
219 * Improved support for py2exe.
183 * Improved support for py2exe.
220
184
221 * Fix #270856: IPython hangs with PyGTK
185 * Fix #270856: IPython hangs with PyGTK
222
186
223 * Fix #270998: A magic with no docstring breaks the '%magic magic'
187 * Fix #270998: A magic with no docstring breaks the '%magic magic'
224
188
225 * fix #271684: -c startup commands screw up raw vs. native history
189 * fix #271684: -c startup commands screw up raw vs. native history
226
190
227 * Numerous bugs on Windows with the new ipcluster have been fixed.
191 * Numerous bugs on Windows with the new ipcluster have been fixed.
228
192
229 * The ipengine and ipcontroller scripts now handle missing furl files
193 * The ipengine and ipcontroller scripts now handle missing furl files
230 more gracefully by giving better error messages.
194 more gracefully by giving better error messages.
231
195
232 * %rehashx: Aliases no longer contain dots. python3.0 binary
196 * %rehashx: Aliases no longer contain dots. python3.0 binary
233 will create alias python30. Fixes:
197 will create alias python30. Fixes:
234 #259716 "commands with dots in them don't work"
198 #259716 "commands with dots in them don't work"
235
199
236 * %cpaste: %cpaste -r repeats the last pasted block.
200 * %cpaste: %cpaste -r repeats the last pasted block.
237 The block is assigned to pasted_block even if code
201 The block is assigned to pasted_block even if code
238 raises exception.
202 raises exception.
239
203
240 * Bug #274067 'The code in get_home_dir is broken for py2exe' was
204 * Bug #274067 'The code in get_home_dir is broken for py2exe' was
241 fixed.
205 fixed.
242
206
207 * Many other small bug fixes not listed here by number (see the bzr log for
208 more info).
209
243 Backwards incompatible changes
210 Backwards incompatible changes
244 ------------------------------
211 ------------------------------
245
212
246 * `ipykit` and related files were unmaintained and have been removed.
213 * `ipykit` and related files were unmaintained and have been removed.
247
214
248 * The :func:`IPython.genutils.doctest_reload` does not actually call
215 * The :func:`IPython.genutils.doctest_reload` does not actually call
249 `reload(doctest)` anymore, as this was causing many problems with the test
216 `reload(doctest)` anymore, as this was causing many problems with the test
250 suite. It still resets `doctest.master` to None.
217 suite. It still resets `doctest.master` to None.
251
218
252 * While we have not deliberately broken Python 2.4 compatibility, only minor
219 * While we have not deliberately broken Python 2.4 compatibility, only minor
253 testing was done with Python 2.4, while 2.5 and 2.6 were fully tested. But
220 testing was done with Python 2.4, while 2.5 and 2.6 were fully tested. But
254 if you encounter problems with 2.4, please do report them as bugs.
221 if you encounter problems with 2.4, please do report them as bugs.
255
222
256 * The :command:`ipcluster` now requires a mode argument; for example to start a
223 * The :command:`ipcluster` now requires a mode argument; for example to start a
257 cluster on the local machine with 4 engines, you must now type::
224 cluster on the local machine with 4 engines, you must now type::
258
225
259 $ ipcluster local -n 4
226 $ ipcluster local -n 4
260
227
261 * The controller now has a ``-r`` flag that needs to be used if you want to
228 * The controller now has a ``-r`` flag that needs to be used if you want to
262 reuse existing furl files. Otherwise they are deleted (the default).
229 reuse existing furl files. Otherwise they are deleted (the default).
263
230
264 * Remove ipy_leo.py. You can use :command:`easy_install ipython-extension` to
231 * Remove ipy_leo.py. You can use :command:`easy_install ipython-extension` to
265 get it. (done to decouple it from ipython release cycle)
232 get it. (done to decouple it from ipython release cycle)
266
233
267
234
268 Release 0.9.1
235 Release 0.9.1
269 =============
236 =============
270
237
271 This release was quickly made to restore compatibility with Python 2.4, which
238 This release was quickly made to restore compatibility with Python 2.4, which
272 version 0.9 accidentally broke. No new features were introduced, other than
239 version 0.9 accidentally broke. No new features were introduced, other than
273 some additional testing support for internal use.
240 some additional testing support for internal use.
274
241
275
242
276 Release 0.9
243 Release 0.9
277 ===========
244 ===========
278
245
279 New features
246 New features
280 ------------
247 ------------
281
248
282 * All furl files and security certificates are now put in a read-only
249 * All furl files and security certificates are now put in a read-only
283 directory named ~./ipython/security.
250 directory named ~./ipython/security.
284
251
285 * A single function :func:`get_ipython_dir`, in :mod:`IPython.genutils` that
252 * A single function :func:`get_ipython_dir`, in :mod:`IPython.genutils` that
286 determines the user's IPython directory in a robust manner.
253 determines the user's IPython directory in a robust manner.
287
254
288 * Laurent's WX application has been given a top-level script called
255 * Laurent's WX application has been given a top-level script called
289 ipython-wx, and it has received numerous fixes. We expect this code to be
256 ipython-wx, and it has received numerous fixes. We expect this code to be
290 architecturally better integrated with Gael's WX 'ipython widget' over the
257 architecturally better integrated with Gael's WX 'ipython widget' over the
291 next few releases.
258 next few releases.
292
259
293 * The Editor synchronization work by Vivian De Smedt has been merged in. This
260 * The Editor synchronization work by Vivian De Smedt has been merged in. This
294 code adds a number of new editor hooks to synchronize with editors under
261 code adds a number of new editor hooks to synchronize with editors under
295 Windows.
262 Windows.
296
263
297 * A new, still experimental but highly functional, WX shell by Gael Varoquaux.
264 * A new, still experimental but highly functional, WX shell by Gael Varoquaux.
298 This work was sponsored by Enthought, and while it's still very new, it is
265 This work was sponsored by Enthought, and while it's still very new, it is
299 based on a more cleanly organized arhictecture of the various IPython
266 based on a more cleanly organized arhictecture of the various IPython
300 components. We will continue to develop this over the next few releases as a
267 components. We will continue to develop this over the next few releases as a
301 model for GUI components that use IPython.
268 model for GUI components that use IPython.
302
269
303 * Another GUI frontend, Cocoa based (Cocoa is the OSX native GUI framework),
270 * Another GUI frontend, Cocoa based (Cocoa is the OSX native GUI framework),
304 authored by Barry Wark. Currently the WX and the Cocoa ones have slightly
271 authored by Barry Wark. Currently the WX and the Cocoa ones have slightly
305 different internal organizations, but the whole team is working on finding
272 different internal organizations, but the whole team is working on finding
306 what the right abstraction points are for a unified codebase.
273 what the right abstraction points are for a unified codebase.
307
274
308 * As part of the frontend work, Barry Wark also implemented an experimental
275 * As part of the frontend work, Barry Wark also implemented an experimental
309 event notification system that various ipython components can use. In the
276 event notification system that various ipython components can use. In the
310 next release the implications and use patterns of this system regarding the
277 next release the implications and use patterns of this system regarding the
311 various GUI options will be worked out.
278 various GUI options will be worked out.
312
279
313 * IPython finally has a full test system, that can test docstrings with
280 * IPython finally has a full test system, that can test docstrings with
314 IPython-specific functionality. There are still a few pieces missing for it
281 IPython-specific functionality. There are still a few pieces missing for it
315 to be widely accessible to all users (so they can run the test suite at any
282 to be widely accessible to all users (so they can run the test suite at any
316 time and report problems), but it now works for the developers. We are
283 time and report problems), but it now works for the developers. We are
317 working hard on continuing to improve it, as this was probably IPython's
284 working hard on continuing to improve it, as this was probably IPython's
318 major Achilles heel (the lack of proper test coverage made it effectively
285 major Achilles heel (the lack of proper test coverage made it effectively
319 impossible to do large-scale refactoring). The full test suite can now
286 impossible to do large-scale refactoring). The full test suite can now
320 be run using the :command:`iptest` command line program.
287 be run using the :command:`iptest` command line program.
321
288
322 * The notion of a task has been completely reworked. An `ITask` interface has
289 * The notion of a task has been completely reworked. An `ITask` interface has
323 been created. This interface defines the methods that tasks need to
290 been created. This interface defines the methods that tasks need to
324 implement. These methods are now responsible for things like submitting
291 implement. These methods are now responsible for things like submitting
325 tasks and processing results. There are two basic task types:
292 tasks and processing results. There are two basic task types:
326 :class:`IPython.kernel.task.StringTask` (this is the old `Task` object, but
293 :class:`IPython.kernel.task.StringTask` (this is the old `Task` object, but
327 renamed) and the new :class:`IPython.kernel.task.MapTask`, which is based on
294 renamed) and the new :class:`IPython.kernel.task.MapTask`, which is based on
328 a function.
295 a function.
329
296
330 * A new interface, :class:`IPython.kernel.mapper.IMapper` has been defined to
297 * A new interface, :class:`IPython.kernel.mapper.IMapper` has been defined to
331 standardize the idea of a `map` method. This interface has a single `map`
298 standardize the idea of a `map` method. This interface has a single `map`
332 method that has the same syntax as the built-in `map`. We have also defined
299 method that has the same syntax as the built-in `map`. We have also defined
333 a `mapper` factory interface that creates objects that implement
300 a `mapper` factory interface that creates objects that implement
334 :class:`IPython.kernel.mapper.IMapper` for different controllers. Both the
301 :class:`IPython.kernel.mapper.IMapper` for different controllers. Both the
335 multiengine and task controller now have mapping capabilties.
302 multiengine and task controller now have mapping capabilties.
336
303
337 * The parallel function capabilities have been reworks. The major changes are
304 * The parallel function capabilities have been reworks. The major changes are
338 that i) there is now an `@parallel` magic that creates parallel functions,
305 that i) there is now an `@parallel` magic that creates parallel functions,
339 ii) the syntax for mulitple variable follows that of `map`, iii) both the
306 ii) the syntax for mulitple variable follows that of `map`, iii) both the
340 multiengine and task controller now have a parallel function implementation.
307 multiengine and task controller now have a parallel function implementation.
341
308
342 * All of the parallel computing capabilities from `ipython1-dev` have been
309 * All of the parallel computing capabilities from `ipython1-dev` have been
343 merged into IPython proper. This resulted in the following new subpackages:
310 merged into IPython proper. This resulted in the following new subpackages:
344 :mod:`IPython.kernel`, :mod:`IPython.kernel.core`, :mod:`IPython.config`,
311 :mod:`IPython.kernel`, :mod:`IPython.kernel.core`, :mod:`IPython.config`,
345 :mod:`IPython.tools` and :mod:`IPython.testing`.
312 :mod:`IPython.tools` and :mod:`IPython.testing`.
346
313
347 * As part of merging in the `ipython1-dev` stuff, the `setup.py` script and
314 * As part of merging in the `ipython1-dev` stuff, the `setup.py` script and
348 friends have been completely refactored. Now we are checking for
315 friends have been completely refactored. Now we are checking for
349 dependencies using the approach that matplotlib uses.
316 dependencies using the approach that matplotlib uses.
350
317
351 * The documentation has been completely reorganized to accept the
318 * The documentation has been completely reorganized to accept the
352 documentation from `ipython1-dev`.
319 documentation from `ipython1-dev`.
353
320
354 * We have switched to using Foolscap for all of our network protocols in
321 * We have switched to using Foolscap for all of our network protocols in
355 :mod:`IPython.kernel`. This gives us secure connections that are both
322 :mod:`IPython.kernel`. This gives us secure connections that are both
356 encrypted and authenticated.
323 encrypted and authenticated.
357
324
358 * We have a brand new `COPYING.txt` files that describes the IPython license
325 * We have a brand new `COPYING.txt` files that describes the IPython license
359 and copyright. The biggest change is that we are putting "The IPython
326 and copyright. The biggest change is that we are putting "The IPython
360 Development Team" as the copyright holder. We give more details about
327 Development Team" as the copyright holder. We give more details about
361 exactly what this means in this file. All developer should read this and use
328 exactly what this means in this file. All developer should read this and use
362 the new banner in all IPython source code files.
329 the new banner in all IPython source code files.
363
330
364 * sh profile: ./foo runs foo as system command, no need to do !./foo anymore
331 * sh profile: ./foo runs foo as system command, no need to do !./foo anymore
365
332
366 * String lists now support ``sort(field, nums = True)`` method (to easily sort
333 * String lists now support ``sort(field, nums = True)`` method (to easily sort
367 system command output). Try it with ``a = !ls -l ; a.sort(1, nums=1)``.
334 system command output). Try it with ``a = !ls -l ; a.sort(1, nums=1)``.
368
335
369 * '%cpaste foo' now assigns the pasted block as string list, instead of string
336 * '%cpaste foo' now assigns the pasted block as string list, instead of string
370
337
371 * The ipcluster script now run by default with no security. This is done
338 * The ipcluster script now run by default with no security. This is done
372 because the main usage of the script is for starting things on localhost.
339 because the main usage of the script is for starting things on localhost.
373 Eventually when ipcluster is able to start things on other hosts, we will put
340 Eventually when ipcluster is able to start things on other hosts, we will put
374 security back.
341 security back.
375
342
376 * 'cd --foo' searches directory history for string foo, and jumps to that dir.
343 * 'cd --foo' searches directory history for string foo, and jumps to that dir.
377 Last part of dir name is checked first. If no matches for that are found,
344 Last part of dir name is checked first. If no matches for that are found,
378 look at the whole path.
345 look at the whole path.
379
346
380
347
381 Bug fixes
348 Bug fixes
382 ---------
349 ---------
383
350
384 * The Windows installer has been fixed. Now all IPython scripts have ``.bat``
351 * The Windows installer has been fixed. Now all IPython scripts have ``.bat``
385 versions created. Also, the Start Menu shortcuts have been updated.
352 versions created. Also, the Start Menu shortcuts have been updated.
386
353
387 * The colors escapes in the multiengine client are now turned off on win32 as
354 * The colors escapes in the multiengine client are now turned off on win32 as
388 they don't print correctly.
355 they don't print correctly.
389
356
390 * The :mod:`IPython.kernel.scripts.ipengine` script was exec'ing
357 * The :mod:`IPython.kernel.scripts.ipengine` script was exec'ing
391 mpi_import_statement incorrectly, which was leading the engine to crash when
358 mpi_import_statement incorrectly, which was leading the engine to crash when
392 mpi was enabled.
359 mpi was enabled.
393
360
394 * A few subpackages had missing ``__init__.py`` files.
361 * A few subpackages had missing ``__init__.py`` files.
395
362
396 * The documentation is only created if Sphinx is found. Previously, the
363 * The documentation is only created if Sphinx is found. Previously, the
397 ``setup.py`` script would fail if it was missing.
364 ``setup.py`` script would fail if it was missing.
398
365
399 * Greedy ``cd`` completion has been disabled again (it was enabled in 0.8.4) as
366 * Greedy ``cd`` completion has been disabled again (it was enabled in 0.8.4) as
400 it caused problems on certain platforms.
367 it caused problems on certain platforms.
401
368
402
369
403 Backwards incompatible changes
370 Backwards incompatible changes
404 ------------------------------
371 ------------------------------
405
372
406 * The ``clusterfile`` options of the :command:`ipcluster` command has been
373 * The ``clusterfile`` options of the :command:`ipcluster` command has been
407 removed as it was not working and it will be replaced soon by something much
374 removed as it was not working and it will be replaced soon by something much
408 more robust.
375 more robust.
409
376
410 * The :mod:`IPython.kernel` configuration now properly find the user's
377 * The :mod:`IPython.kernel` configuration now properly find the user's
411 IPython directory.
378 IPython directory.
412
379
413 * In ipapi, the :func:`make_user_ns` function has been replaced with
380 * In ipapi, the :func:`make_user_ns` function has been replaced with
414 :func:`make_user_namespaces`, to support dict subclasses in namespace
381 :func:`make_user_namespaces`, to support dict subclasses in namespace
415 creation.
382 creation.
416
383
417 * :class:`IPython.kernel.client.Task` has been renamed
384 * :class:`IPython.kernel.client.Task` has been renamed
418 :class:`IPython.kernel.client.StringTask` to make way for new task types.
385 :class:`IPython.kernel.client.StringTask` to make way for new task types.
419
386
420 * The keyword argument `style` has been renamed `dist` in `scatter`, `gather`
387 * The keyword argument `style` has been renamed `dist` in `scatter`, `gather`
421 and `map`.
388 and `map`.
422
389
423 * Renamed the values that the rename `dist` keyword argument can have from
390 * Renamed the values that the rename `dist` keyword argument can have from
424 `'basic'` to `'b'`.
391 `'basic'` to `'b'`.
425
392
426 * IPython has a larger set of dependencies if you want all of its capabilities.
393 * IPython has a larger set of dependencies if you want all of its capabilities.
427 See the `setup.py` script for details.
394 See the `setup.py` script for details.
428
395
429 * The constructors for :class:`IPython.kernel.client.MultiEngineClient` and
396 * The constructors for :class:`IPython.kernel.client.MultiEngineClient` and
430 :class:`IPython.kernel.client.TaskClient` no longer take the (ip,port) tuple.
397 :class:`IPython.kernel.client.TaskClient` no longer take the (ip,port) tuple.
431 Instead they take the filename of a file that contains the FURL for that
398 Instead they take the filename of a file that contains the FURL for that
432 client. If the FURL file is in your IPYTHONDIR, it will be found automatically
399 client. If the FURL file is in your IPYTHONDIR, it will be found automatically
433 and the constructor can be left empty.
400 and the constructor can be left empty.
434
401
435 * The asynchronous clients in :mod:`IPython.kernel.asyncclient` are now created
402 * The asynchronous clients in :mod:`IPython.kernel.asyncclient` are now created
436 using the factory functions :func:`get_multiengine_client` and
403 using the factory functions :func:`get_multiengine_client` and
437 :func:`get_task_client`. These return a `Deferred` to the actual client.
404 :func:`get_task_client`. These return a `Deferred` to the actual client.
438
405
439 * The command line options to `ipcontroller` and `ipengine` have changed to
406 * The command line options to `ipcontroller` and `ipengine` have changed to
440 reflect the new Foolscap network protocol and the FURL files. Please see the
407 reflect the new Foolscap network protocol and the FURL files. Please see the
441 help for these scripts for details.
408 help for these scripts for details.
442
409
443 * The configuration files for the kernel have changed because of the Foolscap
410 * The configuration files for the kernel have changed because of the Foolscap
444 stuff. If you were using custom config files before, you should delete them
411 stuff. If you were using custom config files before, you should delete them
445 and regenerate new ones.
412 and regenerate new ones.
446
413
447 Changes merged in from IPython1
414 Changes merged in from IPython1
448 -------------------------------
415 -------------------------------
449
416
450 New features
417 New features
451 ............
418 ............
452
419
453 * Much improved ``setup.py`` and ``setupegg.py`` scripts. Because Twisted and
420 * Much improved ``setup.py`` and ``setupegg.py`` scripts. Because Twisted and
454 zope.interface are now easy installable, we can declare them as dependencies
421 zope.interface are now easy installable, we can declare them as dependencies
455 in our setupegg.py script.
422 in our setupegg.py script.
456
423
457 * IPython is now compatible with Twisted 2.5.0 and 8.x.
424 * IPython is now compatible with Twisted 2.5.0 and 8.x.
458
425
459 * Added a new example of how to use :mod:`ipython1.kernel.asynclient`.
426 * Added a new example of how to use :mod:`ipython1.kernel.asynclient`.
460
427
461 * Initial draft of a process daemon in :mod:`ipython1.daemon`. This has not
428 * Initial draft of a process daemon in :mod:`ipython1.daemon`. This has not
462 been merged into IPython and is still in `ipython1-dev`.
429 been merged into IPython and is still in `ipython1-dev`.
463
430
464 * The ``TaskController`` now has methods for getting the queue status.
431 * The ``TaskController`` now has methods for getting the queue status.
465
432
466 * The ``TaskResult`` objects not have information about how long the task
433 * The ``TaskResult`` objects not have information about how long the task
467 took to run.
434 took to run.
468
435
469 * We are attaching additional attributes to exceptions ``(_ipython_*)`` that
436 * We are attaching additional attributes to exceptions ``(_ipython_*)`` that
470 we use to carry additional info around.
437 we use to carry additional info around.
471
438
472 * New top-level module :mod:`asyncclient` that has asynchronous versions (that
439 * New top-level module :mod:`asyncclient` that has asynchronous versions (that
473 return deferreds) of the client classes. This is designed to users who want
440 return deferreds) of the client classes. This is designed to users who want
474 to run their own Twisted reactor.
441 to run their own Twisted reactor.
475
442
476 * All the clients in :mod:`client` are now based on Twisted. This is done by
443 * All the clients in :mod:`client` are now based on Twisted. This is done by
477 running the Twisted reactor in a separate thread and using the
444 running the Twisted reactor in a separate thread and using the
478 :func:`blockingCallFromThread` function that is in recent versions of Twisted.
445 :func:`blockingCallFromThread` function that is in recent versions of Twisted.
479
446
480 * Functions can now be pushed/pulled to/from engines using
447 * Functions can now be pushed/pulled to/from engines using
481 :meth:`MultiEngineClient.push_function` and
448 :meth:`MultiEngineClient.push_function` and
482 :meth:`MultiEngineClient.pull_function`.
449 :meth:`MultiEngineClient.pull_function`.
483
450
484 * Gather/scatter are now implemented in the client to reduce the work load
451 * Gather/scatter are now implemented in the client to reduce the work load
485 of the controller and improve performance.
452 of the controller and improve performance.
486
453
487 * Complete rewrite of the IPython docuementation. All of the documentation
454 * Complete rewrite of the IPython docuementation. All of the documentation
488 from the IPython website has been moved into docs/source as restructured
455 from the IPython website has been moved into docs/source as restructured
489 text documents. PDF and HTML documentation are being generated using
456 text documents. PDF and HTML documentation are being generated using
490 Sphinx.
457 Sphinx.
491
458
492 * New developer oriented documentation: development guidelines and roadmap.
459 * New developer oriented documentation: development guidelines and roadmap.
493
460
494 * Traditional ``ChangeLog`` has been changed to a more useful ``changes.txt``
461 * Traditional ``ChangeLog`` has been changed to a more useful ``changes.txt``
495 file that is organized by release and is meant to provide something more
462 file that is organized by release and is meant to provide something more
496 relevant for users.
463 relevant for users.
497
464
498 Bug fixes
465 Bug fixes
499 .........
466 .........
500
467
501 * Created a proper ``MANIFEST.in`` file to create source distributions.
468 * Created a proper ``MANIFEST.in`` file to create source distributions.
502
469
503 * Fixed a bug in the ``MultiEngine`` interface. Previously, multi-engine
470 * Fixed a bug in the ``MultiEngine`` interface. Previously, multi-engine
504 actions were being collected with a :class:`DeferredList` with
471 actions were being collected with a :class:`DeferredList` with
505 ``fireononeerrback=1``. This meant that methods were returning
472 ``fireononeerrback=1``. This meant that methods were returning
506 before all engines had given their results. This was causing extremely odd
473 before all engines had given their results. This was causing extremely odd
507 bugs in certain cases. To fix this problem, we have 1) set
474 bugs in certain cases. To fix this problem, we have 1) set
508 ``fireononeerrback=0`` to make sure all results (or exceptions) are in
475 ``fireononeerrback=0`` to make sure all results (or exceptions) are in
509 before returning and 2) introduced a :exc:`CompositeError` exception
476 before returning and 2) introduced a :exc:`CompositeError` exception
510 that wraps all of the engine exceptions. This is a huge change as it means
477 that wraps all of the engine exceptions. This is a huge change as it means
511 that users will have to catch :exc:`CompositeError` rather than the actual
478 that users will have to catch :exc:`CompositeError` rather than the actual
512 exception.
479 exception.
513
480
514 Backwards incompatible changes
481 Backwards incompatible changes
515 ..............................
482 ..............................
516
483
517 * All names have been renamed to conform to the lowercase_with_underscore
484 * All names have been renamed to conform to the lowercase_with_underscore
518 convention. This will require users to change references to all names like
485 convention. This will require users to change references to all names like
519 ``queueStatus`` to ``queue_status``.
486 ``queueStatus`` to ``queue_status``.
520
487
521 * Previously, methods like :meth:`MultiEngineClient.push` and
488 * Previously, methods like :meth:`MultiEngineClient.push` and
522 :meth:`MultiEngineClient.push` used ``*args`` and ``**kwargs``. This was
489 :meth:`MultiEngineClient.push` used ``*args`` and ``**kwargs``. This was
523 becoming a problem as we weren't able to introduce new keyword arguments into
490 becoming a problem as we weren't able to introduce new keyword arguments into
524 the API. Now these methods simple take a dict or sequence. This has also
491 the API. Now these methods simple take a dict or sequence. This has also
525 allowed us to get rid of the ``*All`` methods like :meth:`pushAll` and
492 allowed us to get rid of the ``*All`` methods like :meth:`pushAll` and
526 :meth:`pullAll`. These things are now handled with the ``targets`` keyword
493 :meth:`pullAll`. These things are now handled with the ``targets`` keyword
527 argument that defaults to ``'all'``.
494 argument that defaults to ``'all'``.
528
495
529 * The :attr:`MultiEngineClient.magicTargets` has been renamed to
496 * The :attr:`MultiEngineClient.magicTargets` has been renamed to
530 :attr:`MultiEngineClient.targets`.
497 :attr:`MultiEngineClient.targets`.
531
498
532 * All methods in the MultiEngine interface now accept the optional keyword
499 * All methods in the MultiEngine interface now accept the optional keyword
533 argument ``block``.
500 argument ``block``.
534
501
535 * Renamed :class:`RemoteController` to :class:`MultiEngineClient` and
502 * Renamed :class:`RemoteController` to :class:`MultiEngineClient` and
536 :class:`TaskController` to :class:`TaskClient`.
503 :class:`TaskController` to :class:`TaskClient`.
537
504
538 * Renamed the top-level module from :mod:`api` to :mod:`client`.
505 * Renamed the top-level module from :mod:`api` to :mod:`client`.
539
506
540 * Most methods in the multiengine interface now raise a :exc:`CompositeError`
507 * Most methods in the multiengine interface now raise a :exc:`CompositeError`
541 exception that wraps the user's exceptions, rather than just raising the raw
508 exception that wraps the user's exceptions, rather than just raising the raw
542 user's exception.
509 user's exception.
543
510
544 * Changed the ``setupNS`` and ``resultNames`` in the ``Task`` class to ``push``
511 * Changed the ``setupNS`` and ``resultNames`` in the ``Task`` class to ``push``
545 and ``pull``.
512 and ``pull``.
546
513
547
514
548 Release 0.8.4
515 Release 0.8.4
549 =============
516 =============
550
517
551 This was a quick release to fix an unfortunate bug that slipped into the 0.8.3
518 This was a quick release to fix an unfortunate bug that slipped into the 0.8.3
552 release. The ``--twisted`` option was disabled, as it turned out to be broken
519 release. The ``--twisted`` option was disabled, as it turned out to be broken
553 across several platforms.
520 across several platforms.
554
521
555
522
556 Release 0.8.3
523 Release 0.8.3
557 =============
524 =============
558
525
559 * pydb is now disabled by default (due to %run -d problems). You can enable
526 * pydb is now disabled by default (due to %run -d problems). You can enable
560 it by passing -pydb command line argument to IPython. Note that setting
527 it by passing -pydb command line argument to IPython. Note that setting
561 it in config file won't work.
528 it in config file won't work.
562
529
563
530
564 Release 0.8.2
531 Release 0.8.2
565 =============
532 =============
566
533
567 * %pushd/%popd behave differently; now "pushd /foo" pushes CURRENT directory
534 * %pushd/%popd behave differently; now "pushd /foo" pushes CURRENT directory
568 and jumps to /foo. The current behaviour is closer to the documented
535 and jumps to /foo. The current behaviour is closer to the documented
569 behaviour, and should not trip anyone.
536 behaviour, and should not trip anyone.
570
537
571
538
572 Older releases
539 Older releases
573 ==============
540 ==============
574
541
575 Changes in earlier releases of IPython are described in the older file
542 Changes in earlier releases of IPython are described in the older file
576 ``ChangeLog``. Please refer to this document for details.
543 ``ChangeLog``. Please refer to this document for details.
577
544
@@ -1,494 +1,515 b''
1 .. _development:
1 .. _development:
2
2
3 ==============================
3 ==============================
4 IPython development guidelines
4 IPython development guidelines
5 ==============================
5 ==============================
6
6
7
7
8 Overview
8 Overview
9 ========
9 ========
10
10
11 This document describes IPython from the perspective of developers. Most
11 This document describes IPython from the perspective of developers. Most
12 importantly, it gives information for people who want to contribute to the
12 importantly, it gives information for people who want to contribute to the
13 development of IPython. So if you want to help out, read on!
13 development of IPython. So if you want to help out, read on!
14
14
15 How to contribute to IPython
15 How to contribute to IPython
16 ============================
16 ============================
17
17
18 IPython development is done using Bazaar [Bazaar]_ and Launchpad [Launchpad]_.
18 IPython development is done using Bazaar [Bazaar]_ and Launchpad [Launchpad]_.
19 This makes it easy for people to contribute to the development of IPython.
19 This makes it easy for people to contribute to the development of IPython.
20 There are several ways in which you can join in.
20 There are several ways in which you can join in.
21
21
22 If you have a small change that you want to send to the team, you can edit your
22 If you have a small change that you want to send to the team, you can edit your
23 bazaar checkout of IPython (see below) in-place, and ask bazaar for the
23 bazaar checkout of IPython (see below) in-place, and ask bazaar for the
24 differences::
24 differences::
25
25
26 $ cd /path/to/your/copy/of/ipython
26 $ cd /path/to/your/copy/of/ipython
27 $ bzr diff > my_fixes.diff
27 $ bzr diff > my_fixes.diff
28
28
29 This produces a patch file with your fixes, which we can apply to the source
29 This produces a patch file with your fixes, which we can apply to the source
30 tree. This file should then be attached to a ticket in our `bug tracker
30 tree. This file should then be attached to a ticket in our `bug tracker
31 <https://bugs.launchpad.net/ipython>`_, indicating what it does.
31 <https://bugs.launchpad.net/ipython>`_, indicating what it does.
32
32
33 This model of creating small, self-contained patches works very well and there
33 This model of creating small, self-contained patches works very well and there
34 are open source projects that do their entire development this way. However,
34 are open source projects that do their entire development this way. However,
35 in IPython we have found that for tracking larger changes, making use of
35 in IPython we have found that for tracking larger changes, making use of
36 bazaar's full capabilities in conjunction with Launchpad's code hosting
36 bazaar's full capabilities in conjunction with Launchpad's code hosting
37 services makes for a much better experience.
37 services makes for a much better experience.
38
38
39 Making your own branch of IPython allows you to refine your changes over time,
39 Making your own branch of IPython allows you to refine your changes over time,
40 track the development of the main team, and propose your own full version of
40 track the development of the main team, and propose your own full version of
41 the code for others to use and review, with a minimum amount of fuss. The next
41 the code for others to use and review, with a minimum amount of fuss. The next
42 parts of this document will explain how to do this.
42 parts of this document will explain how to do this.
43
43
44 Install Bazaar and create a Launchpad account
44 Install Bazaar and create a Launchpad account
45 ---------------------------------------------
45 ---------------------------------------------
46
46
47 First make sure you have installed Bazaar (see their `website
47 First make sure you have installed Bazaar (see their `website
48 <http://bazaar-vcs.org/>`_). To see that Bazaar is installed and knows about
48 <http://bazaar-vcs.org/>`_). To see that Bazaar is installed and knows about
49 you, try the following::
49 you, try the following::
50
50
51 $ bzr whoami
51 $ bzr whoami
52 Joe Coder <jcoder@gmail.com>
52 Joe Coder <jcoder@gmail.com>
53
53
54 This should display your name and email. Next, you will want to create an
54 This should display your name and email. Next, you will want to create an
55 account on the `Launchpad website <http://www.launchpad.net>`_ and setup your
55 account on the `Launchpad website <http://www.launchpad.net>`_ and setup your
56 ssh keys. For more information of setting up your ssh keys, see `this link
56 ssh keys. For more information of setting up your ssh keys, see `this link
57 <https://help.launchpad.net/YourAccount/CreatingAnSSHKeyPair>`_.
57 <https://help.launchpad.net/YourAccount/CreatingAnSSHKeyPair>`_.
58
58
59 Get the main IPython branch from Launchpad
59 Get the main IPython branch from Launchpad
60 ------------------------------------------
60 ------------------------------------------
61
61
62 Now, you can get a copy of the main IPython development branch (we call this
62 Now, you can get a copy of the main IPython development branch (we call this
63 the "trunk")::
63 the "trunk")::
64
64
65 $ bzr branch lp:ipython
65 $ bzr branch lp:ipython
66
66
67 Create a working branch
67 Create a working branch
68 -----------------------
68 -----------------------
69
69
70 When working on IPython, you won't actually make edits directly to the
70 When working on IPython, you won't actually make edits directly to the
71 :file:`lp:ipython` branch. Instead, you will create a separate branch for your
71 :file:`lp:ipython` branch. Instead, you will create a separate branch for your
72 changes. For now, let's assume you want to do your work in a branch named
72 changes. For now, let's assume you want to do your work in a branch named
73 "ipython-mybranch". Create this branch by doing::
73 "ipython-mybranch". Create this branch by doing::
74
74
75 $ bzr branch ipython ipython-mybranch
75 $ bzr branch ipython ipython-mybranch
76
76
77 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
78 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
79 "install-docs-update".
79 "install-docs-update".
80
80
81 Make edits in your working branch
81 Make edits in your working branch
82 ---------------------------------
82 ---------------------------------
83
83
84 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`
85 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
86 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
87 installed. Then, just do::
87 installed. Then, just do::
88
88
89 $ cd ipython-mybranch
89 $ cd ipython-mybranch
90 $ python setupegg.py develop
90 $ python setupegg.py develop
91
91
92 Now, make some changes. After a while, you will want to commit your changes.
92 Now, make some changes. After a while, you will want to commit your changes.
93 This let's Bazaar know that you like the changes you have made and gives you
93 This let's Bazaar know that you like the changes you have made and gives you
94 an opportunity to keep a nice record of what you have done. This looks like
94 an opportunity to keep a nice record of what you have done. This looks like
95 this::
95 this::
96
96
97 $ ...do work in ipython-mybranch...
97 $ ...do work in ipython-mybranch...
98 $ bzr commit -m "the commit message goes here"
98 $ bzr commit -m "the commit message goes here"
99
99
100 Please note that since we now don't use an old-style linear ChangeLog (that
100 Please note that since we now don't use an old-style linear ChangeLog (that
101 tends to cause problems with distributed version control systems), you should
101 tends to cause problems with distributed version control systems), you should
102 ensure that your log messages are reasonably detailed. Use a docstring-like
102 ensure that your log messages are reasonably detailed. Use a docstring-like
103 approach in the commit messages (including the second line being left
103 approach in the commit messages (including the second line being left
104 *blank*)::
104 *blank*)::
105
105
106 Single line summary of changes being committed.
106 Single line summary of changes being committed.
107
107
108 * more details when warranted ...
108 * more details when warranted ...
109 * including crediting outside contributors if they sent the
109 * including crediting outside contributors if they sent the
110 code/bug/idea!
110 code/bug/idea!
111
111
112 As you work, you will repeat this edit/commit cycle many times. If you work on
112 As you work, you will repeat this edit/commit cycle many times. If you work on
113 your branch for a long time, you will also want to get the latest changes from
113 your branch for a long time, you will also want to get the latest changes from
114 the :file:`lp:ipython` branch. This can be done with the following sequence of
114 the :file:`lp:ipython` branch. This can be done with the following sequence of
115 commands::
115 commands::
116
116
117 $ ls
117 $ ls
118 ipython
118 ipython
119 ipython-mybranch
119 ipython-mybranch
120
120
121 $ cd ipython
121 $ cd ipython
122 $ bzr pull
122 $ bzr pull
123 $ cd ../ipython-mybranch
123 $ cd ../ipython-mybranch
124 $ bzr merge ../ipython
124 $ bzr merge ../ipython
125 $ bzr commit -m "Merging changes from trunk"
125 $ bzr commit -m "Merging changes from trunk"
126
126
127 Along the way, you should also run the IPython test suite. You can do this
127 Along the way, you should also run the IPython test suite. You can do this
128 using the :command:`iptest` command (which is basically a customized version of
128 using the :command:`iptest` command (which is basically a customized version of
129 :command:`nosetests`)::
129 :command:`nosetests`)::
130
130
131 $ cd
131 $ cd
132 $ iptest
132 $ iptest
133
133
134 The :command:`iptest` command will also pick up and run any tests you have
134 The :command:`iptest` command will also pick up and run any tests you have
135 written. See :ref:`_devel_testing` for further details on the testing system.
135 written. See :ref:`_devel_testing` for further details on the testing system.
136
136
137
137
138 Post your branch and request a code review
138 Post your branch and request a code review
139 ------------------------------------------
139 ------------------------------------------
140
140
141 Once you are done with your edits, you should post your branch on Launchpad so
141 Once you are done with your edits, you should post your branch on Launchpad so
142 that other IPython developers can review the changes and help you merge your
142 that other IPython developers can review the changes and help you merge your
143 changes into the main development branch. To post your branch on Launchpad,
143 changes into the main development branch. To post your branch on Launchpad,
144 do::
144 do::
145
145
146 $ cd ipython-mybranch
146 $ cd ipython-mybranch
147 $ bzr push lp:~yourusername/ipython/ipython-mybranch
147 $ bzr push lp:~yourusername/ipython/ipython-mybranch
148
148
149 Then, go to the `IPython Launchpad site <www.launchpad.net/ipython>`_, and you
149 Then, go to the `IPython Launchpad site <www.launchpad.net/ipython>`_, and you
150 should see your branch under the "Code" tab. If you click on your branch, you
150 should see your branch under the "Code" tab. If you click on your branch, you
151 can provide a short description of the branch as well as mark its status. Most
151 can provide a short description of the branch as well as mark its status. Most
152 importantly, you should click the link that reads "Propose for merging into
152 importantly, you should click the link that reads "Propose for merging into
153 another branch". What does this do?
153 another branch". What does this do?
154
154
155 This let's the other IPython developers know that your branch is ready to be
155 This let's the other IPython developers know that your branch is ready to be
156 reviewed and merged into the main development branch. During this review
156 reviewed and merged into the main development branch. During this review
157 process, other developers will give you feedback and help you get your code
157 process, other developers will give you feedback and help you get your code
158 ready to be merged. What types of things will we be looking for:
158 ready to be merged. What types of things will we be looking for:
159
159
160 * All code is documented.
160 * All code is documented.
161 * All code has tests.
161 * All code has tests.
162 * The entire IPython test suite passes.
162 * The entire IPython test suite passes.
163
163
164 Once your changes have been reviewed and approved, someone will merge them
164 Once your changes have been reviewed and approved, someone will merge them
165 into the main development branch.
165 into the main development branch.
166
166
167
168 Some notes for core developers when merging third-party contributions
169 =====================================================================
170
171 Core developers, who ultimately merge any approved branch (from themselves,
172 another developer, or any third-party contribution) will typically use
173 :command:`bzr merge` to merge the branch into the trunk and push it to the main
174 Launcphad site. This is a short list of things to keep in mind when doing this
175 process, so that the project history is easy to understand in the long run, and
176 that generating release notes is as painless and accurate as possible.
177
178 - When you merge any non-trivial functionality (from one small bug fix to a big
179 feature branch), please remember to always edit the changes_ file
180 accordingly. This file has one main section for each release, and if you
181 edit it as you go, noting what new features, bug fixes or API changes you
182 have made, the release notes will be almost finished when they are needed
183 later. This is much easier if done when you merge the work, rather than
184 weeks or months later by re-reading a massive Bazaar log.
185
186 - When big merges are done, the practice of putting a summary commit message in
187 the merge is *extremely* useful. It makes this kind of job much nicer,
188 because that summary log message can be almost copy/pasted without changes,
189 if it was well written, rather than dissecting the next-level messages from
190 the individual commits.
191
192 - It's important that we remember to always credit who gave us something if
193 it's not the committer. In general, we have been fairly good on this front,
194 this is just a reminder to keep things up. As a note, if you are ever
195 committing something that is completely (or almost so) a third-party
196 contribution, do the commit as::
197
198 $ bzr commit --author="Someone Else"
199
200 This way it will show that name separately in the log, which makes it even
201 easier to spot. Obviously we often rework third party contributions
202 extensively, but this is still good to keep in mind for cases when we don't
203 touch the code too much.
204
205
167 Documentation
206 Documentation
168 =============
207 =============
169
208
170 Standalone documentation
209 Standalone documentation
171 ------------------------
210 ------------------------
172
211
173 All standalone documentation should be written in plain text (``.txt``) files
212 All standalone documentation should be written in plain text (``.txt``) files
174 using reStructuredText [reStructuredText]_ for markup and formatting. All such
213 using reStructuredText [reStructuredText]_ for markup and formatting. All such
175 documentation should be placed in directory :file:`docs/source` of the IPython
214 documentation should be placed in directory :file:`docs/source` of the IPython
176 source tree. The documentation in this location will serve as the main source
215 source tree. The documentation in this location will serve as the main source
177 for IPython documentation and all existing documentation should be converted
216 for IPython documentation and all existing documentation should be converted
178 to this format.
217 to this format.
179
218
180 To build the final documentation, we use Sphinx [Sphinx]_. Once you have
219 To build the final documentation, we use Sphinx [Sphinx]_. Once you have
181 Sphinx installed, you can build the html docs yourself by doing::
220 Sphinx installed, you can build the html docs yourself by doing::
182
221
183 $ cd ipython-mybranch/docs
222 $ cd ipython-mybranch/docs
184 $ make html
223 $ make html
185
224
186 Docstring format
225 Docstring format
187 ----------------
226 ----------------
188
227
189 Good docstrings are very important. All new code should have docstrings that
228 Good docstrings are very important. All new code should have docstrings that
190 are formatted using reStructuredText for markup and formatting, since it is
229 are formatted using reStructuredText for markup and formatting, since it is
191 understood by a wide variety of tools. Details about using reStructuredText
230 understood by a wide variety of tools. Details about using reStructuredText
192 for docstrings can be found `here
231 for docstrings can be found `here
193 <http://epydoc.sourceforge.net/manual-othermarkup.html>`_.
232 <http://epydoc.sourceforge.net/manual-othermarkup.html>`_.
194
233
195 Additional PEPs of interest regarding documentation of code:
234 Additional PEPs of interest regarding documentation of code:
196
235
197 * `Docstring Conventions <http://www.python.org/peps/pep-0257.html>`_
236 * `Docstring Conventions <http://www.python.org/peps/pep-0257.html>`_
198 * `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_
237 * `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_
199 * `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_
238 * `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_
200
239
201
240
202 Coding conventions
241 Coding conventions
203 ==================
242 ==================
204
243
205 General
244 General
206 -------
245 -------
207
246
208 In general, we'll try to follow the standard Python style conventions as
247 In general, we'll try to follow the standard Python style conventions as
209 described here:
248 described here:
210
249
211 * `Style Guide for Python Code <http://www.python.org/peps/pep-0008.html>`_
250 * `Style Guide for Python Code <http://www.python.org/peps/pep-0008.html>`_
212
251
213
252
214 Other comments:
253 Other comments:
215
254
216 * In a large file, top level classes and functions should be
255 * In a large file, top level classes and functions should be
217 separated by 2-3 lines to make it easier to separate them visually.
256 separated by 2-3 lines to make it easier to separate them visually.
218 * Use 4 spaces for indentation.
257 * Use 4 spaces for indentation.
219 * Keep the ordering of methods the same in classes that have the same
258 * Keep the ordering of methods the same in classes that have the same
220 methods. This is particularly true for classes that implement an interface.
259 methods. This is particularly true for classes that implement an interface.
221
260
222 Naming conventions
261 Naming conventions
223 ------------------
262 ------------------
224
263
225 In terms of naming conventions, we'll follow the guidelines from the `Style
264 In terms of naming conventions, we'll follow the guidelines from the `Style
226 Guide for Python Code`_.
265 Guide for Python Code`_.
227
266
228 For all new IPython code (and much existing code is being refactored), we'll
267 For all new IPython code (and much existing code is being refactored), we'll
229 use:
268 use:
230
269
231 * All ``lowercase`` module names.
270 * All ``lowercase`` module names.
232
271
233 * ``CamelCase`` for class names.
272 * ``CamelCase`` for class names.
234
273
235 * ``lowercase_with_underscores`` for methods, functions, variables and
274 * ``lowercase_with_underscores`` for methods, functions, variables and
236 attributes.
275 attributes.
237
276
238 There are, however, some important exceptions to these rules. In some cases,
277 There are, however, some important exceptions to these rules. In some cases,
239 IPython code will interface with packages (Twisted, Wx, Qt) that use other
278 IPython code will interface with packages (Twisted, Wx, Qt) that use other
240 conventions. At some level this makes it impossible to adhere to our own
279 conventions. At some level this makes it impossible to adhere to our own
241 standards at all times. In particular, when subclassing classes that use other
280 standards at all times. In particular, when subclassing classes that use other
242 naming conventions, you must follow their naming conventions. To deal with
281 naming conventions, you must follow their naming conventions. To deal with
243 cases like this, we propose the following policy:
282 cases like this, we propose the following policy:
244
283
245 * If you are subclassing a class that uses different conventions, use its
284 * If you are subclassing a class that uses different conventions, use its
246 naming conventions throughout your subclass. Thus, if you are creating a
285 naming conventions throughout your subclass. Thus, if you are creating a
247 Twisted Protocol class, used Twisted's
286 Twisted Protocol class, used Twisted's
248 ``namingSchemeForMethodsAndAttributes.``
287 ``namingSchemeForMethodsAndAttributes.``
249
288
250 * All IPython's official interfaces should use our conventions. In some cases
289 * All IPython's official interfaces should use our conventions. In some cases
251 this will mean that you need to provide shadow names (first implement
290 this will mean that you need to provide shadow names (first implement
252 ``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all
291 ``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all
253 costs, but it will probably be necessary at times. But, please use this
292 costs, but it will probably be necessary at times. But, please use this
254 sparingly!
293 sparingly!
255
294
256 Implementation-specific *private* methods will use
295 Implementation-specific *private* methods will use
257 ``_single_underscore_prefix``. Names with a leading double underscore will
296 ``_single_underscore_prefix``. Names with a leading double underscore will
258 *only* be used in special cases, as they makes subclassing difficult (such
297 *only* be used in special cases, as they makes subclassing difficult (such
259 names are not easily seen by child classes).
298 names are not easily seen by child classes).
260
299
261 Occasionally some run-in lowercase names are used, but mostly for very short
300 Occasionally some run-in lowercase names are used, but mostly for very short
262 names or where we are implementing methods very similar to existing ones in a
301 names or where we are implementing methods very similar to existing ones in a
263 base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had
302 base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had
264 established precedent).
303 established precedent).
265
304
266 The old IPython codebase has a big mix of classes and modules prefixed with an
305 The old IPython codebase has a big mix of classes and modules prefixed with an
267 explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned
306 explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned
268 upon, as namespaces offer cleaner prefixing. The only case where this approach
307 upon, as namespaces offer cleaner prefixing. The only case where this approach
269 is justified is for classes which are expected to be imported into external
308 is justified is for classes which are expected to be imported into external
270 namespaces and a very generic name (like Shell) is too likely to clash with
309 namespaces and a very generic name (like Shell) is too likely to clash with
271 something else. We'll need to revisit this issue as we clean up and refactor
310 something else. We'll need to revisit this issue as we clean up and refactor
272 the code, but in general we should remove as many unnecessary ``IP``/``ip``
311 the code, but in general we should remove as many unnecessary ``IP``/``ip``
273 prefixes as possible. However, if a prefix seems absolutely necessary the more
312 prefixes as possible. However, if a prefix seems absolutely necessary the more
274 specific ``IPY`` or ``ipy`` are preferred.
313 specific ``IPY`` or ``ipy`` are preferred.
275
314
276 .. _devel_testing:
315 .. _devel_testing:
277
316
278 Testing system
317 Testing system
279 ==============
318 ==============
280
319
281 It is extremely important that all code contributed to IPython has tests.
320 It is extremely important that all code contributed to IPython has tests.
282 Tests should be written as unittests, doctests or as entities that the Nose
321 Tests should be written as unittests, doctests or as entities that the Nose
283 [Nose]_ testing package will find. Regardless of how the tests are written, we
322 [Nose]_ testing package will find. Regardless of how the tests are written, we
284 will use Nose for discovering and running the tests. Nose will be required to
323 will use Nose for discovering and running the tests. Nose will be required to
285 run the IPython test suite, but will not be required to simply use IPython.
324 run the IPython test suite, but will not be required to simply use IPython.
286
325
287 Tests of Twisted using code need to follow two additional guidelines:
326 Tests of Twisted using code need to follow two additional guidelines:
288
327
289 1. Twisted using tests should be written by subclassing the :class:`TestCase`
328 1. Twisted using tests should be written by subclassing the :class:`TestCase`
290 class that comes with :mod:`twisted.trial.unittest`.
329 class that comes with :mod:`twisted.trial.unittest`.
291
330
292 2. All :class:`Deferred` instances that are created in the test must be
331 2. All :class:`Deferred` instances that are created in the test must be
293 properly chained and the final one *must* be the return value of the test
332 properly chained and the final one *must* be the return value of the test
294 method.
333 method.
295
334
296 When these two things are done, Nose will be able to run the tests and the
335 When these two things are done, Nose will be able to run the tests and the
297 twisted reactor will be handled correctly.
336 twisted reactor will be handled correctly.
298
337
299 Each subpackage in IPython should have its own :file:`tests` directory that
338 Each subpackage in IPython should have its own :file:`tests` directory that
300 contains all of the tests for that subpackage. This allows each subpackage to
339 contains all of the tests for that subpackage. This allows each subpackage to
301 be self-contained. A good convention to follow is to have a file named
340 be self-contained. A good convention to follow is to have a file named
302 :file:`test_foo.py` for each module :file:`foo.py` in the package. This makes
341 :file:`test_foo.py` for each module :file:`foo.py` in the package. This makes
303 it easy to organize the tests, though like most conventions, it's OK to break
342 it easy to organize the tests, though like most conventions, it's OK to break
304 it if logic and common sense dictate otherwise.
343 it if logic and common sense dictate otherwise.
305
344
306 If a subpackage has any dependencies beyond the Python standard library, the
345 If a subpackage has any dependencies beyond the Python standard library, the
307 tests for that subpackage should be skipped if the dependencies are not
346 tests for that subpackage should be skipped if the dependencies are not
308 found. This is very important so users don't get tests failing simply because
347 found. This is very important so users don't get tests failing simply because
309 they don't have dependencies. We ship a set of decorators in the
348 they don't have dependencies. We ship a set of decorators in the
310 :mod:`IPython.testing` package to tag tests that may be platform-specific or
349 :mod:`IPython.testing` package to tag tests that may be platform-specific or
311 otherwise may have restrictions; if the existing ones don't fit your needs, add
350 otherwise may have restrictions; if the existing ones don't fit your needs, add
312 a new decorator in that location so other tests can reuse it.
351 a new decorator in that location so other tests can reuse it.
313
352
314 To run the IPython test suite, use the :command:`iptest` command that is
353 To run the IPython test suite, use the :command:`iptest` command that is
315 installed with IPython (if you are using IPython in-place, without installing
354 installed with IPython (if you are using IPython in-place, without installing
316 it, you can find this script in the :file:`scripts` directory)::
355 it, you can find this script in the :file:`scripts` directory)::
317
356
318 $ iptest
357 $ iptest
319
358
320 This command runs Nose with the proper options and extensions. By default,
359 This command colects all IPython tests into separate groups, and then calls
321 :command:`iptest` runs the entire IPython test suite (skipping tests that may
360 either Nose with the proper options and extensions, or Twisted's
322 be platform-specific or which depend on tools you may not have). But you can
361 :command:`trial`. This ensures that tests that need the Twisted reactor
323 also use it to run only one specific test file, or a specific test function.
362 management facilities execute separate of Nose. If any individual test group
324 For example, this will run only the :file:`test_magic` file from the test
363 fails, :command:`iptest` will print what you need to type so you can rerun that
325 suite::
364 particular test group alone for debugging.
365
366 By default, :command:`iptest` runs the entire IPython test
367 suite (skipping tests that may be platform-specific or which depend on tools
368 you may not have). But you can also use it to run only one specific test file,
369 or a specific test function. For example, this will run only the
370 :file:`test_magic` file from the test suite::
326
371
327 $ iptest IPython.tests.test_magic
372 $ iptest IPython.tests.test_magic
328 ----------------------------------------------------------------------
373 ----------------------------------------------------------------------
329 Ran 10 tests in 0.348s
374 Ran 10 tests in 0.348s
330
375
331 OK (SKIP=3)
376 OK (SKIP=3)
332 Deleting object: second_pass
377 Deleting object: second_pass
333
378
334 while the ``path:function`` syntax allows you to select a specific function in
379 while the ``path:function`` syntax allows you to select a specific function in
335 that file to run::
380 that file to run::
336
381
337 $ iptest IPython.tests.test_magic:test_obj_del
382 $ iptest IPython.tests.test_magic:test_obj_del
338 ----------------------------------------------------------------------
383 ----------------------------------------------------------------------
339 Ran 1 test in 0.204s
384 Ran 1 test in 0.204s
340
385
341 OK
386 OK
342
387
343 Since :command:`iptest` is based on nosetests, you can pass it any regular
388 Since :command:`iptest` is based on nosetests, you can pass it any regular
344 nosetests option. For example, you can use ``--pdb`` or ``--pdb-failures`` to
389 nosetests option. For example, you can use ``--pdb`` or ``--pdb-failures`` to
345 automatically activate the interactive Pdb debugger on errors or failures. See
390 automatically activate the interactive Pdb debugger on errors or failures. See
346 the nosetests documentation for further details.
391 the nosetests documentation for further details.
347
392
348 .. warning::
349
350 Note that right now we have a nasty interaction between ipdoctest and
351 twisted. Until we figure this out, please use the following instructions to
352 ensure that at least you run all the tests.
353
354 Right now, if you now run::
355
356 $ iptest [any options] [any submodules]
357
358 it will NOT load ipdoctest but won't cause any Twisted problems.
359
360 Once you're happy that you didn't break Twisted, run::
361
362 $ iptest --with-ipdoctest [any options] [any submodules]
363
364 This MAY give a Twisted AlreadyCalledError exception at the end, but it will
365 also correctly load up all of the ipython-specific tests and doctests.
366
367 The above can be made easier with a trivial shell alias::
368
369 $ alias iptest2='iptest --with-ipdoctest'
370
371 So that you can run::
372
373 $ iptest ...
374 # Twisted happy
375 # iptest2 ...
376 # ignore possible Twisted error, this checks all the rest.
377
378
393
379 A few tips for writing tests
394 A few tips for writing tests
380 ----------------------------
395 ----------------------------
381
396
382 You can write tests either as normal test files, using all the conventions that
397 You can write tests either as normal test files, using all the conventions that
383 Nose recognizes, or as doctests. Note that *all* IPython functions should have
398 Nose recognizes, or as doctests. Note that *all* IPython functions should have
384 at least one example that serves as a doctest, whenever technically feasible.
399 at least one example that serves as a doctest, whenever technically feasible.
385 However, example doctests should only be in the main docstring if they are *a
400 However, example doctests should only be in the main docstring if they are *a
386 good example*, i.e. if they convey useful information about the function. If
401 good example*, i.e. if they convey useful information about the function. If
387 you simply would like to write a test as a doctest, put it in a separate test
402 you simply would like to write a test as a doctest, put it in a separate test
388 file and write a no-op function whose only purpose is its docstring.
403 file and write a no-op function whose only purpose is its docstring.
389
404
390 Note, however, that in a file named :file:`test_X`, functions whose only test
405 Note, however, that in a file named :file:`test_X`, functions whose only test
391 is their docstring (as a doctest) and which have no test functionality of their
406 is their docstring (as a doctest) and which have no test functionality of their
392 own, should be called *doctest_foo* instead of *test_foo*, otherwise they get
407 own, should be called *doctest_foo* instead of *test_foo*, otherwise they get
393 double-counted (the empty function call is counted as a test, which just
408 double-counted (the empty function call is counted as a test, which just
394 inflates tests numbers artificially). This restriction does not apply to
409 inflates tests numbers artificially). This restriction does not apply to
395 functions in files with other names, due to how Nose discovers tests.
410 functions in files with other names, due to how Nose discovers tests.
396
411
397 You can use IPython examples in your docstrings. Those can make full use of
412 You can use IPython examples in your docstrings. Those can make full use of
398 IPython functionality (magics, variable substitution, etc), but be careful to
413 IPython functionality (magics, variable substitution, etc), but be careful to
399 keep them generic enough that they run identically on all Operating Systems.
414 keep them generic enough that they run identically on all Operating Systems.
400
415
401 The prompts in your doctests can be either of the plain Python ``>>>`` variety
416 The prompts in your doctests can be either of the plain Python ``>>>`` variety
402 or ``In [1]:`` IPython style. Since this is the IPython system, after all, we
417 or ``In [1]:`` IPython style. Since this is the IPython system, after all, we
403 encourage you to use IPython prompts throughout, unless you are illustrating a
418 encourage you to use IPython prompts throughout, unless you are illustrating a
404 specific aspect of the normal prompts (such as the ``%doctest_mode`` magic).
419 specific aspect of the normal prompts (such as the ``%doctest_mode`` magic).
405
420
406 If a test isn't safe to run inside the main nose process (e.g. because it loads
421 If a test isn't safe to run inside the main nose process (e.g. because it loads
407 a GUI toolkit), consider running it in a subprocess and capturing its output
422 a GUI toolkit), consider running it in a subprocess and capturing its output
408 for evaluation and test decision later. Here is an example of how to do it, by
423 for evaluation and test decision later. Here is an example of how to do it, by
409 relying on the builtin ``_ip`` object that contains the public IPython api as
424 relying on the builtin ``_ip`` object that contains the public IPython api as
410 defined in :mod:`IPython.ipapi`::
425 defined in :mod:`IPython.ipapi`::
411
426
412 def test_obj_del():
427 def test_obj_del():
413 """Test that object's __del__ methods are called on exit."""
428 """Test that object's __del__ methods are called on exit."""
414 test_dir = os.path.dirname(__file__)
429 test_dir = os.path.dirname(__file__)
415 del_file = os.path.join(test_dir,'obj_del.py')
430 del_file = os.path.join(test_dir,'obj_del.py')
416 out = _ip.IP.getoutput('ipython %s' % del_file)
431 out = _ip.IP.getoutput('ipython %s' % del_file)
417 nt.assert_equals(out,'object A deleted')
432 nt.assert_equals(out,'object A deleted')
418
433
419
434
420
435
421 If a doctest contains input whose output you don't want to verify identically
436 If a doctest contains input whose output you don't want to verify identically
422 via doctest (random output, an object id, etc), you can mark a docstring with
437 via doctest (random output, an object id, etc), you can mark a docstring with
423 ``#random``. All of these test will have their code executed but no output
438 ``#random``. All of these test will have their code executed but no output
424 checking will be done::
439 checking will be done::
425
440
426 >>> 1+3
441 >>> 1+3
427 junk goes here... # random
442 junk goes here... # random
428
443
429 >>> 1+2
444 >>> 1+2
430 again, anything goes #random
445 again, anything goes #random
431 if multiline, the random mark is only needed once.
446 if multiline, the random mark is only needed once.
432
447
433 >>> 1+2
448 >>> 1+2
434 You can also put the random marker at the end:
449 You can also put the random marker at the end:
435 # random
450 # random
436
451
437 >>> 1+2
452 >>> 1+2
438 # random
453 # random
439 .. or at the beginning.
454 .. or at the beginning.
440
455
441 In a case where you want an *entire* docstring to be executed but not verified
456 In a case where you want an *entire* docstring to be executed but not verified
442 (this only serves to check that the code runs without crashing, so it should be
457 (this only serves to check that the code runs without crashing, so it should be
443 used very sparingly), you can put ``# all-random`` in the docstring.
458 used very sparingly), you can put ``# all-random`` in the docstring.
444
459
445 .. _devel_config:
460 .. _devel_config:
446
461
447 Release checklist
462 Release checklist
448 =================
463 =================
449
464
450 Most of the release process is automated by the :file:`release` script in the
465 Most of the release process is automated by the :file:`release` script in the
451 :file:`tools` directory. This is just a handy reminder for the release manager.
466 :file:`tools` directory. This is just a handy reminder for the release manager.
452
467
468 #. First, run :file:`build_release`, which does all the file checking and
469 building that the real release script will do. This will let you do test
470 installations, check that the build procedure runs OK, etc. You may want to
471 disable a few things like multi-version RPM building while testing, because
472 otherwise the build takes really long.
473
453 #. Run the release script, which makes the tar.gz, eggs and Win32 .exe
474 #. Run the release script, which makes the tar.gz, eggs and Win32 .exe
454 installer. It posts them to the site and registers the release with PyPI.
475 installer. It posts them to the site and registers the release with PyPI.
455
476
456 #. Updating the website with announcements and links to the updated
477 #. Updating the website with announcements and links to the updated
457 changes.txt in html form. Remember to put a short note both on the news
478 changes.txt in html form. Remember to put a short note both on the news
458 page of the site and on Launcphad.
479 page of the site and on Launcphad.
459
480
460 #. Drafting a short release announcement with i) highlights and ii) a link to
481 #. Drafting a short release announcement with i) highlights and ii) a link to
461 the html changes.txt.
482 the html changes.txt.
462
483
463 #. Make sure that the released version of the docs is live on the site.
484 #. Make sure that the released version of the docs is live on the site.
464
485
465 #. Celebrate!
486 #. Celebrate!
466
487
467 Porting to 3.0
488 Porting to 3.0
468 ==============
489 ==============
469
490
470 There are no definite plans for porting of IPython to python 3. The major
491 There are no definite plans for porting of IPython to python 3. The major
471 issue is the dependency on twisted framework for the networking/threading
492 issue is the dependency on twisted framework for the networking/threading
472 stuff. It is possible that it the traditional IPython interactive console
493 stuff. It is possible that it the traditional IPython interactive console
473 could be ported more easily since it has no such dependency. Here are a few
494 could be ported more easily since it has no such dependency. Here are a few
474 things that will need to be considered when doing such a port especially
495 things that will need to be considered when doing such a port especially
475 if we want to have a codebase that works directly on both 2.x and 3.x.
496 if we want to have a codebase that works directly on both 2.x and 3.x.
476
497
477 1. The syntax for exceptions changed (PEP 3110). The old
498 1. The syntax for exceptions changed (PEP 3110). The old
478 `except exc, var` changed to `except exc as var`. At last
499 `except exc, var` changed to `except exc as var`. At last
479 count there was 78 occurences of this usage in the codebase. This
500 count there was 78 occurences of this usage in the codebase. This
480 is a particularly problematic issue, because it's not easy to
501 is a particularly problematic issue, because it's not easy to
481 implement it in a 2.5-compatible way.
502 implement it in a 2.5-compatible way.
482
503
483 Because it is quite difficult to support simultaneously Python 2.5 and 3.x, we
504 Because it is quite difficult to support simultaneously Python 2.5 and 3.x, we
484 will likely at some point put out a release that requires strictly 2.6 and
505 will likely at some point put out a release that requires strictly 2.6 and
485 abandons 2.5 compatibility. This will then allow us to port the code to using
506 abandons 2.5 compatibility. This will then allow us to port the code to using
486 :func:`print` as a function, `except exc as var` syntax, etc. But as of
507 :func:`print` as a function, `except exc as var` syntax, etc. But as of
487 version 0.11 at least, we will retain Python 2.5 compatibility.
508 version 0.11 at least, we will retain Python 2.5 compatibility.
488
509
489
510
490 .. [Bazaar] Bazaar. http://bazaar-vcs.org/
511 .. [Bazaar] Bazaar. http://bazaar-vcs.org/
491 .. [Launchpad] Launchpad. http://www.launchpad.net/ipython
512 .. [Launchpad] Launchpad. http://www.launchpad.net/ipython
492 .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html
513 .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html
493 .. [Sphinx] Sphinx. http://sphinx.pocoo.org/
514 .. [Sphinx] Sphinx. http://sphinx.pocoo.org/
494 .. [Nose] Nose: a discovery based unittest extension. http://code.google.com/p/python-nose/
515 .. [Nose] Nose: a discovery based unittest extension. http://code.google.com/p/python-nose/
General Comments 0
You need to be logged in to leave comments. Login now