summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/ACKS.txt1
-rw-r--r--Doc/library/collections.rst2
-rw-r--r--Doc/library/configparser.rst16
-rw-r--r--Doc/library/curses.rst2
-rw-r--r--Doc/library/json.rst18
-rw-r--r--Doc/library/nntplib.rst6
-rw-r--r--Doc/library/optparse.rst11
-rw-r--r--Doc/library/stdtypes.rst8
-rw-r--r--Doc/library/subprocess.rst4
-rw-r--r--Doc/library/textwrap.rst19
-rw-r--r--Doc/library/threading.rst6
-rw-r--r--Doc/library/types.rst2
-rw-r--r--Doc/library/unittest.rst2
-rw-r--r--Doc/whatsnew/3.3.rst35
-rw-r--r--Include/object.h2
-rw-r--r--Include/pyfpe.h8
-rw-r--r--Lib/_pyio.py8
-rw-r--r--Lib/argparse.py26
-rw-r--r--Lib/gzip.py4
-rw-r--r--Lib/test/string_tests.py3
-rw-r--r--Lib/test/test_argparse.py48
-rw-r--r--Lib/test/test_ast.py8
-rw-r--r--Lib/test/test_importlib/test_locks.py22
-rw-r--r--Lib/test/test_mailbox.py10
-rw-r--r--Lib/test/test_memoryio.py7
-rw-r--r--Lib/test/test_super.py15
-rw-r--r--Lib/test/test_textwrap.py64
-rw-r--r--Lib/test/test_webbrowser.py192
-rw-r--r--Lib/webbrowser.py15
-rw-r--r--Makefile.pre.in17
-rw-r--r--Misc/ACKS2
-rw-r--r--Misc/NEWS67
-rw-r--r--Modules/_cursesmodule.c1
-rw-r--r--Modules/_io/bytesio.c24
-rw-r--r--Modules/_io/stringio.c19
-rw-r--r--Modules/_testbuffer.c5
-rw-r--r--Objects/memoryobject.c78
-rw-r--r--Objects/typeobject.c14
-rw-r--r--Objects/unicodeobject.c5
-rw-r--r--Python/ast.c186
-rw-r--r--Python/formatter_unicode.c2
-rw-r--r--setup.py2
42 files changed, 759 insertions, 227 deletions
diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt
index 5636e05..68aff56 100644
--- a/Doc/ACKS.txt
+++ b/Doc/ACKS.txt
@@ -96,6 +96,7 @@ docs@python.org), and we'll be glad to correct the problem.
* Rob Hooft
* Brian Hooper
* Randall Hopper
+ * Mike Hoy
* Michael Hudson
* Eric Huss
* Jeremy Hylton
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index 4c5b649..dc76ea5 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -1012,7 +1012,7 @@ are deleted. But when new keys are added, the keys are appended
to the end and the sort is not maintained.
It is also straight-forward to create an ordered dictionary variant
-that the remembers the order the keys were *last* inserted.
+that remembers the order the keys were *last* inserted.
If a new entry overwrites an existing entry, the
original insertion position is changed and moved to the end::
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst
index afceb8d..6f0ae6a 100644
--- a/Doc/library/configparser.rst
+++ b/Doc/library/configparser.rst
@@ -1007,7 +1007,7 @@ ConfigParser Objects
.. versionadded:: 3.2
- .. method:: get(section, option, raw=False, [vars, fallback])
+ .. method:: get(section, option, *, raw=False, vars=None[, fallback])
Get an *option* value for the named *section*. If *vars* is provided, it
must be a dictionary. The *option* is looked up in *vars* (if provided),
@@ -1025,21 +1025,21 @@ ConfigParser Objects
(especially when using the mapping protocol).
- .. method:: getint(section, option, raw=False, [vars, fallback])
+ .. method:: getint(section, option, *, raw=False, vars=None[, fallback])
A convenience method which coerces the *option* in the specified *section*
to an integer. See :meth:`get` for explanation of *raw*, *vars* and
*fallback*.
- .. method:: getfloat(section, option, raw=False, [vars, fallback])
+ .. method:: getfloat(section, option, *, raw=False, vars=None[, fallback])
A convenience method which coerces the *option* in the specified *section*
to a floating point number. See :meth:`get` for explanation of *raw*,
*vars* and *fallback*.
- .. method:: getboolean(section, option, raw=False, [vars, fallback])
+ .. method:: getboolean(section, option, *, raw=False, vars=None[, fallback])
A convenience method which coerces the *option* in the specified *section*
to a Boolean value. Note that the accepted values for the option are
@@ -1149,7 +1149,13 @@ ConfigParser Objects
RawConfigParser Objects
-----------------------
-.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None)
+.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, \
+ allow_no_value=False, *, delimiters=('=', ':'), \
+ comment_prefixes=('#', ';'), \
+ inline_comment_prefixes=None, strict=True, \
+ empty_lines_in_values=True, \
+ default_section=configparser.DEFAULTSECT[, \
+ interpolation])
Legacy variant of the :class:`ConfigParser` with interpolation disabled
by default and unsafe ``add_section`` and ``set`` methods.
diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index c424148..2d0043c 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -837,7 +837,7 @@ the following methods and attributes:
.. attribute:: window.encoding
Encoding used to encode method arguments (Unicode strings and characters).
- The encoding attribute is inherited from by parent window when a subwindow
+ The encoding attribute is inherited from the parent window when a subwindow
is created, for example with :meth:`window.subwin`. By default, the locale
encoding is used (see :func:`locale.getpreferredencoding`).
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
index 0229ab5..95f120c 100644
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -146,9 +146,12 @@ Basic Usage
object members will be pretty-printed with that indent level. An indent level
of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
selects the most compact representation. Using a positive integer indent
- indents that many spaces per level. If *indent* is a string (such at '\t'),
+ indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
that string is used to indent each level.
+ .. versionchanged:: 3.2
+ Allow strings for *indent* in addition to integers.
+
If *separators* is an ``(item_separator, dict_separator)`` tuple, then it
will be used instead of the default ``(', ', ': ')`` separators. ``(',',
':')`` is the most compact JSON representation.
@@ -371,10 +374,15 @@ Encoders and Decoders
will be sorted by key; this is useful for regression tests to ensure that
JSON serializations can be compared on a day-to-day basis.
- If *indent* is a non-negative integer (it is ``None`` by default), then JSON
- array elements and object members will be pretty-printed with that indent
- level. An indent level of 0 will only insert newlines. ``None`` is the most
- compact representation.
+ If *indent* is a non-negative integer or string, then JSON array elements and
+ object members will be pretty-printed with that indent level. An indent level
+ of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
+ selects the most compact representation. Using a positive integer indent
+ indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
+ that string is used to indent each level.
+
+ .. versionchanged:: 3.2
+ Allow strings for *indent* in addition to integers.
If specified, *separators* should be an ``(item_separator, key_separator)``
tuple. The default is ``(', ', ': ')``. To get the most compact JSON
diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst
index 62da72c..87a50b0 100644
--- a/Doc/library/nntplib.rst
+++ b/Doc/library/nntplib.rst
@@ -487,10 +487,10 @@ The following are optional NNTP extensions defined in :rfc:`2980`. Some of
them have been superseded by newer commands in :rfc:`3977`.
-.. method:: NNTP.xhdr(header, string, *, file=None)
+.. method:: NNTP.xhdr(hdr, str, *, file=None)
- Send an ``XHDR`` command. The *header* argument is a header keyword, e.g.
- ``'subject'``. The *string* argument should have the form ``'first-last'``
+ Send an ``XHDR`` command. The *hdr* argument is a header keyword, e.g.
+ ``'subject'``. The *str* argument should have the form ``'first-last'``
where *first* and *last* are the first and last article numbers to search.
Return a pair ``(response, list)``, where *list* is a list of pairs ``(id,
text)``, where *id* is an article number (as a string) and *text* is the text of
diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst
index add582e..6dc57bb 100644
--- a/Doc/library/optparse.rst
+++ b/Doc/library/optparse.rst
@@ -1165,6 +1165,17 @@ must specify for any option using that action.
options.tracks.append(int("4"))
+ The ``append`` action calls the ``append`` method on the current value of the
+ option. This means that any default value specified must have an ``append``
+ method. It also means that if the default value is non-empty, the default
+ elements will be present in the parsed value for the option, with any values
+ from the command line appended after those default values::
+
+ >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults'])
+ >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg'])
+ >>> opts.files
+ ['~/.mypkg/defaults', 'overrides.mypkg']
+
* ``"append_const"`` [required: :attr:`~Option.const`; relevant:
:attr:`~Option.dest`]
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index 90f3e54..3c038be 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -2687,13 +2687,19 @@ copying.
.. attribute:: shape
A tuple of integers the length of :attr:`ndim` giving the shape of the
- memory as a N-dimensional array.
+ memory as an N-dimensional array.
+
+ .. versionchanged:: 3.3
+ An empty tuple instead of None when ndim = 0.
.. attribute:: strides
A tuple of integers the length of :attr:`ndim` giving the size in bytes to
access each element for each dimension of the array.
+ .. versionchanged:: 3.3
+ An empty tuple instead of None when ndim = 0.
+
.. attribute:: suboffsets
Used internally for PIL-style arrays. The value is informational only.
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
index c0fc4d7..2d5f761 100644
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -669,8 +669,8 @@ The following attributes are also available:
.. warning::
- Use :meth:`communicate` rather than :attr:`.stdin.write <stdin>`,
- :attr:`.stdout.read <stdout>` or :attr:`.stderr.read <stderr>` to avoid
+ Use :meth:`~Popen.communicate` rather than :attr:`.stdin.write <Popen.stdin>`,
+ :attr:`.stdout.read <Popen.stdout>` or :attr:`.stderr.read <Popen.stderr>` to avoid
deadlocks due to any of the other OS pipe buffers filling up and blocking the
child process.
diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst
index 0ac1cc6..c625254 100644
--- a/Doc/library/textwrap.rst
+++ b/Doc/library/textwrap.rst
@@ -25,6 +25,9 @@ otherwise, you should use an instance of :class:`TextWrapper` for efficiency.
Optional keyword arguments correspond to the instance attributes of
:class:`TextWrapper`, documented below. *width* defaults to ``70``.
+ See the :meth:`TextWrapper.wrap` method for additional details on how
+ :func:`wrap` behaves.
+
.. function:: fill(text, width=70, **kwargs)
@@ -167,15 +170,18 @@ in a block of text.
.. attribute:: drop_whitespace
- (default: ``True``) If true, whitespace that, after wrapping, happens to
- end up at the beginning or end of a line is dropped (leading whitespace in
- the first line is always preserved, though).
+ (default: ``True``) If true, whitespace at the beginning and ending of
+ every line (after wrapping but before indenting) is dropped.
+ Whitespace at the beginning of the paragraph, however, is not dropped
+ if non-whitespace follows it. If whitespace being dropped takes up an
+ entire line, the whole line is dropped.
.. attribute:: initial_indent
(default: ``''``) String that will be prepended to the first line of
- wrapped output. Counts towards the length of the first line.
+ wrapped output. Counts towards the length of the first line. The empty
+ string is not indented.
.. attribute:: subsequent_indent
@@ -236,8 +242,9 @@ in a block of text.
Wraps the single paragraph in *text* (a string) so every line is at most
:attr:`width` characters long. All wrapping options are taken from
- instance attributes of the :class:`TextWrapper` instance. Returns a list
- of output lines, without final newlines.
+ instance attributes of the :class:`TextWrapper` instance. Returns a list
+ of output lines, without final newlines. If the wrapped output has no
+ content, the returned list is empty.
.. method:: fill(text)
diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
index 275a578..7ab739b 100644
--- a/Doc/library/threading.rst
+++ b/Doc/library/threading.rst
@@ -255,8 +255,8 @@ daemonic, and cannot be :meth:`~Thread.join`\ ed. They are never deleted,
since it is impossible to detect the termination of alien threads.
-.. class:: Thread(group=None, target=None, name=None, args=(), kwargs={},
- verbose=None, *, daemon=None)
+.. class:: Thread(group=None, target=None, name=None, args=(), kwargs={}, *, \
+ daemon=None)
This constructor should always be called with keyword arguments. Arguments
are:
@@ -275,8 +275,6 @@ since it is impossible to detect the termination of alien threads.
*kwargs* is a dictionary of keyword arguments for the target invocation.
Defaults to ``{}``.
- *verbose* is a flag used for debugging messages.
-
If not ``None``, *daemon* explicitly sets whether the thread is daemonic.
If ``None`` (the default), the daemonic property is inherited from the
current thread.
diff --git a/Doc/library/types.rst b/Doc/library/types.rst
index b60b195..695480f 100644
--- a/Doc/library/types.rst
+++ b/Doc/library/types.rst
@@ -69,7 +69,7 @@ implement a Python interpreter. It deliberately avoids including some of
the types that arise only incidentally during processing such as the
``listiterator`` type.
-Typical use is of these names is for :func:`isinstance` or
+Typical use of these names is for :func:`isinstance` or
:func:`issubclass` checks.
Standard names are defined for the following types:
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index 0af9038..2657ebd 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -1265,7 +1265,7 @@ Test cases
.. method:: assertListEqual(first, second, msg=None)
assertTupleEqual(first, second, msg=None)
- Tests that two lists or tuples are equal. If not an error message is
+ Tests that two lists or tuples are equal. If not, an error message is
constructed that shows only the differences between the two. An error
is also raised if either of the parameters are of the wrong type.
These methods are used by default when comparing lists or tuples with
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index 9e68203..caa838f 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -563,6 +563,41 @@ which considerably simplifies writing decorators and any code that validates
or amends calling signatures or arguments.
+PEP 421: Adding sys.implementation
+==================================
+
+:pep:`421` - Adding sys.implementation
+ PEP written and implemented by Eric Snow.
+
+A new attribute on the :mod:`sys` module exposes details specific to the
+implementation of the currently running interpreter. The initial set of
+attributes on :attr:`sys.implementation` are ``name``, ``version``,
+``hexversion``, and ``cache_tag``.
+
+The intention of ``sys.implementation`` is to consolidate into one namespace
+the implementation-specific data used by the standard library. This allows
+different Python implementations to share a single standard library code base
+much more easily. In its initial state, ``sys.implementation`` holds only a
+small portion of the implementation-specific data. Over time that ratio will
+shift in order to make the standard library more portable.
+
+One example of improved standard library portability is ``cache_tag``. As of
+Python 3.3, ``sys.implementation.cache_tag`` is used by :mod:`importlib` to
+support :pep:`3147` compliance. Any Python implementation that uses
+``importlib`` for its built-in import system may use ``cache_tag`` to control
+the caching behavior for modules.
+
+SimpleNamespace
+---------------
+
+The implementation of ``sys.implementation`` also introduces a new type to
+Python: :class:`types.SimpleNamespace`. In contrast to a mapping-based
+namespace, like :class:`dict`, ``SimpleNamespace`` is attribute-based, like
+:class:`object`. However, unlike ``object``, ``SimpleNamespace`` instances
+are writable. This means that you can add, remove, and modify the namespace
+through normal attribute access.
+
+
.. _importlib:
Using importlib as the Implementation of Import
diff --git a/Include/object.h b/Include/object.h
index 3aabb3b..387cadb 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -962,7 +962,7 @@ with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL.
*/
/* This is the old private API, invoked by the macros before 3.2.4.
- Kept for binary compatibility of extensions. */
+ Kept for binary compatibility of extensions using the stable ABI. */
PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*);
PyAPI_FUNC(void) _PyTrash_destroy_chain(void);
PyAPI_DATA(int) _PyTrash_delete_nesting;
diff --git a/Include/pyfpe.h b/Include/pyfpe.h
index 19110ab..e957119 100644
--- a/Include/pyfpe.h
+++ b/Include/pyfpe.h
@@ -4,8 +4,8 @@
extern "C" {
#endif
/*
- ---------------------------------------------------------------------
- / Copyright (c) 1996. \
+ ---------------------------------------------------------------------
+ / Copyright (c) 1996. \
| The Regents of the University of California. |
| All rights reserved. |
| |
@@ -37,8 +37,8 @@ extern "C" {
| opinions of authors expressed herein do not necessarily state or |
| reflect those of the United States Government or the University |
| of California, and shall not be used for advertising or product |
- \ endorsement purposes. /
- ---------------------------------------------------------------------
+ \ endorsement purposes. /
+ ---------------------------------------------------------------------
*/
/*
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 387c585..fa77ec1 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -895,12 +895,18 @@ class BytesIO(BufferedIOBase):
return pos
def readable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return True
def writable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return True
def seekable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return True
@@ -1562,6 +1568,8 @@ class TextIOWrapper(TextIOBase):
return self._buffer
def seekable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return self._seekable
def readable(self):
diff --git a/Lib/argparse.py b/Lib/argparse.py
index 67bbef2..d5976e9 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1725,10 +1725,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
if action.dest is not SUPPRESS:
if not hasattr(namespace, action.dest):
if action.default is not SUPPRESS:
- default = action.default
- if isinstance(action.default, str):
- default = self._get_value(action, default)
- setattr(namespace, action.dest, default)
+ setattr(namespace, action.dest, action.default)
# add any parser defaults that aren't present
for dest in self._defaults:
@@ -1951,9 +1948,24 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
# if we didn't consume all the argument strings, there were extras
extras.extend(arg_strings[stop_index:])
- # make sure all required actions were present
- required_actions = [_get_action_name(action) for action in self._actions
- if action.required and action not in seen_actions]
+ # make sure all required actions were present and also convert
+ # action defaults which were not given as arguments
+ required_actions = []
+ for action in self._actions:
+ if action not in seen_actions:
+ if action.required:
+ required_actions.append(_get_action_name(action))
+ else:
+ # Convert action default now instead of doing it before
+ # parsing arguments to avoid calling convert functions
+ # twice (which may fail) if the argument was given, but
+ # only if it was defined already in the namespace
+ if (action.default is not None and
+ hasattr(namespace, action.dest) and
+ action.default is getattr(namespace, action.dest)):
+ setattr(namespace, action.dest,
+ self._get_value(action, action.default))
+
if required_actions:
self.error(_('the following arguments are required: %s') %
', '.join(required_actions))
diff --git a/Lib/gzip.py b/Lib/gzip.py
index b6656a9..d8abffd 100644
--- a/Lib/gzip.py
+++ b/Lib/gzip.py
@@ -670,9 +670,9 @@ def _test():
if not chunk:
break
g.write(chunk)
- if g is not sys.stdout:
+ if g is not sys.stdout.buffer:
g.close()
- if f is not sys.stdin:
+ if f is not sys.stdin.buffer:
f.close()
if __name__ == '__main__':
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index 8da3e77..e4688d0 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -1206,6 +1206,9 @@ class MixinStrUnicodeUserStringTest:
self.checkraises(ValueError, '%%%df' % (2**64), '__mod__', (3.2))
self.checkraises(ValueError, '%%.%df' % (2**64), '__mod__', (3.2))
+ class X(object): pass
+ self.checkraises(TypeError, 'abc', '__mod__', X())
+
def test_floatformatting(self):
# float formatting
for prec in range(100):
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 2e6584f..caf99af 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -1463,6 +1463,22 @@ class TestFileTypeR(TempDirMixin, ParserTestCase):
('readonly', NS(x=None, spam=RFile('readonly'))),
]
+class TestFileTypeDefaults(TempDirMixin, ParserTestCase):
+ """Test that a file is not created unless the default is needed"""
+ def setUp(self):
+ super(TestFileTypeDefaults, self).setUp()
+ file = open(os.path.join(self.temp_dir, 'good'), 'w')
+ file.write('good')
+ file.close()
+
+ argument_signatures = [
+ Sig('-c', type=argparse.FileType('r'), default='no-file.txt'),
+ ]
+ # should provoke no such file error
+ failures = ['']
+ # should not provoke error because default file is created
+ successes = [('-c good', NS(c=RFile('good')))]
+
class TestFileTypeRB(TempDirMixin, ParserTestCase):
"""Test the FileType option/argument type for reading files"""
@@ -4559,6 +4575,38 @@ class TestMessageContentError(TestCase):
self.assertNotIn(msg, 'optional_positional')
+# ================================================
+# Check that the type function is called only once
+# ================================================
+
+class TestTypeFunctionCallOnlyOnce(TestCase):
+
+ def test_type_function_call_only_once(self):
+ def spam(string_to_convert):
+ self.assertEqual(string_to_convert, 'spam!')
+ return 'foo_converted'
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--foo', type=spam, default='bar')
+ args = parser.parse_args('--foo spam!'.split())
+ self.assertEqual(NS(foo='foo_converted'), args)
+
+# ================================================================
+# Check that the type function is called with a non-string default
+# ================================================================
+
+class TestTypeFunctionCallWithNonStringDefault(TestCase):
+
+ def test_type_function_call_with_non_string_default(self):
+ def spam(int_to_convert):
+ self.assertEqual(int_to_convert, 0)
+ return 'foo_converted'
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--foo', type=spam, default=0)
+ args = parser.parse_args([])
+ self.assertEqual(NS(foo='foo_converted'), args)
+
# ======================
# parse_known_args tests
# ======================
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index aa08166..a8853c7 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -407,6 +407,14 @@ class ASTHelpers_Test(unittest.TestCase):
b = compile('foo(1 + 1)', '<unknown>', 'exec', ast.PyCF_ONLY_AST)
self.assertEqual(ast.dump(a), ast.dump(b))
+ def test_parse_in_error(self):
+ try:
+ 1/0
+ except Exception:
+ with self.assertRaises(SyntaxError) as e:
+ ast.literal_eval(r"'\U'")
+ self.assertIsNotNone(e.exception.__context__)
+
def test_dump(self):
node = ast.parse('spam(eggs, "and cheese")')
self.assertEqual(ast.dump(node),
diff --git a/Lib/test/test_importlib/test_locks.py b/Lib/test/test_importlib/test_locks.py
index d36b71e..c373b11 100644
--- a/Lib/test/test_importlib/test_locks.py
+++ b/Lib/test/test_importlib/test_locks.py
@@ -1,4 +1,5 @@
from importlib import _bootstrap
+import sys
import time
import unittest
import weakref
@@ -41,6 +42,17 @@ else:
@unittest.skipUnless(threading, "threads needed for this test")
class DeadlockAvoidanceTests(unittest.TestCase):
+ def setUp(self):
+ try:
+ self.old_switchinterval = sys.getswitchinterval()
+ sys.setswitchinterval(0.000001)
+ except AttributeError:
+ self.old_switchinterval = None
+
+ def tearDown(self):
+ if self.old_switchinterval is not None:
+ sys.setswitchinterval(self.old_switchinterval)
+
def run_deadlock_avoidance_test(self, create_deadlock):
NLOCKS = 10
locks = [LockType(str(i)) for i in range(NLOCKS)]
@@ -75,10 +87,12 @@ class DeadlockAvoidanceTests(unittest.TestCase):
def test_deadlock(self):
results = self.run_deadlock_avoidance_test(True)
- # One of the threads detected a potential deadlock on its second
- # acquire() call.
- self.assertEqual(results.count((True, False)), 1)
- self.assertEqual(results.count((True, True)), len(results) - 1)
+ # At least one of the threads detected a potential deadlock on its
+ # second acquire() call. It may be several of them, because the
+ # deadlock avoidance mechanism is conservative.
+ nb_deadlocks = results.count((True, False))
+ self.assertGreaterEqual(nb_deadlocks, 1)
+ self.assertEqual(results.count((True, True)), len(results) - nb_deadlocks)
def test_no_deadlock(self):
results = self.run_deadlock_avoidance_test(False)
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 5515357..fd7f319 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -763,13 +763,13 @@ class TestMaildir(TestMailbox, unittest.TestCase):
self.assertIsNot(match, None, "Invalid file name: '%s'" % tail)
groups = match.groups()
if previous_groups is not None:
- self.assertTrue(int(groups[0] >= previous_groups[0]),
+ self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]),
"Non-monotonic seconds: '%s' before '%s'" %
(previous_groups[0], groups[0]))
- self.assertTrue(int(groups[1] >= previous_groups[1]) or
- groups[0] != groups[1],
- "Non-monotonic milliseconds: '%s' before '%s'" %
- (previous_groups[1], groups[1]))
+ if int(groups[0]) == int(previous_groups[0]):
+ self.assertGreaterEqual(int(groups[1]), int(previous_groups[1]),
+ "Non-monotonic milliseconds: '%s' before '%s'" %
+ (previous_groups[1], groups[1]))
self.assertEqual(int(groups[2]), pid,
"Process ID mismatch: '%s' should be '%s'" %
(groups[2], pid))
diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py
index 04ec8e7..e5db945 100644
--- a/Lib/test/test_memoryio.py
+++ b/Lib/test/test_memoryio.py
@@ -318,9 +318,9 @@ class MemoryTestMixin:
self.assertEqual(memio.isatty(), False)
self.assertEqual(memio.closed, False)
memio.close()
- self.assertEqual(memio.writable(), True)
- self.assertEqual(memio.readable(), True)
- self.assertEqual(memio.seekable(), True)
+ self.assertRaises(ValueError, memio.writable)
+ self.assertRaises(ValueError, memio.readable)
+ self.assertRaises(ValueError, memio.seekable)
self.assertRaises(ValueError, memio.isatty)
self.assertEqual(memio.closed, True)
@@ -665,7 +665,6 @@ class CBytesIOTest(PyBytesIOTest):
check(io.BytesIO(b'a'), basesize + 1 + 1 )
check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 )
-
class CStringIOTest(PyStringIOTest):
ioclass = io.StringIO
UnsupportedOperation = io.UnsupportedOperation
diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py
index 32eb1c0..f6469cf 100644
--- a/Lib/test/test_super.py
+++ b/Lib/test/test_super.py
@@ -115,6 +115,21 @@ class TestSuper(unittest.TestCase):
return __class__
self.assertIs(X.f(), X)
+ def test_obscure_super_errors(self):
+ def f():
+ super()
+ self.assertRaises(RuntimeError, f)
+ def f(x):
+ del x
+ super()
+ self.assertRaises(RuntimeError, f, None)
+ class X:
+ def f(x):
+ nonlocal __class__
+ del __class__
+ super()
+ self.assertRaises(RuntimeError, X().f)
+
def test_main():
support.run_unittest(TestSuper)
diff --git a/Lib/test/test_textwrap.py b/Lib/test/test_textwrap.py
index bb4a851..c86f5cf 100644
--- a/Lib/test/test_textwrap.py
+++ b/Lib/test/test_textwrap.py
@@ -22,7 +22,7 @@ class BaseTestCase(unittest.TestCase):
result = []
for i in range(len(textin)):
result.append(" %d: %r" % (i, textin[i]))
- result = '\n'.join(result)
+ result = "\n".join(result) if result else " no lines"
elif isinstance(textin, str):
result = " %s\n" % repr(textin)
return result
@@ -66,6 +66,15 @@ class WrapTestCase(BaseTestCase):
"I'm glad to hear it!"])
self.check_wrap(text, 80, [text])
+ def test_empty_string(self):
+ # Check that wrapping the empty string returns an empty list.
+ self.check_wrap("", 6, [])
+ self.check_wrap("", 6, [], drop_whitespace=False)
+
+ def test_empty_string_with_initial_indent(self):
+ # Check that the empty string is not indented.
+ self.check_wrap("", 6, [], initial_indent="++")
+ self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False)
def test_whitespace(self):
# Whitespace munging and end-of-sentence detection
@@ -331,7 +340,32 @@ What a mess!
["blah", " ", "(ding", " ", "dong),",
" ", "wubba"])
- def test_initial_whitespace(self):
+ def test_drop_whitespace_false(self):
+ # Check that drop_whitespace=False preserves whitespace.
+ # SF patch #1581073
+ text = " This is a sentence with much whitespace."
+ self.check_wrap(text, 10,
+ [" This is a", " ", "sentence ",
+ "with ", "much white", "space."],
+ drop_whitespace=False)
+
+ def test_drop_whitespace_false_whitespace_only(self):
+ # Check that drop_whitespace=False preserves a whitespace-only string.
+ self.check_wrap(" ", 6, [" "], drop_whitespace=False)
+
+ def test_drop_whitespace_false_whitespace_only_with_indent(self):
+ # Check that a whitespace-only string gets indented (when
+ # drop_whitespace is False).
+ self.check_wrap(" ", 6, [" "], drop_whitespace=False,
+ initial_indent=" ")
+
+ def test_drop_whitespace_whitespace_only(self):
+ # Check drop_whitespace on a whitespace-only string.
+ self.check_wrap(" ", 6, [])
+
+ def test_drop_whitespace_leading_whitespace(self):
+ # Check that drop_whitespace does not drop leading whitespace (if
+ # followed by non-whitespace).
# SF bug #622849 reported inconsistent handling of leading
# whitespace; let's test that a bit, shall we?
text = " This is a sentence with leading whitespace."
@@ -340,13 +374,27 @@ What a mess!
self.check_wrap(text, 30,
[" This is a sentence with", "leading whitespace."])
- def test_no_drop_whitespace(self):
- # SF patch #1581073
- text = " This is a sentence with much whitespace."
- self.check_wrap(text, 10,
- [" This is a", " ", "sentence ",
- "with ", "much white", "space."],
+ def test_drop_whitespace_whitespace_line(self):
+ # Check that drop_whitespace skips the whole line if a non-leading
+ # line consists only of whitespace.
+ text = "abcd efgh"
+ # Include the result for drop_whitespace=False for comparison.
+ self.check_wrap(text, 6, ["abcd", " ", "efgh"],
drop_whitespace=False)
+ self.check_wrap(text, 6, ["abcd", "efgh"])
+
+ def test_drop_whitespace_whitespace_only_with_indent(self):
+ # Check that initial_indent is not applied to a whitespace-only
+ # string. This checks a special case of the fact that dropping
+ # whitespace occurs before indenting.
+ self.check_wrap(" ", 6, [], initial_indent="++")
+
+ def test_drop_whitespace_whitespace_indent(self):
+ # Check that drop_whitespace does not drop whitespace indents.
+ # This checks a special case of the fact that dropping whitespace
+ # occurs before indenting.
+ self.check_wrap("abcd efgh", 6, [" abcd", " efgh"],
+ initial_indent=" ", subsequent_indent=" ")
def test_split(self):
# Ensure that the standard _split() method works as advertised
diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py
new file mode 100644
index 0000000..34b9364
--- /dev/null
+++ b/Lib/test/test_webbrowser.py
@@ -0,0 +1,192 @@
+import webbrowser
+import unittest
+import subprocess
+from unittest import mock
+from test import support
+
+
+URL = 'http://www.example.com'
+CMD_NAME = 'test'
+
+
+class PopenMock(mock.MagicMock):
+
+ def poll(self):
+ return 0
+
+ def wait(self, seconds=None):
+ return 0
+
+
+class CommandTestMixin:
+
+ def _test(self, meth, *, args=[URL], kw={}, options, arguments):
+ """Given a web browser instance method name along with arguments and
+ keywords for same (which defaults to the single argument URL), creates
+ a browser instance from the class pointed to by self.browser, calls the
+ indicated instance method with the indicated arguments, and compares
+ the resulting options and arguments passed to Popen by the browser
+ instance against the 'options' and 'args' lists. Options are compared
+ in a position independent fashion, and the arguments are compared in
+ sequence order to whatever is left over after removing the options.
+
+ """
+ popen = PopenMock()
+ support.patch(self, subprocess, 'Popen', popen)
+ browser = self.browser_class(name=CMD_NAME)
+ getattr(browser, meth)(*args, **kw)
+ popen_args = subprocess.Popen.call_args[0][0]
+ self.assertEqual(popen_args[0], CMD_NAME)
+ popen_args.pop(0)
+ for option in options:
+ self.assertIn(option, popen_args)
+ popen_args.pop(popen_args.index(option))
+ self.assertEqual(popen_args, arguments)
+
+
+class GenericBrowserCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.GenericBrowser
+
+ def test_open(self):
+ self._test('open',
+ options=[],
+ arguments=[URL])
+
+
+class BackgroundBrowserCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.BackgroundBrowser
+
+ def test_open(self):
+ self._test('open',
+ options=[],
+ arguments=[URL])
+
+
+class ChromeCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.Chrome
+
+ def test_open(self):
+ self._test('open',
+ options=[],
+ arguments=[URL])
+
+ def test_open_with_autoraise_false(self):
+ self._test('open', kw=dict(autoraise=False),
+ options=[],
+ arguments=[URL])
+
+ def test_open_new(self):
+ self._test('open_new',
+ options=['--new-window'],
+ arguments=[URL])
+
+ def test_open_new_tab(self):
+ self._test('open_new_tab',
+ options=[],
+ arguments=[URL])
+
+
+class MozillaCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.Mozilla
+
+ def test_open(self):
+ self._test('open',
+ options=['-raise', '-remote'],
+ arguments=['openURL({})'.format(URL)])
+
+ def test_open_with_autoraise_false(self):
+ self._test('open', kw=dict(autoraise=False),
+ options=['-noraise', '-remote'],
+ arguments=['openURL({})'.format(URL)])
+
+ def test_open_new(self):
+ self._test('open_new',
+ options=['-raise', '-remote'],
+ arguments=['openURL({},new-window)'.format(URL)])
+
+ def test_open_new_tab(self):
+ self._test('open_new_tab',
+ options=['-raise', '-remote'],
+ arguments=['openURL({},new-tab)'.format(URL)])
+
+
+class GaleonCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.Galeon
+
+ def test_open(self):
+ self._test('open',
+ options=['-n'],
+ arguments=[URL])
+
+ def test_open_with_autoraise_false(self):
+ self._test('open', kw=dict(autoraise=False),
+ options=['-noraise', '-n'],
+ arguments=[URL])
+
+ def test_open_new(self):
+ self._test('open_new',
+ options=['-w'],
+ arguments=[URL])
+
+ def test_open_new_tab(self):
+ self._test('open_new_tab',
+ options=['-w'],
+ arguments=[URL])
+
+
+class OperaCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.Opera
+
+ def test_open(self):
+ self._test('open',
+ options=['-remote'],
+ arguments=['openURL({})'.format(URL)])
+
+ def test_open_with_autoraise_false(self):
+ self._test('open', kw=dict(autoraise=False),
+ options=['-remote', '-noraise'],
+ arguments=['openURL({})'.format(URL)])
+
+ def test_open_new(self):
+ self._test('open_new',
+ options=['-remote'],
+ arguments=['openURL({},new-window)'.format(URL)])
+
+ def test_open_new(self):
+ self._test('open_new_tab',
+ options=['-remote'],
+ arguments=['openURL({},new-page)'.format(URL)])
+
+
+class ELinksCommandTest(CommandTestMixin, unittest.TestCase):
+
+ browser_class = webbrowser.Elinks
+
+ def test_open(self):
+ self._test('open', options=['-remote'],
+ arguments=['openURL({})'.format(URL)])
+
+ def test_open_with_autoraise_false(self):
+ self._test('open',
+ options=['-remote'],
+ arguments=['openURL({})'.format(URL)])
+
+ def test_open_new(self):
+ self._test('open_new',
+ options=['-remote'],
+ arguments=['openURL({},new-window)'.format(URL)])
+
+ def test_open_new_tab(self):
+ self._test('open_new_tab',
+ options=['-remote'],
+ arguments=['openURL({},new-tab)'.format(URL)])
+
+
+if __name__=='__main__':
+ unittest.main()
diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
index ce5b48e..94d4ad4 100644
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -206,12 +206,18 @@ class UnixBrowser(BaseBrowser):
"""Parent class for all Unix browsers with remote functionality."""
raise_opts = None
+ background = False
+ redirect_stdout = True
+ # In remote_args, %s will be replaced with the requested URL. %action will
+ # be replaced depending on the value of 'new' passed to open.
+ # remote_action is used for new=0 (open). If newwin is not None, it is
+ # used for new=1 (open_new). If newtab is not None, it is used for
+ # new=3 (open_new_tab). After both substitutions are made, any empty
+ # strings in the transformed remote_args list will be removed.
remote_args = ['%action', '%s']
remote_action = None
remote_action_newwin = None
remote_action_newtab = None
- background = False
- redirect_stdout = True
def _invoke(self, args, remote, autoraise):
raise_opt = []
@@ -224,7 +230,7 @@ class UnixBrowser(BaseBrowser):
cmdline = [self.name] + raise_opt + args
if remote or self.background:
- inout = io.open(os.devnull, "r+")
+ inout = subprocess.DEVNULL
else:
# for TTY browsers, we need stdin/out
inout = None
@@ -264,6 +270,7 @@ class UnixBrowser(BaseBrowser):
args = [arg.replace("%s", url).replace("%action", action)
for arg in self.remote_args]
+ args = [arg for arg in args if arg]
success = self._invoke(args, True, autoraise)
if not success:
# remote invocation failed, try straight way
@@ -347,7 +354,7 @@ class Konqueror(BaseBrowser):
else:
action = "openURL"
- devnull = io.open(os.devnull, "r+")
+ devnull = subprocess.DEVNULL
# if possible, put browser in separate process group, so
# keyboard interrupts don't affect browser as well as Python
setsid = getattr(os, 'setsid', None)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index d42c938..af4fd81 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -229,8 +229,8 @@ IO_OBJS= \
##########################################################################
# Grammar
-GRAMMAR_H= $(srcdir)/Include/graminit.h
-GRAMMAR_C= $(srcdir)/Python/graminit.c
+GRAMMAR_H= Include/graminit.h
+GRAMMAR_C= Python/graminit.c
GRAMMAR_INPUT= $(srcdir)/Grammar/Grammar
@@ -296,9 +296,9 @@ PGENOBJS= $(POBJS) $(PGOBJS)
##########################################################################
# AST
-AST_H_DIR= $(srcdir)/Include
+AST_H_DIR= Include
AST_H= $(AST_H_DIR)/Python-ast.h
-AST_C_DIR= $(srcdir)/Python
+AST_C_DIR= Python
AST_C= $(AST_C_DIR)/Python-ast.c
AST_ASDL= $(srcdir)/Parser/Python.asdl
@@ -474,8 +474,13 @@ $(SYSCONFIGDATA): $(BUILDPYTHON)
$(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars
# Build the shared modules
+# MAKEFLAGS are sorted and normalized. Under GNU make the 's' for
+# -s, --silent or --quiet is always the first char.
sharedmods: $(BUILDPYTHON) $(SYSCONFIGDATA)
- case $$MAKEFLAGS in *s*) quiet=-q; esac; \
+ @case "$$MAKEFLAGS" in \
+ s*) quiet="-q";; \
+ *) quiet="";; \
+ esac; \
$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \
$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
@@ -660,9 +665,11 @@ Parser/printgrammar.o: $(srcdir)/Parser/printgrammar.c
Parser/pgenmain.o: $(srcdir)/Include/parsetok.h
$(AST_H): $(AST_ASDL) $(ASDLGEN_FILES)
+ $(MKDIR_P) $(AST_H_DIR)
$(ASDLGEN) -h $(AST_H_DIR) $(AST_ASDL)
$(AST_C): $(AST_H) $(AST_ASDL) $(ASDLGEN_FILES)
+ $(MKDIR_P) $(AST_C_DIR)
$(ASDLGEN) -c $(AST_C_DIR) $(AST_ASDL)
Python/compile.o Python/symtable.o Python/ast.o: $(GRAMMAR_H) $(AST_H)
diff --git a/Misc/ACKS b/Misc/ACKS
index 88e92d7..8af9f73 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -335,6 +335,7 @@ Nils Fischbeck
Frederik Fix
Matt Fleming
Hernán Martínez Foffani
+Arnaud Fontaine
Michael Foord
Amaury Forgeot d'Arc
Doug Fort
@@ -730,6 +731,7 @@ Paul Moore
Derek Morr
James A Morrison
Derek McTavish Mounce
+Alessandro Moura
Pablo Mouzo
Mher Movsisyan
Ruslan Mstoi
diff --git a/Misc/NEWS b/Misc/NEWS
index e6e4cbb..0db3e09 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,71 @@
Python News
+++++++++++
+What's New in Python 3.3.1
+==========================
+
+*Release date: XX-XX-XXXX*
+
+Core and Builtins
+-----------------
+
+- Issue #15839: Convert SystemErrors in super() to RuntimeErrors.
+
+- Issue #15846: Fix SystemError which happened when using ast.parse in an
+ exception handler on code with syntax errors.
+
+- Issue #15801: Make sure mappings passed to '%' formatting are actually
+ subscriptable.
+
+Library
+-------
+
+- Issue #15876: Fix a refleak in the curses module: window.encoding.
+
+- Issue #15841: The readable(), writable() and seekable() methods of BytesIO
+ and StringIO objects now raise ValueError when the object has been closed.
+ Patch by Alessandro Moura.
+
+- Issue #15447: Use subprocess.DEVNULL in webbrowser, instead of opening
+ os.devnull explicitly and leaving it open.
+
+- Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to
+ Popen when %action substitutions produce empty strings.
+
+- Issue #12776,#11839: call argparse type function (specified by add_argument)
+ only once. Before, the type function was called twice in the case where the
+ default was specified and the argument was given as well. This was
+ especially problematic for the FileType type, as a default file would always
+ be opened, even if a file argument was specified on the command line.
+
+Extension Modules
+-----------------
+
+Tests
+-----
+
+- Issue #15802: Fix test logic in TestMaildir.test_create_tmp. Patch
+ by Serhiy Storchaka.
+
+- Issue #15557: Added a test suite for the webbrowser module, thanks
+ to Anton Barkovsky.
+
+Build
+-----
+
+- Issue #15819: Make sure we can build Python out-of-tree from a readonly
+ source directory. (Somewhat related to Issue #9860.)
+
+Documentation
+-------------
+
+- Issue #11964: Document a change in v3.2 to the behavior of the indent
+ parameter of json encoding operations.
+
+Tools/Demos
+-----------
+
+
What's New in Python 3.3.0?
===========================
@@ -118,8 +183,6 @@ Library
- Issue #15544: Fix Decimal.__float__ to work with payload-carrying NaNs.
-- Issue #15776: Allow pyvenv to work in existing directory with --clean.
-
- Issue #15249: BytesGenerator now correctly mangles From lines (when
requested) even if the body contains undecodable bytes.
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 3f9ca13..4e1449b 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -1938,6 +1938,7 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value)
if (ascii == NULL)
return -1;
encoding = strdup(PyBytes_AS_STRING(ascii));
+ Py_DECREF(ascii);
if (encoding == NULL) {
PyErr_NoMemory();
return -1;
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 3d027e2..54840bb 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -121,7 +121,7 @@ resize_buffer(bytesio *self, size_t size)
}
/* Internal routine for writing a string of bytes to the buffer of a BytesIO
- object. Returns the number of bytes wrote, or -1 on error. */
+ object. Returns the number of bytes written, or -1 on error. */
static Py_ssize_t
write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
{
@@ -171,10 +171,20 @@ bytesio_get_closed(bytesio *self)
}
}
+PyDoc_STRVAR(readable_doc,
+"readable() -> bool. Returns True if the IO object can be read.");
+
+PyDoc_STRVAR(writable_doc,
+"writable() -> bool. Returns True if the IO object can be written.");
+
+PyDoc_STRVAR(seekable_doc,
+"seekable() -> bool. Returns True if the IO object can be seeked.");
+
/* Generic getter for the writable, readable and seekable properties */
static PyObject *
-return_true(bytesio *self)
+return_not_closed(bytesio *self)
{
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -682,8 +692,10 @@ bytesio_getstate(bytesio *self)
}
else {
dict = PyDict_Copy(self->dict);
- if (dict == NULL)
+ if (dict == NULL) {
+ Py_DECREF(initvalue);
return NULL;
+ }
}
state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
@@ -867,9 +879,9 @@ static PyGetSetDef bytesio_getsetlist[] = {
};
static struct PyMethodDef bytesio_methods[] = {
- {"readable", (PyCFunction)return_true, METH_NOARGS, NULL},
- {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL},
- {"writable", (PyCFunction)return_true, METH_NOARGS, NULL},
+ {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc},
+ {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc},
+ {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc},
{"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
{"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
{"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index a1c31c0..9d73884 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -760,10 +760,21 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
}
/* Properties and pseudo-properties */
+
+PyDoc_STRVAR(stringio_readable_doc,
+"readable() -> bool. Returns True if the IO object can be read.");
+
+PyDoc_STRVAR(stringio_writable_doc,
+"writable() -> bool. Returns True if the IO object can be written.");
+
+PyDoc_STRVAR(stringio_seekable_doc,
+"seekable() -> bool. Returns True if the IO object can be seeked.");
+
static PyObject *
stringio_seekable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -771,6 +782,7 @@ static PyObject *
stringio_readable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -778,6 +790,7 @@ static PyObject *
stringio_writable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -956,9 +969,9 @@ static struct PyMethodDef stringio_methods[] = {
{"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc},
{"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc},
- {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS},
- {"readable", (PyCFunction)stringio_readable, METH_NOARGS},
- {"writable", (PyCFunction)stringio_writable, METH_NOARGS},
+ {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc},
+ {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc},
+ {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc},
{"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
{"__setstate__", (PyCFunction)stringio_setstate, METH_O},
diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c
index 87ada0a..316666e 100644
--- a/Modules/_testbuffer.c
+++ b/Modules/_testbuffer.c
@@ -16,6 +16,7 @@ PyObject *calcsize = NULL;
static const char *simple_fmt = "B";
PyObject *simple_format = NULL;
#define SIMPLE_FORMAT(fmt) (fmt == NULL || strcmp(fmt, "B") == 0)
+#define FIX_FORMAT(fmt) (fmt == NULL ? "B" : fmt)
/**************************************************************************/
@@ -513,10 +514,8 @@ static int
cmp_structure(Py_buffer *dest, Py_buffer *src)
{
Py_ssize_t i;
- int same_fmt = ((dest->format == NULL && src->format == NULL) || \
- (strcmp(dest->format, src->format) == 0));
- if (!same_fmt ||
+ if (strcmp(FIX_FORMAT(dest->format), FIX_FORMAT(src->format)) != 0 ||
dest->itemsize != src->itemsize ||
dest->ndim != src->ndim)
return -1;
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index f547983..d56faf8 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -2861,28 +2861,74 @@ memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
}
+PyDoc_STRVAR(memory_obj_doc,
+ "The underlying object of the memoryview.");
+PyDoc_STRVAR(memory_nbytes_doc,
+ "The amount of space in bytes that the array would use in\n"
+ " a contiguous representation.");
+PyDoc_STRVAR(memory_readonly_doc,
+ "A bool indicating whether the memory is read only.");
+PyDoc_STRVAR(memory_itemsize_doc,
+ "The size in bytes of each element of the memoryview.");
+PyDoc_STRVAR(memory_format_doc,
+ "A string containing the format (in struct module style)\n"
+ " for each element in the view.");
+PyDoc_STRVAR(memory_ndim_doc,
+ "An integer indicating how many dimensions of a multi-dimensional\n"
+ " array the memory represents.");
+PyDoc_STRVAR(memory_shape_doc,
+ "A tuple of ndim integers giving the shape of the memory\n"
+ " as an N-dimensional array.");
+PyDoc_STRVAR(memory_strides_doc,
+ "A tuple of ndim integers giving the size in bytes to access\n"
+ " each element for each dimension of the array.");
+PyDoc_STRVAR(memory_suboffsets_doc,
+ "A tuple of integers used internally for PIL-style arrays.");
+PyDoc_STRVAR(memory_c_contiguous_doc,
+ "A bool indicating whether the memory is C contiguous.");
+PyDoc_STRVAR(memory_f_contiguous_doc,
+ "A bool indicating whether the memory is Fortran contiguous.");
+PyDoc_STRVAR(memory_contiguous_doc,
+ "A bool indicating whether the memory is contiguous.");
+
static PyGetSetDef memory_getsetlist[] = {
- {"obj", (getter)memory_obj_get, NULL, NULL},
- {"nbytes", (getter)memory_nbytes_get, NULL, NULL},
- {"readonly", (getter)memory_readonly_get, NULL, NULL},
- {"itemsize", (getter)memory_itemsize_get, NULL, NULL},
- {"format", (getter)memory_format_get, NULL, NULL},
- {"ndim", (getter)memory_ndim_get, NULL, NULL},
- {"shape", (getter)memory_shape_get, NULL, NULL},
- {"strides", (getter)memory_strides_get, NULL, NULL},
- {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},
- {"c_contiguous", (getter)memory_c_contiguous, NULL, NULL},
- {"f_contiguous", (getter)memory_f_contiguous, NULL, NULL},
- {"contiguous", (getter)memory_contiguous, NULL, NULL},
+ {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
+ {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
+ {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
+ {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
+ {"format", (getter)memory_format_get, NULL, memory_format_doc},
+ {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
+ {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
+ {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
+ {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
+ {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
+ {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
+ {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
{NULL, NULL, NULL, NULL},
};
+PyDoc_STRVAR(memory_release_doc,
+"M.release() -> None\n\
+\n\
+Release the underlying buffer exposed by the memoryview object.");
+PyDoc_STRVAR(memory_tobytes_doc,
+"M.tobytes() -> bytes\n\
+\n\
+Return the data in the buffer as a byte string.");
+PyDoc_STRVAR(memory_tolist_doc,
+"M.tolist() -> list\n\
+\n\
+Return the data in the buffer as a list of elements.");
+PyDoc_STRVAR(memory_cast_doc,
+"M.cast(format[, shape]) -> memoryview\n\
+\n\
+Cast a memoryview to a new format or shape.");
static PyMethodDef memory_methods[] = {
- {"release", (PyCFunction)memory_release, METH_NOARGS, NULL},
- {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},
- {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},
- {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, NULL},
+ {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
+ {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
+ {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
+ {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
{"__enter__", memory_enter, METH_NOARGS, NULL},
{"__exit__", memory_exit, METH_VARARGS, NULL},
{NULL, NULL}
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 8fb239b..bd55ede 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6502,18 +6502,18 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
PyCodeObject *co = f->f_code;
Py_ssize_t i, n;
if (co == NULL) {
- PyErr_SetString(PyExc_SystemError,
+ PyErr_SetString(PyExc_RuntimeError,
"super(): no code object");
return -1;
}
if (co->co_argcount == 0) {
- PyErr_SetString(PyExc_SystemError,
+ PyErr_SetString(PyExc_RuntimeError,
"super(): no arguments");
return -1;
}
obj = f->f_localsplus[0];
if (obj == NULL) {
- PyErr_SetString(PyExc_SystemError,
+ PyErr_SetString(PyExc_RuntimeError,
"super(): arg[0] deleted");
return -1;
}
@@ -6532,18 +6532,18 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
PyTuple_GET_SIZE(co->co_cellvars) + i;
PyObject *cell = f->f_localsplus[index];
if (cell == NULL || !PyCell_Check(cell)) {
- PyErr_SetString(PyExc_SystemError,
+ PyErr_SetString(PyExc_RuntimeError,
"super(): bad __class__ cell");
return -1;
}
type = (PyTypeObject *) PyCell_GET(cell);
if (type == NULL) {
- PyErr_SetString(PyExc_SystemError,
+ PyErr_SetString(PyExc_RuntimeError,
"super(): empty __class__ cell");
return -1;
}
if (!PyType_Check(type)) {
- PyErr_Format(PyExc_SystemError,
+ PyErr_Format(PyExc_RuntimeError,
"super(): __class__ is not a type (%s)",
Py_TYPE(type)->tp_name);
return -1;
@@ -6552,7 +6552,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
}
}
if (type == NULL) {
- PyErr_SetString(PyExc_SystemError,
+ PyErr_SetString(PyExc_RuntimeError,
"super(): __class__ cell not found");
return -1;
}
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 773a9be..2795168 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -9146,7 +9146,7 @@ tailmatch(PyObject *self,
/* We do not need to compare 0 and len(substring)-1 because
the if statement above ensured already that they are equal
when we end up here. */
- // TODO: honor direction and do a forward or backwards search
+ /* TODO: honor direction and do a forward or backwards search */
for (i = 1; i < end_sub; ++i) {
if (PyUnicode_READ(kind_self, data_self, offset + i) !=
PyUnicode_READ(kind_sub, data_sub, i))
@@ -13461,8 +13461,7 @@ PyUnicode_Format(PyObject *format, PyObject *args)
arglen = -1;
argidx = -2;
}
- if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) &&
- !PyUnicode_Check(args))
+ if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args))
dict = args;
while (--fmtcnt >= 0) {
diff --git a/Python/ast.c b/Python/ast.c
index fc6c565..43c18f4 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -545,9 +545,9 @@ init_normalization(struct compiling *c)
}
static identifier
-new_identifier(const char* n, struct compiling *c)
+new_identifier(const char *n, struct compiling *c)
{
- PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL);
+ PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL);
if (!id)
return NULL;
/* PyUnicode_DecodeUTF8 should always return a ready string. */
@@ -574,79 +574,43 @@ new_identifier(const char* n, struct compiling *c)
#define NEW_IDENTIFIER(n) new_identifier(STR(n), c)
-/* This routine provides an invalid object for the syntax error.
- The outermost routine must unpack this error and create the
- proper object. We do this so that we don't have to pass
- the filename to everything function.
-
- XXX Maybe we should just pass the filename...
-*/
-
static int
-ast_error(const node *n, const char *errstr)
-{
- PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset);
- if (!u)
- return 0;
- PyErr_SetObject(PyExc_SyntaxError, u);
- Py_DECREF(u);
- return 0;
-}
-
-static void
-ast_error_finish(const char *filename)
+ast_error(struct compiling *c, const node *n, const char *errmsg)
{
- PyObject *type, *value, *tback, *errstr, *offset, *loc, *tmp;
+ PyObject *value, *errstr, *loc, *tmp;
PyObject *filename_obj;
- long lineno;
-
- assert(PyErr_Occurred());
- if (!PyErr_ExceptionMatches(PyExc_SyntaxError))
- return;
-
- PyErr_Fetch(&type, &value, &tback);
- errstr = PyTuple_GetItem(value, 0);
- if (!errstr)
- return;
- Py_INCREF(errstr);
- lineno = PyLong_AsLong(PyTuple_GetItem(value, 1));
- if (lineno == -1) {
- Py_DECREF(errstr);
- return;
- }
- offset = PyTuple_GetItem(value, 2);
- if (!offset) {
- Py_DECREF(errstr);
- return;
- }
- Py_DECREF(value);
-
- loc = PyErr_ProgramText(filename, lineno);
+
+ loc = PyErr_ProgramText(c->c_filename, LINENO(n));
if (!loc) {
Py_INCREF(Py_None);
loc = Py_None;
}
- if (filename != NULL)
- filename_obj = PyUnicode_DecodeFSDefault(filename);
- else {
+ if (c->c_filename) {
+ filename_obj = PyUnicode_DecodeFSDefault(c->c_filename);
+ if (!filename_obj) {
+ Py_DECREF(loc);
+ return 0;
+ }
+ } else {
Py_INCREF(Py_None);
filename_obj = Py_None;
}
- if (filename_obj != NULL)
- tmp = Py_BuildValue("(NlOO)", filename_obj, lineno, offset, loc);
- else
- tmp = NULL;
- Py_DECREF(loc);
- if (!tmp) {
- Py_DECREF(errstr);
- return;
+ tmp = Py_BuildValue("(NiiN)", filename_obj, LINENO(n), n->n_col_offset, loc);
+ if (!tmp)
+ return 0;
+ errstr = PyUnicode_FromString(errmsg);
+ if (!errstr) {
+ Py_DECREF(tmp);
+ return 0;
}
value = PyTuple_Pack(2, errstr, tmp);
Py_DECREF(errstr);
Py_DECREF(tmp);
- if (!value)
- return;
- PyErr_Restore(type, value, tback);
+ if (value) {
+ PyErr_SetObject(PyExc_SyntaxError, value);
+ Py_DECREF(value);
+ }
+ return 0;
}
/* num_stmts() returns number of contained statements.
@@ -724,11 +688,14 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
struct compiling c;
mod_ty res = NULL;
+ c.c_arena = arena;
+ c.c_filename = filename;
+ c.c_normalize = c.c_normalize_args = NULL;
if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {
c.c_encoding = "utf-8";
if (TYPE(n) == encoding_decl) {
#if 0
- ast_error(n, "encoding declaration in Unicode string");
+ ast_error(c, n, "encoding declaration in Unicode string");
goto out;
#endif
n = CHILD(n, 0);
@@ -740,9 +707,6 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
/* PEP 3120 */
c.c_encoding = "utf-8";
}
- c.c_arena = arena;
- c.c_filename = filename;
- c.c_normalize = c.c_normalize_args = NULL;
k = 0;
switch (TYPE(n)) {
@@ -835,8 +799,6 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL);
Py_DECREF(c.c_normalize_args);
}
- if (!res)
- ast_error_finish(filename);
return res;
}
@@ -882,18 +844,18 @@ static const char* FORBIDDEN[] = {
};
static int
-forbidden_name(identifier name, const node *n, int full_checks)
+forbidden_name(struct compiling *c, identifier name, const node *n, int full_checks)
{
assert(PyUnicode_Check(name));
if (PyUnicode_CompareWithASCIIString(name, "__debug__") == 0) {
- ast_error(n, "assignment to keyword");
+ ast_error(c, n, "assignment to keyword");
return 1;
}
if (full_checks) {
const char **p;
for (p = FORBIDDEN; *p; p++) {
if (PyUnicode_CompareWithASCIIString(name, *p) == 0) {
- ast_error(n, "assignment to keyword");
+ ast_error(c, n, "assignment to keyword");
return 1;
}
}
@@ -929,7 +891,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
switch (e->kind) {
case Attribute_kind:
e->v.Attribute.ctx = ctx;
- if (ctx == Store && forbidden_name(e->v.Attribute.attr, n, 1))
+ if (ctx == Store && forbidden_name(c, e->v.Attribute.attr, n, 1))
return 0;
break;
case Subscript_kind:
@@ -942,7 +904,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
break;
case Name_kind:
if (ctx == Store) {
- if (forbidden_name(e->v.Name.id, n, 1))
+ if (forbidden_name(c, e->v.Name.id, n, 1))
return 0; /* forbidden_name() calls ast_error() */
}
e->v.Name.ctx = ctx;
@@ -1016,7 +978,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
"can't %s %s",
ctx == Store ? "assign to" : "delete",
expr_name);
- return ast_error(n, buf);
+ return ast_error(c, n, buf);
}
/* If the LHS is a list or tuple, we need to set the assignment
@@ -1164,7 +1126,7 @@ ast_for_arg(struct compiling *c, const node *n)
name = NEW_IDENTIFIER(ch);
if (!name)
return NULL;
- if (forbidden_name(name, ch, 0))
+ if (forbidden_name(c, name, ch, 0))
return NULL;
if (NCH(n) == 3 && TYPE(CHILD(n, 1)) == COLON) {
@@ -1194,7 +1156,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
int j = 0; /* index for kwdefaults and kwonlyargs */
if (kwonlyargs == NULL) {
- ast_error(CHILD(n, start), "named arguments must follow bare *");
+ ast_error(c, CHILD(n, start), "named arguments must follow bare *");
return -1;
}
assert(kwdefaults != NULL);
@@ -1226,7 +1188,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
argname = NEW_IDENTIFIER(ch);
if (!argname)
goto error;
- if (forbidden_name(argname, ch, 0))
+ if (forbidden_name(c, argname, ch, 0))
goto error;
arg = arg(argname, annotation, c->c_arena);
if (!arg)
@@ -1237,7 +1199,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
case DOUBLESTAR:
return i;
default:
- ast_error(ch, "unexpected node");
+ ast_error(c, ch, "unexpected node");
goto error;
}
}
@@ -1329,7 +1291,7 @@ ast_for_arguments(struct compiling *c, const node *n)
return NULL;
if (nposargs + nkwonlyargs > 255) {
- ast_error(n, "more than 255 arguments");
+ ast_error(c, n, "more than 255 arguments");
return NULL;
}
@@ -1357,7 +1319,7 @@ ast_for_arguments(struct compiling *c, const node *n)
found_default = 1;
}
else if (found_default) {
- ast_error(n,
+ ast_error(c, n,
"non-default argument follows default argument");
return NULL;
}
@@ -1369,7 +1331,7 @@ ast_for_arguments(struct compiling *c, const node *n)
break;
case STAR:
if (i+1 >= NCH(n)) {
- ast_error(CHILD(n, i),
+ ast_error(c, CHILD(n, i),
"named arguments must follow bare *");
return NULL;
}
@@ -1386,7 +1348,7 @@ ast_for_arguments(struct compiling *c, const node *n)
vararg = NEW_IDENTIFIER(CHILD(ch, 0));
if (!vararg)
return NULL;
- if (forbidden_name(vararg, CHILD(ch, 0), 0))
+ if (forbidden_name(c, vararg, CHILD(ch, 0), 0))
return NULL;
if (NCH(ch) > 1) {
/* there is an annotation on the vararg */
@@ -1417,7 +1379,7 @@ ast_for_arguments(struct compiling *c, const node *n)
if (!kwargannotation)
return NULL;
}
- if (forbidden_name(kwarg, CHILD(ch, 0), 0))
+ if (forbidden_name(c, kwarg, CHILD(ch, 0), 0))
return NULL;
i += 3;
break;
@@ -1536,7 +1498,7 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
name = NEW_IDENTIFIER(CHILD(n, name_i));
if (!name)
return NULL;
- if (forbidden_name(name, CHILD(n, name_i), 0))
+ if (forbidden_name(c, name, CHILD(n, name_i), 0))
return NULL;
args = ast_for_arguments(c, CHILD(n, name_i + 1));
if (!args)
@@ -1877,10 +1839,10 @@ ast_for_atom(struct compiling *c, const node *n)
char buf[128];
s = _PyUnicode_AsString(errstr);
PyOS_snprintf(buf, sizeof(buf), "(unicode error) %s", s);
- ast_error(n, buf);
+ ast_error(c, n, buf);
Py_DECREF(errstr);
} else {
- ast_error(n, "(unicode error) unknown error");
+ ast_error(c, n, "(unicode error) unknown error");
}
Py_DECREF(type);
Py_DECREF(value);
@@ -2465,14 +2427,14 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
}
}
if (ngens > 1 || (ngens && (nargs || nkeywords))) {
- ast_error(n, "Generator expression must be parenthesized "
+ ast_error(c, n, "Generator expression must be parenthesized "
"if not sole argument");
return NULL;
}
if (nargs + nkeywords + ngens > 255) {
- ast_error(n, "more than 255 arguments");
- return NULL;
+ ast_error(c, n, "more than 255 arguments");
+ return NULL;
}
args = asdl_seq_new(nargs + ngens, c->c_arena);
@@ -2489,12 +2451,12 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
expr_ty e;
if (NCH(ch) == 1) {
if (nkeywords) {
- ast_error(CHILD(ch, 0),
+ ast_error(c, CHILD(ch, 0),
"non-keyword arg after keyword arg");
return NULL;
}
if (vararg) {
- ast_error(CHILD(ch, 0),
+ ast_error(c, CHILD(ch, 0),
"only named arguments may follow *expression");
return NULL;
}
@@ -2524,19 +2486,19 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
* then is very confusing.
*/
if (e->kind == Lambda_kind) {
- ast_error(CHILD(ch, 0), "lambda cannot contain assignment");
+ ast_error(c, CHILD(ch, 0), "lambda cannot contain assignment");
return NULL;
} else if (e->kind != Name_kind) {
- ast_error(CHILD(ch, 0), "keyword can't be an expression");
+ ast_error(c, CHILD(ch, 0), "keyword can't be an expression");
return NULL;
- } else if (forbidden_name(e->v.Name.id, ch, 1)) {
+ } else if (forbidden_name(c, e->v.Name.id, ch, 1)) {
return NULL;
}
key = e->v.Name.id;
for (k = 0; k < nkeywords; k++) {
tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg;
if (!PyUnicode_Compare(tmp, key)) {
- ast_error(CHILD(ch, 0), "keyword argument repeated");
+ ast_error(c, CHILD(ch, 0), "keyword argument repeated");
return NULL;
}
}
@@ -2629,7 +2591,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
case Subscript_kind:
break;
default:
- ast_error(ch, "illegal expression for augmented assignment");
+ ast_error(c, ch, "illegal expression for augmented assignment");
return NULL;
}
@@ -2662,7 +2624,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
expr_ty e;
node *ch = CHILD(n, i);
if (TYPE(ch) == yield_expr) {
- ast_error(ch, "assignment to yield expression not possible");
+ ast_error(c, ch, "assignment to yield expression not possible");
return NULL;
}
e = ast_for_testlist(c, ch);
@@ -2809,11 +2771,11 @@ alias_for_import_name(struct compiling *c, const node *n, int store)
str = NEW_IDENTIFIER(str_node);
if (!str)
return NULL;
- if (store && forbidden_name(str, str_node, 0))
+ if (store && forbidden_name(c, str, str_node, 0))
return NULL;
}
else {
- if (forbidden_name(name, name_node, 0))
+ if (forbidden_name(c, name, name_node, 0))
return NULL;
}
return alias(name, str, c->c_arena);
@@ -2832,7 +2794,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store)
a->asname = NEW_IDENTIFIER(asname_node);
if (!a->asname)
return NULL;
- if (forbidden_name(a->asname, asname_node, 0))
+ if (forbidden_name(c, a->asname, asname_node, 0))
return NULL;
return a;
}
@@ -2843,7 +2805,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store)
name = NEW_IDENTIFIER(name_node);
if (!name)
return NULL;
- if (store && forbidden_name(name, name_node, 0))
+ if (store && forbidden_name(c, name, name_node, 0))
return NULL;
return alias(name, NULL, c->c_arena);
}
@@ -2972,13 +2934,13 @@ ast_for_import_stmt(struct compiling *c, const node *n)
n = CHILD(n, idx);
n_children = NCH(n);
if (n_children % 2 == 0) {
- ast_error(n, "trailing comma not allowed without"
+ ast_error(c, n, "trailing comma not allowed without"
" surrounding parentheses");
return NULL;
}
break;
default:
- ast_error(n, "Unexpected node-type in from-import");
+ ast_error(c, n, "Unexpected node-type in from-import");
return NULL;
}
@@ -3384,7 +3346,7 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body)
identifier e = NEW_IDENTIFIER(CHILD(exc, 3));
if (!e)
return NULL;
- if (forbidden_name(e, CHILD(exc, 3), 0))
+ if (forbidden_name(c, e, CHILD(exc, 3), 0))
return NULL;
expression = ast_for_expr(c, CHILD(exc, 1));
if (!expression)
@@ -3443,7 +3405,7 @@ ast_for_try_stmt(struct compiling *c, const node *n)
}
}
else if (TYPE(CHILD(n, nch - 3)) != except_clause) {
- ast_error(n, "malformed 'try' statement");
+ ast_error(c, n, "malformed 'try' statement");
return NULL;
}
@@ -3535,7 +3497,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
classname = NEW_IDENTIFIER(CHILD(n, 1));
if (!classname)
return NULL;
- if (forbidden_name(classname, CHILD(n, 3), 0))
+ if (forbidden_name(c, classname, CHILD(n, 3), 0))
return NULL;
return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq,
LINENO(n), n->n_col_offset, c->c_arena);
@@ -3548,7 +3510,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
classname = NEW_IDENTIFIER(CHILD(n, 1));
if (!classname)
return NULL;
- if (forbidden_name(classname, CHILD(n, 3), 0))
+ if (forbidden_name(c, classname, CHILD(n, 3), 0))
return NULL;
return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq,
LINENO(n), n->n_col_offset, c->c_arena);
@@ -3573,7 +3535,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
classname = NEW_IDENTIFIER(CHILD(n, 1));
if (!classname)
return NULL;
- if (forbidden_name(classname, CHILD(n, 1), 0))
+ if (forbidden_name(c, classname, CHILD(n, 1), 0))
return NULL;
return ClassDef(classname, call->v.Call.args, call->v.Call.keywords,
@@ -3832,10 +3794,10 @@ parsestr(struct compiling *c, const node *n, int *bytesmode)
}
if (*bytesmode) {
/* Disallow non-ascii characters (but not escapes) */
- const char *c;
- for (c = s; *c; c++) {
- if (Py_CHARMASK(*c) >= 0x80) {
- ast_error(n, "bytes can only contain ASCII "
+ const char *ch;
+ for (ch = s; *ch; ch++) {
+ if (Py_CHARMASK(*ch) >= 0x80) {
+ ast_error(c, n, "bytes can only contain ASCII "
"literal characters.");
return NULL;
}
@@ -3883,7 +3845,7 @@ parsestrplus(struct compiling *c, const node *n, int *bytesmode)
if (s == NULL)
goto onError;
if (*bytesmode != subbm) {
- ast_error(n, "cannot mix bytes and nonbytes literals");
+ ast_error(c, n, "cannot mix bytes and nonbytes literals");
goto onError;
}
if (PyBytes_Check(v) && PyBytes_Check(s)) {
diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c
index a263efc..aa62502 100644
--- a/Python/formatter_unicode.c
+++ b/Python/formatter_unicode.c
@@ -1099,7 +1099,7 @@ format_float_internal(PyObject *value,
&locale, 0);
done:
- Py_DECREF(unicode_tmp);
+ Py_XDECREF(unicode_tmp);
free_locale_info(&locale);
return result;
}
diff --git a/setup.py b/setup.py
index 9ddf2e9..d60967a 100644
--- a/setup.py
+++ b/setup.py
@@ -1788,6 +1788,8 @@ class PyBuildExt(build_ext):
mkpath(ffi_builddir)
config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
if (('--host=' in arg) or ('--build=' in arg))]
+ if not self.verbose:
+ config_args.append("-q")
# Pass empty CFLAGS because we'll just append the resulting
# CFLAGS to Python's; -g or -O2 is to be avoided.