merge heads

This commit is contained in:
Benjamin Peterson 2013-04-07 09:53:49 -04:00
commit 5a3c6dbe6a
14 changed files with 239 additions and 443 deletions

View file

@ -137,40 +137,136 @@ ArgumentParser objects
argument_default=None, conflict_handler='error', \
add_help=True)
Create a new :class:`ArgumentParser` object. Each parameter has its own more
detailed description below, but in short they are:
Create a new :class:`ArgumentParser` object. All parameters should be passed
as keyword arguments. Each parameter has its own more detailed description
below, but in short they are:
* description_ - Text to display before the argument help.
* prog_ - The name of the program (default: ``sys.argv[0]``)
* epilog_ - Text to display after the argument help.
* usage_ - The string describing the program usage (default: generated from
arguments added to parser)
* add_help_ - Add a -h/--help option to the parser. (default: ``True``)
* description_ - Text to display before the argument help (default: none)
* argument_default_ - Set the global default value for arguments.
(default: ``None``)
* epilog_ - Text to display after the argument help (default: none)
* parents_ - A list of :class:`ArgumentParser` objects whose arguments should
also be included.
also be included
* prefix_chars_ - The set of characters that prefix optional arguments.
* formatter_class_ - A class for customizing the help output
* prefix_chars_ - The set of characters that prefix optional arguments
(default: '-')
* fromfile_prefix_chars_ - The set of characters that prefix files from
which additional arguments should be read. (default: ``None``)
which additional arguments should be read (default: ``None``)
* formatter_class_ - A class for customizing the help output.
* argument_default_ - The global default value for arguments
(default: ``None``)
* conflict_handler_ - Usually unnecessary, defines strategy for resolving
conflicting optionals.
* conflict_handler_ - The strategy for resolving conflicting optionals
(usually unnecessary)
* prog_ - The name of the program (default:
``sys.argv[0]``)
* usage_ - The string describing the program usage (default: generated)
* add_help_ - Add a -h/--help option to the parser (default: ``True``)
The following sections describe how each of these are used.
prog
^^^^
By default, :class:`ArgumentParser` objects uses ``sys.argv[0]`` to determine
how to display the name of the program in help messages. This default is almost
always desirable because it will make the help messages match how the program was
invoked on the command line. For example, consider a file named
``myprogram.py`` with the following code::
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help')
args = parser.parse_args()
The help for this program will display ``myprogram.py`` as the program name
(regardless of where the program was invoked from)::
$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
$ cd ..
$ python subdir\myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
To change this default behavior, another value can be supplied using the
``prog=`` argument to :class:`ArgumentParser`::
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.print_help()
usage: myprogram [-h]
optional arguments:
-h, --help show this help message and exit
Note that the program name, whether determined from ``sys.argv[0]`` or from the
``prog=`` argument, is available to help messages using the ``%(prog)s`` format
specifier.
::
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.add_argument('--foo', help='foo of the %(prog)s program')
>>> parser.print_help()
usage: myprogram [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo of the myprogram program
usage
^^^^^
By default, :class:`ArgumentParser` calculates the usage message from the
arguments it contains::
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [-h] [--foo [FOO]] bar [bar ...]
positional arguments:
bar bar help
optional arguments:
-h, --help show this help message and exit
--foo [FOO] foo help
The default message can be overridden with the ``usage=`` keyword argument::
>>> parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [options]
positional arguments:
bar bar help
optional arguments:
-h, --help show this help message and exit
--foo [FOO] foo help
The ``%(prog)s`` format specifier is available to fill in the program name in
your usage messages.
description
^^^^^^^^^^^
@ -218,122 +314,6 @@ line-wrapped, but this behavior can be adjusted with the formatter_class_
argument to :class:`ArgumentParser`.
add_help
^^^^^^^^
By default, ArgumentParser objects add an option which simply displays
the parser's help message. For example, consider a file named
``myprogram.py`` containing the following code::
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help')
args = parser.parse_args()
If ``-h`` or ``--help`` is supplied at the command line, the ArgumentParser
help will be printed::
$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
Occasionally, it may be useful to disable the addition of this help option.
This can be achieved by passing ``False`` as the ``add_help=`` argument to
:class:`ArgumentParser`::
>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
>>> parser.add_argument('--foo', help='foo help')
>>> parser.print_help()
usage: PROG [--foo FOO]
optional arguments:
--foo FOO foo help
The help option is typically ``-h/--help``. The exception to this is
if the ``prefix_chars=`` is specified and does not include ``-``, in
which case ``-h`` and ``--help`` are not valid options. In
this case, the first character in ``prefix_chars`` is used to prefix
the help options::
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/')
>>> parser.print_help()
usage: PROG [+h]
optional arguments:
+h, ++help show this help message and exit
prefix_chars
^^^^^^^^^^^^
Most command-line options will use ``-`` as the prefix, e.g. ``-f/--foo``.
Parsers that need to support different or additional prefix
characters, e.g. for options
like ``+f`` or ``/foo``, may specify them using the ``prefix_chars=`` argument
to the ArgumentParser constructor::
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
>>> parser.add_argument('++bar')
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')
The ``prefix_chars=`` argument defaults to ``'-'``. Supplying a set of
characters that does not include ``-`` will cause ``-f/--foo`` options to be
disallowed.
fromfile_prefix_chars
^^^^^^^^^^^^^^^^^^^^^
Sometimes, for example when dealing with a particularly long argument lists, it
may make sense to keep the list of arguments in a file rather than typing it out
at the command line. If the ``fromfile_prefix_chars=`` argument is given to the
:class:`ArgumentParser` constructor, then arguments that start with any of the
specified characters will be treated as files, and will be replaced by the
arguments they contain. For example::
>>> with open('args.txt', 'w') as fp:
... fp.write('-f\nbar')
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(f='bar')
Arguments read from a file must by default be one per line (but see also
:meth:`~ArgumentParser.convert_arg_line_to_args`) and are treated as if they
were in the same place as the original file referencing argument on the command
line. So in the example above, the expression ``['-f', 'foo', '@args.txt']``
is considered equivalent to the expression ``['-f', 'foo', '-f', 'bar']``.
The ``fromfile_prefix_chars=`` argument defaults to ``None``, meaning that
arguments will never be treated as file references.
argument_default
^^^^^^^^^^^^^^^^
Generally, argument defaults are specified either by passing a default to
:meth:`~ArgumentParser.add_argument` or by calling the
:meth:`~ArgumentParser.set_defaults` methods with a specific set of name-value
pairs. Sometimes however, it may be useful to specify a single parser-wide
default for arguments. This can be accomplished by passing the
``argument_default=`` keyword argument to :class:`ArgumentParser`. For example,
to globally suppress attribute creation on :meth:`~ArgumentParser.parse_args`
calls, we supply ``argument_default=SUPPRESS``::
>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar', nargs='?')
>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args([])
Namespace()
parents
^^^^^^^
@ -471,6 +451,74 @@ as the regular formatter does)::
--foo int
prefix_chars
^^^^^^^^^^^^
Most command-line options will use ``-`` as the prefix, e.g. ``-f/--foo``.
Parsers that need to support different or additional prefix
characters, e.g. for options
like ``+f`` or ``/foo``, may specify them using the ``prefix_chars=`` argument
to the ArgumentParser constructor::
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
>>> parser.add_argument('++bar')
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')
The ``prefix_chars=`` argument defaults to ``'-'``. Supplying a set of
characters that does not include ``-`` will cause ``-f/--foo`` options to be
disallowed.
fromfile_prefix_chars
^^^^^^^^^^^^^^^^^^^^^
Sometimes, for example when dealing with a particularly long argument lists, it
may make sense to keep the list of arguments in a file rather than typing it out
at the command line. If the ``fromfile_prefix_chars=`` argument is given to the
:class:`ArgumentParser` constructor, then arguments that start with any of the
specified characters will be treated as files, and will be replaced by the
arguments they contain. For example::
>>> with open('args.txt', 'w') as fp:
... fp.write('-f\nbar')
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(f='bar')
Arguments read from a file must by default be one per line (but see also
:meth:`~ArgumentParser.convert_arg_line_to_args`) and are treated as if they
were in the same place as the original file referencing argument on the command
line. So in the example above, the expression ``['-f', 'foo', '@args.txt']``
is considered equivalent to the expression ``['-f', 'foo', '-f', 'bar']``.
The ``fromfile_prefix_chars=`` argument defaults to ``None``, meaning that
arguments will never be treated as file references.
argument_default
^^^^^^^^^^^^^^^^
Generally, argument defaults are specified either by passing a default to
:meth:`~ArgumentParser.add_argument` or by calling the
:meth:`~ArgumentParser.set_defaults` methods with a specific set of name-value
pairs. Sometimes however, it may be useful to specify a single parser-wide
default for arguments. This can be accomplished by passing the
``argument_default=`` keyword argument to :class:`ArgumentParser`. For example,
to globally suppress attribute creation on :meth:`~ArgumentParser.parse_args`
calls, we supply ``argument_default=SUPPRESS``::
>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar', nargs='?')
>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args([])
Namespace()
conflict_handler
^^^^^^^^^^^^^^^^
@ -508,22 +556,20 @@ action is retained as the ``-f`` action, because only the ``--foo`` option
string was overridden.
prog
^^^^
add_help
^^^^^^^^
By default, :class:`ArgumentParser` objects uses ``sys.argv[0]`` to determine
how to display the name of the program in help messages. This default is almost
always desirable because it will make the help messages match how the program was
invoked on the command line. For example, consider a file named
``myprogram.py`` with the following code::
By default, ArgumentParser objects add an option which simply displays
the parser's help message. For example, consider a file named
``myprogram.py`` containing the following code::
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help')
args = parser.parse_args()
The help for this program will display ``myprogram.py`` as the program name
(regardless of where the program was invoked from)::
If ``-h`` or ``--help`` is supplied at the command line, the ArgumentParser
help will be printed::
$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]
@ -531,76 +577,31 @@ The help for this program will display ``myprogram.py`` as the program name
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
$ cd ..
$ python subdir\myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
Occasionally, it may be useful to disable the addition of this help option.
This can be achieved by passing ``False`` as the ``add_help=`` argument to
:class:`ArgumentParser`::
To change this default behavior, another value can be supplied using the
``prog=`` argument to :class:`ArgumentParser`::
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
>>> parser.add_argument('--foo', help='foo help')
>>> parser.print_help()
usage: myprogram [-h]
usage: PROG [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
Note that the program name, whether determined from ``sys.argv[0]`` or from the
``prog=`` argument, is available to help messages using the ``%(prog)s`` format
specifier.
The help option is typically ``-h/--help``. The exception to this is
if the ``prefix_chars=`` is specified and does not include ``-``, in
which case ``-h`` and ``--help`` are not valid options. In
this case, the first character in ``prefix_chars`` is used to prefix
the help options::
::
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.add_argument('--foo', help='foo of the %(prog)s program')
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/')
>>> parser.print_help()
usage: myprogram [-h] [--foo FOO]
usage: PROG [-h]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo of the myprogram program
usage
^^^^^
By default, :class:`ArgumentParser` calculates the usage message from the
arguments it contains::
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [-h] [--foo [FOO]] bar [bar ...]
positional arguments:
bar bar help
optional arguments:
-h, --help show this help message and exit
--foo [FOO] foo help
The default message can be overridden with the ``usage=`` keyword argument::
>>> parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [options]
positional arguments:
bar bar help
optional arguments:
-h, --help show this help message and exit
--foo [FOO] foo help
The ``%(prog)s`` format specifier is available to fill in the program name in
your usage messages.
-h, --help show this help message and exit
The add_argument() method

View file

@ -79,7 +79,7 @@ The :mod:`functools` module defines the following functions:
Example of an LRU cache for static web content::
@lru_cache(maxsize=20)
@lru_cache(maxsize=32)
def get_pep(num):
'Retrieve text of a Python Enhancement Proposal'
resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
@ -93,8 +93,8 @@ The :mod:`functools` module defines the following functions:
... pep = get_pep(n)
... print(n, len(pep))
>>> print(get_pep.cache_info())
CacheInfo(hits=3, misses=8, maxsize=20, currsize=8)
>>> get_pep.cache_info()
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
Example of efficiently computing
`Fibonacci numbers <http://en.wikipedia.org/wiki/Fibonacci_number>`_
@ -108,10 +108,10 @@ The :mod:`functools` module defines the following functions:
return n
return fib(n-1) + fib(n-2)
>>> print([fib(n) for n in range(16)])
>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
>>> print(fib.cache_info())
>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)
.. versionadded:: 3.2

View file

@ -1433,6 +1433,7 @@ class EditorWindow(object):
def tabify_region_event(self, event):
head, tail, chars, lines = self.get_region()
tabwidth = self._asktabwidth()
if tabwidth is None: return
for pos in range(len(lines)):
line = lines[pos]
if line:
@ -1444,6 +1445,7 @@ class EditorWindow(object):
def untabify_region_event(self, event):
head, tail, chars, lines = self.get_region()
tabwidth = self._asktabwidth()
if tabwidth is None: return
for pos in range(len(lines)):
lines[pos] = lines[pos].expandtabs(tabwidth)
self.set_region(head, tail, chars, lines)
@ -1537,7 +1539,7 @@ class EditorWindow(object):
parent=self.text,
initialvalue=self.indentwidth,
minvalue=2,
maxvalue=16) or self.tabwidth
maxvalue=16)
# Guess indentwidth from text content.
# Return guessed indentwidth. This should not be believed unless

View file

@ -1564,40 +1564,8 @@ class TestSorted(unittest.TestCase):
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0)
class TestRecursionLimit(unittest.TestCase):
# Issue #14010
recursionlimit = sys.getrecursionlimit()
def test_filter(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = filter(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_map(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = map(int, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_zip(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = zip(it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_main(verbose=None):
test_classes = (BuiltinTest, TestSorted, TestRecursionLimit)
test_classes = (BuiltinTest, TestSorted)
run_unittest(*test_classes)

View file

@ -1808,121 +1808,6 @@ class SubclassWithKwargsTest(unittest.TestCase):
self.assertNotIn("does not take keyword arguments", err.args[0])
class TestRecursionLimit(unittest.TestCase):
# Issue #14010
recursionlimit = sys.getrecursionlimit()
def test_accumulate(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = accumulate(it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_chain(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = chain(it, ())
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_compress(self):
data = (0, 1)
selectors = (True, True)
it = data
for _ in range(self.recursionlimit):
it = compress(it, selectors)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
it = selectors
for _ in range(self.recursionlimit):
it = compress(data, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_cycle(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = cycle(it)
with self.assertRaises(RuntimeError):
for _ in range(3):
next(it)
del it
def test_dropwhile(self):
it = (0, 1, 0)
for _ in range(self.recursionlimit):
it = dropwhile(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_filterfalse(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = filterfalse(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_groupby(self):
key = operator.itemgetter(0)
it = ((0, []), (1, []))
for _ in range(self.recursionlimit):
it = groupby(it, key)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_islice(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = islice(it, 2)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_starmap(self):
it = 'ab'
for _ in range(self.recursionlimit):
it = starmap(tuple, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_takewhile(self):
it = (1, 0)
for _ in range(self.recursionlimit):
it = takewhile(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_zip_longest(self):
it = (0, 1)
for _ in range(self.recursionlimit):
it = zip_longest(it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
libreftest = """ Doctest for examples in the library reference: libitertools.tex
@ -2157,7 +2042,7 @@ __test__ = {'libreftest' : libreftest}
def test_main(verbose=None):
test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,
RegressionTests, LengthTransparency,
SubclassWithKwargsTest, TestExamples, TestRecursionLimit)
SubclassWithKwargsTest, TestExamples)
support.run_unittest(*test_classes)
# verify reference counting

View file

@ -931,6 +931,8 @@ class CallableMixin(Base):
result = next(effect)
if _is_exception(result):
raise result
if result is DEFAULT:
result = self.return_value
return result
ret_val = effect(*args, **kwargs)

View file

@ -978,6 +978,10 @@ class MockTest(unittest.TestCase):
self.assertRaises(StopIteration, mock)
self.assertIs(mock.side_effect, this_iter)
def test_side_effect_iterator_default(self):
mock = Mock(return_value=2)
mock.side_effect = iter([1, DEFAULT])
self.assertEqual([mock(), mock()], [1, 2])
def test_assert_has_calls_any_order(self):
mock = Mock()

View file

@ -846,7 +846,6 @@ def splittype(url):
"""splittype('type:opaquestring') --> 'type', 'opaquestring'."""
global _typeprog
if _typeprog is None:
import re
_typeprog = re.compile('^([^/:]+):')
match = _typeprog.match(url)
@ -860,7 +859,6 @@ def splithost(url):
"""splithost('//host[:port]/path') --> 'host[:port]', '/path'."""
global _hostprog
if _hostprog is None:
import re
_hostprog = re.compile('^//([^/?]*)(.*)$')
match = _hostprog.match(url)
@ -877,7 +875,6 @@ def splituser(host):
"""splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'."""
global _userprog
if _userprog is None:
import re
_userprog = re.compile('^(.*)@(.*)$')
match = _userprog.match(host)
@ -889,7 +886,6 @@ def splitpasswd(user):
"""splitpasswd('user:passwd') -> 'user', 'passwd'."""
global _passwdprog
if _passwdprog is None:
import re
_passwdprog = re.compile('^([^:]*):(.*)$',re.S)
match = _passwdprog.match(user)
@ -902,7 +898,6 @@ def splitport(host):
"""splitport('host:port') --> 'host', 'port'."""
global _portprog
if _portprog is None:
import re
_portprog = re.compile('^(.*):([0-9]+)$')
match = _portprog.match(host)
@ -917,7 +912,6 @@ def splitnport(host, defport=-1):
Return None if ':' but not a valid number."""
global _nportprog
if _nportprog is None:
import re
_nportprog = re.compile('^(.*):(.*)$')
match = _nportprog.match(host)
@ -936,7 +930,6 @@ def splitquery(url):
"""splitquery('/path?query') --> '/path', 'query'."""
global _queryprog
if _queryprog is None:
import re
_queryprog = re.compile('^(.*)\?([^?]*)$')
match = _queryprog.match(url)
@ -948,7 +941,6 @@ def splittag(url):
"""splittag('/path#tag') --> '/path', 'tag'."""
global _tagprog
if _tagprog is None:
import re
_tagprog = re.compile('^(.*)#([^#]*)$')
match = _tagprog.match(url)
@ -966,7 +958,6 @@ def splitvalue(attr):
"""splitvalue('attr=value') --> 'attr', 'value'."""
global _valueprog
if _valueprog is None:
import re
_valueprog = re.compile('^([^=]*)=(.*)$')
match = _valueprog.match(attr)

View file

@ -722,6 +722,7 @@ Luke Kenneth Casson Leighton
Tshepang Lekhonkhobe
Marc-André Lemburg
John Lenton
Kostyantyn Leschenko
Benno Leslie
Christopher Tur Lesniewski-Laas
Alain Leufroy

View file

@ -10,9 +10,6 @@ What's New in Python 3.4.0 Alpha 1?
Core and Builtins
-----------------
- Issue #14010: Fix a crash when iterating or deleting deeply nested filters
(builting and in itertools module, i.e. map(), itertools.chain(), etc).
- Issue #17469: Fix _Py_GetAllocatedBlocks() and sys.getallocatedblocks()
when running on valgrind.
@ -1016,6 +1013,8 @@ _ Issue #17385: Fix quadratic behavior in threading.Condition. The FIFO
IDLE
----
- Issue #16887: IDLE now accepts Cancel in tabify/untabify dialog box.
- Issue #14254: IDLE now handles readline correctly across shell restarts.
- Issue #17614: IDLE no longer raises exception when quickly closing a file.

View file

@ -54,14 +54,12 @@ static void
groupby_dealloc(groupbyobject *gbo)
{
PyObject_GC_UnTrack(gbo);
Py_TRASHCAN_SAFE_BEGIN(gbo)
Py_XDECREF(gbo->it);
Py_XDECREF(gbo->keyfunc);
Py_XDECREF(gbo->tgtkey);
Py_XDECREF(gbo->currkey);
Py_XDECREF(gbo->currvalue);
Py_TYPE(gbo)->tp_free(gbo);
Py_TRASHCAN_SAFE_END(gbo)
}
static int
@ -913,11 +911,9 @@ static void
cycle_dealloc(cycleobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->saved);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -1092,11 +1088,9 @@ static void
dropwhile_dealloc(dropwhileobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -1117,10 +1111,7 @@ dropwhile_next(dropwhileobject *lz)
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL)
return NULL;
if (lz->start == 1)
@ -1266,11 +1257,9 @@ static void
takewhile_dealloc(takewhileobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -1291,10 +1280,7 @@ takewhile_next(takewhileobject *lz)
if (lz->stop == 1)
return NULL;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = (*Py_TYPE(it)->tp_iternext)(it);
Py_LeaveRecursiveCall();
if (item == NULL)
return NULL;
@ -1486,10 +1472,8 @@ static void
islice_dealloc(isliceobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -1510,10 +1494,7 @@ islice_next(isliceobject *lz)
iternext = *Py_TYPE(it)->tp_iternext;
while (lz->cnt < lz->next) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL)
return NULL;
Py_DECREF(item);
@ -1521,10 +1502,7 @@ islice_next(isliceobject *lz)
}
if (stop != -1 && lz->cnt >= stop)
return NULL;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL)
return NULL;
lz->cnt++;
@ -1675,11 +1653,9 @@ static void
starmap_dealloc(starmapobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -1697,10 +1673,7 @@ starmap_next(starmapobject *lz)
PyObject *result;
PyObject *it = lz->it;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
args = (*Py_TYPE(it)->tp_iternext)(it);
Py_LeaveRecursiveCall();
if (args == NULL)
return NULL;
if (!PyTuple_CheckExact(args)) {
@ -1836,11 +1809,9 @@ static void
chain_dealloc(chainobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->active);
Py_XDECREF(lz->source);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -3369,12 +3340,10 @@ static void
accumulate_dealloc(accumulateobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->binop);
Py_XDECREF(lz->total);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -3545,11 +3514,9 @@ static void
compress_dealloc(compressobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->data);
Py_XDECREF(lz->selectors);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -3576,16 +3543,11 @@ compress_next(compressobject *lz)
exception first).
*/
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
datum = datanext(data);
if (datum == NULL) {
Py_LeaveRecursiveCall();
if (datum == NULL)
return NULL;
}
selector = selectornext(selectors);
Py_LeaveRecursiveCall();
if (selector == NULL) {
Py_DECREF(datum);
return NULL;
@ -3712,11 +3674,9 @@ static void
filterfalse_dealloc(filterfalseobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -3737,10 +3697,7 @@ filterfalse_next(filterfalseobject *lz)
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL)
return NULL;
@ -4304,12 +4261,10 @@ static void
zip_longest_dealloc(ziplongestobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->result);
Py_XDECREF(lz->fillvalue);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int

View file

@ -1238,7 +1238,7 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err)
to be an int or have an __int__ method. Steals integral's
reference. error_format will be used to create the TypeError if integral
isn't actually an Integral instance. error_format should be a format string
that can accept a char* naming integral's type.
that can accept a char* naming integral's type.
*/
static PyObject *
convert_integral_to_int(PyObject *integral, const char *error_format)
@ -1257,7 +1257,7 @@ convert_integral_to_int(PyObject *integral, const char *error_format)
}
PyErr_Format(PyExc_TypeError, error_format, Py_TYPE(integral)->tp_name);
Py_DECREF(integral);
return NULL;
return NULL;
}
@ -2702,10 +2702,7 @@ PyObject *
PyIter_Next(PyObject *iter)
{
PyObject *result;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
result = (*iter->ob_type->tp_iternext)(iter);
Py_LeaveRecursiveCall();
if (result == NULL &&
PyErr_Occurred() &&
PyErr_ExceptionMatches(PyExc_StopIteration))

View file

@ -391,11 +391,9 @@ static void
filter_dealloc(filterobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func);
Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -416,10 +414,7 @@ filter_next(filterobject *lz)
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL)
return NULL;
@ -1036,11 +1031,9 @@ static void
map_dealloc(mapobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->iters);
Py_XDECREF(lz->func);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -2227,11 +2220,9 @@ static void
zip_dealloc(zipobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->result);
Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
}
static int
@ -2254,15 +2245,15 @@ zip_next(zipobject *lz)
if (tuplesize == 0)
return NULL;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
if (Py_REFCNT(result) == 1) {
Py_INCREF(result);
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL)
goto error;
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
olditem = PyTuple_GET_ITEM(result, i);
PyTuple_SET_ITEM(result, i, item);
Py_DECREF(olditem);
@ -2270,21 +2261,18 @@ zip_next(zipobject *lz)
} else {
result = PyTuple_New(tuplesize);
if (result == NULL)
goto error;
return NULL;
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL)
goto error;
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, i, item);
}
}
Py_LeaveRecursiveCall();
return result;
error:
Py_XDECREF(result);
Py_LeaveRecursiveCall();
return NULL;
}
static PyObject *

View file

@ -248,8 +248,11 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident)
}
plen -= ipriv;
assert(1 <= PY_SSIZE_T_MAX - nlen);
assert(1 + nlen <= PY_SSIZE_T_MAX - plen);
if (plen + nlen >= PY_SSIZE_T_MAX - 1) {
PyErr_SetString(PyExc_OverflowError,
"private identifier too large to be mangled");
return NULL;
}
maxchar = PyUnicode_MAX_CHAR_VALUE(ident);
if (PyUnicode_MAX_CHAR_VALUE(privateobj) > maxchar)