diff options
-rw-r--r-- | .bzrignore | 1 | ||||
-rw-r--r-- | .hgignore | 1 | ||||
-rw-r--r-- | Doc/howto/urllib2.rst | 2 | ||||
-rw-r--r-- | Doc/library/cgi.rst | 15 | ||||
-rw-r--r-- | Doc/library/itertools.rst | 4 | ||||
-rw-r--r-- | Lib/_pyio.py | 4 | ||||
-rw-r--r-- | Lib/test/test_asynchat.py | 2 | ||||
-rw-r--r-- | Lib/test/test_curses.py | 11 | ||||
-rw-r--r-- | Lib/test/test_mailbox.py | 125 | ||||
-rw-r--r-- | Lib/test/test_memoryio.py | 15 | ||||
-rw-r--r-- | Lib/test/test_scope.py | 15 | ||||
-rw-r--r-- | Modules/_io/bytesio.c | 8 | ||||
-rw-r--r-- | Modules/_io/stringio.c | 39 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 4 | ||||
-rw-r--r-- | Python/peephole.c | 15 |
15 files changed, 149 insertions, 112 deletions
@@ -37,6 +37,7 @@ TAGS .gdb_history Doc/tools/sphinx Doc/tools/jinja +Doc/tools/jinja2 Doc/tools/pygments Doc/tools/docutils Misc/python.pc @@ -39,6 +39,7 @@ Lib/plat-mac/errors.rsrc.df.rsrc Doc/tools/sphinx/ Doc/tools/docutils/ Doc/tools/jinja/ +Doc/tools/jinja2/ Doc/tools/pygments/ Misc/python.pc Modules/Setup diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 51978fc..fb5b1c3 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -492,7 +492,7 @@ than the URL you pass to .add_password() will also match. :: .. note:: - In the above example we only supplied our ``HHTPBasicAuthHandler`` to + In the above example we only supplied our ``HTTPBasicAuthHandler`` to ``build_opener``. By default openers have the handlers for normal situations -- ``ProxyHandler``, ``UnknownHandler``, ``HTTPHandler``, ``HTTPDefaultErrorHandler``, ``HTTPRedirectHandler``, ``FTPHandler``, diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst index 55f6509..03dfe2d 100644 --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -88,12 +88,13 @@ input or the environment (depending on the value of various environment variables set according to the CGI standard). Since it may consume standard input, it should be instantiated only once. -The :class:`FieldStorage` instance can be indexed like a Python dictionary, and -also supports the standard dictionary methods :meth:`__contains__` and -:meth:`keys`. The built-in :func:`len` is also supported. Form fields -containing empty strings are ignored and do not appear in the dictionary; to -keep such values, provide a true value for the optional *keep_blank_values* -keyword parameter when creating the :class:`FieldStorage` instance. +The :class:`FieldStorage` instance can be indexed like a Python dictionary. +It allows membership testing with the :keyword:`in` operator, and also supports +the standard dictionary method :meth:`keys` and the built-in function +:func:`len`. Form fields containing empty strings are ignored and do not appear +in the dictionary; to keep such values, provide a true value for the optional +*keep_blank_values* keyword parameter when creating the :class:`FieldStorage` +instance. For instance, the following code (which assumes that the :mailheader:`Content-Type` header and blank line have already been printed) @@ -101,7 +102,7 @@ checks that the fields ``name`` and ``addr`` are both set to a non-empty string:: form = cgi.FieldStorage() - if not ("name" in form and "addr" in form): + if "name" not in form or "addr" not in form: print("<H1>Error</H1>") print("Please fill in the name and addr fields.") return diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index ac3b761..c1f8d9a 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -49,13 +49,13 @@ Iterator Arguments Results :func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') --> A B C D E F`` :func:`compress` data, selectors (d[0] if s[0]), (d[1] if s[1]), ... ``compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F`` :func:`dropwhile` pred, seq seq[n], seq[n+1], starting when pred fails ``dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1`` -:func:`filterfalse` pred, seq elements of seq where pred(elem) is False ``ifilterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8`` +:func:`filterfalse` pred, seq elements of seq where pred(elem) is False ``filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8`` :func:`groupby` iterable[, keyfunc] sub-iterators grouped by value of keyfunc(v) :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) --> C D E F G`` :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000`` :func:`takewhile` pred, seq seq[0], seq[1], until pred fails ``takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4`` :func:`tee` it, n it1, it2 , ... itn splits one iterator into n -:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-`` +:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-`` ==================== ============================ ================================================= ============================================================= **Combinatoric generators:** diff --git a/Lib/_pyio.py b/Lib/_pyio.py index bbf65bc..5458f99 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -1924,8 +1924,10 @@ class StringIO(TextIOWrapper): # C version, even under Windows. if newline is None: self._writetranslate = False - if initial_value: + if initial_value is not None: if not isinstance(initial_value, str): + raise TypeError("initial_value must be str or None, not {0}" + .format(type(initial_value).__name__)) initial_value = str(initial_value) self.write(initial_value) self.seek(0) diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py index 3da5878..f49701f 100644 --- a/Lib/test/test_asynchat.py +++ b/Lib/test/test_asynchat.py @@ -214,7 +214,7 @@ class TestAsynchat(unittest.TestCase): # the server might have been able to send a byte or two back, but this # at least checks that it received something and didn't just fail # (which could still result in the client not having received anything) - self.assertTrue(len(s.buffer) > 0) + self.assertGreater(len(s.buffer), 0) class TestAsynchat_WithPoll(TestAsynchat): diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index bf60daa..4be2029 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -269,16 +269,17 @@ def main(stdscr): finally: curses.resetty() -if __name__ == '__main__': - curses.wrapper(main) - unit_tests() -else: +def test_main(): # testing setupterm() inside initscr/endwin # causes terminal breakage - curses.setupterm(fd=sys.__stdout__.fileno()) + curses.setupterm(fd=sys.stdout.fileno()) try: stdscr = curses.initscr() main(stdscr) finally: curses.endwin() unit_tests() + +if __name__ == '__main__': + curses.wrapper(main) + unit_tests() diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index 8994340..66472d9 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -24,13 +24,13 @@ class TestBase(unittest.TestCase): self.assertTrue(isinstance(msg, email.message.Message)) self.assertTrue(isinstance(msg, mailbox.Message)) for key, value in _sample_headers.items(): - self.assertTrue(value in msg.get_all(key)) + self.assertIn(value, msg.get_all(key)) self.assertTrue(msg.is_multipart()) self.assertEqual(len(msg.get_payload()), len(_sample_payloads)) for i, payload in enumerate(_sample_payloads): part = msg.get_payload(i) self.assertTrue(isinstance(part, email.message.Message)) - self.assertTrue(not isinstance(part, mailbox.Message)) + self.assertFalse(isinstance(part, mailbox.Message)) self.assertEqual(part.get_payload(), payload) def _delete_recursively(self, target): @@ -91,16 +91,14 @@ class TestMailbox(TestBase): key1 = self._box.add(self._template % 1) self.assertEqual(len(self._box), 2) method(key0) - l = len(self._box) - self.assertTrue(l == 1, "actual l: %s" % l) + self.assertEqual(len(self._box), 1) self.assertRaises(KeyError, lambda: self._box[key0]) self.assertRaises(KeyError, lambda: method(key0)) self.assertEqual(self._box.get_string(key1), self._template % 1) key2 = self._box.add(self._template % 2) self.assertEqual(len(self._box), 2) method(key2) - l = len(self._box) - self.assertTrue(l == 1, "actual l: %s" % l) + self.assertEqual(len(self._box), 1) self.assertRaises(KeyError, lambda: self._box[key2]) self.assertRaises(KeyError, lambda: method(key2)) self.assertEqual(self._box.get_string(key1), self._template % 1) @@ -127,8 +125,8 @@ class TestMailbox(TestBase): msg = self._box.get(key0) self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '0') - self.assertTrue(self._box.get('foo') is None) - self.assertTrue(self._box.get('foo', False) is False) + self.assertIs(self._box.get('foo'), None) + self.assertIs(self._box.get('foo', False), False) self._box.close() self._box = self._factory(self._path) key1 = self._box.add(self._template % 1) @@ -228,29 +226,28 @@ class TestMailbox(TestBase): count = 0 for value in returned_values: self.assertEqual(value['from'], 'foo') - self.assertTrue(int(value.get_payload()) < repetitions) + self.assertLess(int(value.get_payload()), repetitions) count += 1 self.assertEqual(len(values), count) def test_contains(self): # Check existence of keys using __contains__() - method = self._box.__contains__ - self.assertTrue(not method('foo')) + self.assertNotIn('foo', self._box) key0 = self._box.add(self._template % 0) - self.assertTrue(method(key0)) - self.assertTrue(not method('foo')) + self.assertIn(key0, self._box) + self.assertNotIn('foo', self._box) key1 = self._box.add(self._template % 1) - self.assertTrue(method(key1)) - self.assertTrue(method(key0)) - self.assertTrue(not method('foo')) + self.assertIn(key1, self._box) + self.assertIn(key0, self._box) + self.assertNotIn('foo', self._box) self._box.remove(key0) - self.assertTrue(not method(key0)) - self.assertTrue(method(key1)) - self.assertTrue(not method('foo')) + self.assertNotIn(key0, self._box) + self.assertIn(key1, self._box) + self.assertNotIn('foo', self._box) self._box.remove(key1) - self.assertTrue(not method(key1)) - self.assertTrue(not method(key0)) - self.assertTrue(not method('foo')) + self.assertNotIn(key1, self._box) + self.assertNotIn(key0, self._box) + self.assertNotIn('foo', self._box) def test_len(self, repetitions=10): # Get message count @@ -297,7 +294,7 @@ class TestMailbox(TestBase): for i in range(iterations): self._box.add(self._template % i) for i, key in enumerate(keys): - self.assertTrue(self._box.get_string(key) == self._template % i) + self.assertEqual(self._box.get_string(key), self._template % i) self._box.clear() self.assertEqual(len(self._box), 0) for i, key in enumerate(keys): @@ -306,19 +303,19 @@ class TestMailbox(TestBase): def test_pop(self): # Get and remove a message using pop() key0 = self._box.add(self._template % 0) - self.assertTrue(key0 in self._box) + self.assertIn(key0, self._box) key1 = self._box.add(self._template % 1) - self.assertTrue(key1 in self._box) + self.assertIn(key1, self._box) self.assertEqual(self._box.pop(key0).get_payload(), '0') - self.assertTrue(key0 not in self._box) - self.assertTrue(key1 in self._box) + self.assertNotIn(key0, self._box) + self.assertIn(key1, self._box) key2 = self._box.add(self._template % 2) - self.assertTrue(key2 in self._box) + self.assertIn(key2, self._box) self.assertEqual(self._box.pop(key2).get_payload(), '2') - self.assertTrue(key2 not in self._box) - self.assertTrue(key1 in self._box) + self.assertNotIn(key2, self._box) + self.assertIn(key1, self._box) self.assertEqual(self._box.pop(key1).get_payload(), '1') - self.assertTrue(key1 not in self._box) + self.assertNotIn(key1, self._box) self.assertEqual(len(self._box), 0) def test_popitem(self, iterations=10): @@ -329,8 +326,8 @@ class TestMailbox(TestBase): seen = [] for i in range(10): key, msg = self._box.popitem() - self.assertTrue(key in keys) - self.assertTrue(key not in seen) + self.assertIn(key, keys) + self.assertNotIn(key, seen) seen.append(key) self.assertEqual(int(msg.get_payload()), keys.index(key)) self.assertEqual(len(self._box), 0) @@ -377,11 +374,11 @@ class TestMailbox(TestBase): def test_lock_unlock(self): # Lock and unlock the mailbox - self.assertTrue(not os.path.exists(self._get_lock_path())) + self.assertFalse(os.path.exists(self._get_lock_path())) self._box.lock() self.assertTrue(os.path.exists(self._get_lock_path())) self._box.unlock() - self.assertTrue(not os.path.exists(self._get_lock_path())) + self.assertFalse(os.path.exists(self._get_lock_path())) def test_close(self): # Close mailbox and flush changes to disk @@ -400,7 +397,7 @@ class TestMailbox(TestBase): keys = self._box.keys() self.assertEqual(len(keys), 3) for key in keys: - self.assertTrue(self._box.get_string(key) in contents) + self.assertIn(self._box.get_string(key), contents) oldbox.close() def test_dump_message(self): @@ -571,7 +568,7 @@ class TestMaildir(TestMailbox): self._box.add_folder('one') self._box.add_folder('two') self.assertEqual(len(self._box.list_folders()), 2) - self.assertTrue(set(self._box.list_folders()) == set(('one', 'two'))) + self.assertEqual(set(self._box.list_folders()), set(('one', 'two'))) self._box.remove_folder('one') self.assertEqual(len(self._box.list_folders()), 1) self.assertEqual(set(self._box.list_folders()), set(('two',))) @@ -602,7 +599,7 @@ class TestMaildir(TestMailbox): os.utime(foo_path, (time.time() - 129600 - 2, foo_stat.st_mtime)) self._box.clean() - self.assertTrue(not os.path.exists(foo_path)) + self.assertFalse(os.path.exists(foo_path)) self.assertTrue(os.path.exists(bar_path)) def test_create_tmp(self, repetitions=10): @@ -623,7 +620,7 @@ class TestMaildir(TestMailbox): "tmp")), "File in wrong location: '%s'" % head) match = pattern.match(tail) - self.assertTrue(match is not None, "Invalid file name: '%s'" % tail) + 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]), @@ -691,10 +688,10 @@ class TestMaildir(TestMailbox): return None box = self._factory(self._path, factory=dummy_factory) folder = box.add_folder('folder1') - self.assertTrue(folder._factory is dummy_factory) + self.assertIs(folder._factory, dummy_factory) folder1_alias = box.get_folder('folder1') - self.assertTrue(folder1_alias._factory is dummy_factory) + self.assertIs(folder1_alias._factory, dummy_factory) def test_directory_in_folder (self): # Test that mailboxes still work if there's a stray extra directory @@ -721,7 +718,7 @@ class TestMaildir(TestMailbox): os.umask(orig_umask) path = os.path.join(self._path, self._box._lookup(key)) mode = os.stat(path).st_mode - self.assertTrue(mode & 0o111 == 0) + self.assertFalse(mode & 0o111) def test_folder_file_perms(self): # From bug #3228, we want to verify that the file created inside a Maildir @@ -802,7 +799,7 @@ class _TestMboxMMDF(TestMailbox): self._box = self._factory(self._path) self.assertEqual(len(self._box), 3) for key in self._box.keys(): - self.assertTrue(self._box.get_string(key) in values) + self.assertIn(self._box.get_string(key), values) self._box.close() self.assertEqual(mtime, os.path.getmtime(self._path)) @@ -920,8 +917,8 @@ class TestMH(TestMailbox): # Test for bug #1569790: verify that folders returned by .get_folder() # use the same factory function. - self.assertTrue(new_folder._factory is self._box._factory) - self.assertTrue(folder0._factory is self._box._factory) + self.assertIs(new_folder._factory, self._box._factory) + self.assertIs(folder0._factory, self._box._factory) def test_add_and_remove_folders(self): # Delete folders @@ -990,7 +987,7 @@ class TestMH(TestMailbox): {'foo':[key0,key1,key3], 'unseen':[key0], 'bar':[key3], 'replied':[key3]}) self._box.pack() - self.assertTrue(self._box.keys() == [1, 2, 3]) + self.assertEqual(self._box.keys(), [1, 2, 3]) key0 = key0 key1 = key0 + 1 key2 = key1 + 1 @@ -1086,7 +1083,7 @@ class TestMessage(TestBase): self.assertTrue(isinstance(msg, mailbox.Message)) self.assertTrue(isinstance(msg, self._factory)) self.assertEqual(msg.keys(), []) - self.assertTrue(not msg.is_multipart()) + self.assertFalse(msg.is_multipart()) self.assertEqual(msg.get_payload(), None) def test_initialize_incorrectly(self): @@ -1159,7 +1156,7 @@ class TestMaildirMessage(TestMessage): def test_date(self): # Use get_date() and set_date() msg = mailbox.MaildirMessage(_sample_message) - self.assertTrue(abs(msg.get_date() - time.time()) < 60) + self.assertLess(abs(msg.get_date() - time.time()), 60) msg.set_date(0.0) self.assertEqual(msg.get_date(), 0.0) @@ -1309,7 +1306,7 @@ class TestBabylMessage(TestMessage): msg = mailbox.BabylMessage(_sample_message) visible = msg.get_visible() self.assertEqual(visible.keys(), []) - self.assertTrue(visible.get_payload() is None) + self.assertIs(visible.get_payload(), None) visible['User-Agent'] = 'FooBar 1.0' visible['X-Whatever'] = 'Blah' self.assertEqual(msg.get_visible().keys(), []) @@ -1318,10 +1315,10 @@ class TestBabylMessage(TestMessage): self.assertTrue(visible.keys() == ['User-Agent', 'X-Whatever']) self.assertTrue(visible['User-Agent'] == 'FooBar 1.0') self.assertEqual(visible['X-Whatever'], 'Blah') - self.assertTrue(visible.get_payload() is None) + self.assertIs(visible.get_payload(), None) msg.update_visible() self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) - self.assertTrue(visible.get_payload() is None) + self.assertIs(visible.get_payload(), None) visible = msg.get_visible() self.assertEqual(visible.keys(), ['User-Agent', 'Date', 'From', 'To', 'Subject']) @@ -1423,7 +1420,7 @@ class TestMessageConversion(TestBase): msg_mboxMMDF.set_flags(setting) msg = mailbox.MaildirMessage(msg_mboxMMDF) self.assertEqual(msg.get_flags(), result) - self.assertTrue(msg.get_date() == 0.0, msg.get_date()) + self.assertEqual(msg.get_date(), 0.0) msg_mboxMMDF.set_flags('O') self.assertEqual(mailbox.MaildirMessage(msg_mboxMMDF).get_subdir(), 'cur') @@ -1822,34 +1819,34 @@ class MaildirTestCase(unittest.TestCase): self.mbox = mailbox.Maildir(support.TESTFN) #self.assertTrue(hasattr(self.mbox, "boxes")) #self.assertEqual(len(self.mbox.boxes), 0) - self.assertTrue(self.mbox.next() is None) - self.assertTrue(self.mbox.next() is None) + self.assertIs(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) def test_nonempty_maildir_cur(self): self.createMessage("cur") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 1) - self.assertTrue(self.mbox.next() is not None) - self.assertTrue(self.mbox.next() is None) - self.assertTrue(self.mbox.next() is None) + self.assertIsNot(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) def test_nonempty_maildir_new(self): self.createMessage("new") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 1) - self.assertTrue(self.mbox.next() is not None) - self.assertTrue(self.mbox.next() is None) - self.assertTrue(self.mbox.next() is None) + self.assertIsNot(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) def test_nonempty_maildir_both(self): self.createMessage("cur") self.createMessage("new") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 2) - self.assertTrue(self.mbox.next() is not None) - self.assertTrue(self.mbox.next() is not None) - self.assertTrue(self.mbox.next() is None) - self.assertTrue(self.mbox.next() is None) + self.assertIsNot(self.mbox.next(), None) + self.assertIsNot(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) + self.assertIs(self.mbox.next(), None) ## End: tests from the original module (for backward compatibility). diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py index 48d5354..07c80436 100644 --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -140,6 +140,7 @@ class MemoryTestMixin: self.assertEqual(memio.getvalue(), buf * 2) memio.__init__(buf) self.assertEqual(memio.getvalue(), buf) + self.assertRaises(TypeError, memio.__init__, []) def test_read(self): buf = self.buftype("1234567890") @@ -338,6 +339,13 @@ class MemoryTestMixin: self.assertEqual(test1(), buf) self.assertEqual(test2(), buf) + def test_instance_dict_leak(self): + # Test case for issue #6242. + # This will be caught by regrtest.py -R if this leak. + for _ in range(100): + memio = self.ioclass() + memio.foo = 1 + class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): @@ -527,6 +535,13 @@ class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): memio = self.ioclass("a\r\nb\r\n", newline=None) self.assertEqual(memio.read(5), "a\nb\n") + def test_newline_argument(self): + self.assertRaises(TypeError, self.ioclass, newline=b"\n") + self.assertRaises(ValueError, self.ioclass, newline="error") + # These should not raise an error + for newline in (None, "", "\n", "\r", "\r\n"): + self.ioclass(newline=newline) + class CBytesIOTest(PyBytesIOTest): ioclass = io.BytesIO diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py index 84ceafa..ef56b88 100644 --- a/Lib/test/test_scope.py +++ b/Lib/test/test_scope.py @@ -272,19 +272,8 @@ def f(): inner() y = 1 - try: - errorInOuter() - except UnboundLocalError: - pass - else: - self.fail() - - try: - errorInInner() - except NameError: - pass - else: - self.fail() + self.assertRaises(UnboundLocalError, errorInOuter) + self.assertRaises(NameError, errorInInner) # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation exec(""" diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index cafe4a2..e3a7849 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -609,11 +609,14 @@ bytesio_close(bytesio *self) static void bytesio_dealloc(bytesio *self) { + _PyObject_GC_UNTRACK(self); if (self->buf != NULL) { PyMem_Free(self->buf); self->buf = NULL; } - Py_TYPE(self)->tp_clear((PyObject *)self); + Py_CLEAR(self->dict); + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); Py_TYPE(self)->tp_free(self); } @@ -669,7 +672,6 @@ static int bytesio_traverse(bytesio *self, visitproc visit, void *arg) { Py_VISIT(self->dict); - Py_VISIT(self->weakreflist); return 0; } @@ -677,8 +679,6 @@ static int bytesio_clear(bytesio *self) { Py_CLEAR(self->dict); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); return 0; } diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 84a15be..bfb099c 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -509,11 +509,15 @@ static void stringio_dealloc(stringio *self) { _PyObject_GC_UNTRACK(self); + self->ok = 0; + if (self->buf) { + PyMem_Free(self->buf); + self->buf = NULL; + } Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); - if (self->buf) - PyMem_Free(self->buf); + Py_CLEAR(self->dict); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); Py_TYPE(self)->tp_free(self); @@ -546,22 +550,42 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"initial_value", "newline", NULL}; PyObject *value = NULL; + PyObject *newline_obj = NULL; char *newline = "\n"; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist, - &value, &newline)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:__init__", kwlist, + &value, &newline_obj)) return -1; + /* Parse the newline argument. This used to be done with the 'z' + specifier, however this allowed any object with the buffer interface to + be converted. Thus we have to parse it manually since we only want to + allow unicode objects or None. */ + if (newline_obj == Py_None) { + newline = NULL; + } + else if (newline_obj) { + if (!PyUnicode_Check(newline_obj)) { + PyErr_Format(PyExc_TypeError, + "newline must be str or None, not %.200s", + Py_TYPE(newline_obj)->tp_name); + return -1; + } + newline = _PyUnicode_AsString(newline_obj); + if (newline == NULL) + return -1; + } + if (newline && newline[0] != '\0' && !(newline[0] == '\n' && newline[1] == '\0') && !(newline[0] == '\r' && newline[1] == '\0') && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) { PyErr_Format(PyExc_ValueError, - "illegal newline value: %s", newline); + "illegal newline value: %R", newline_obj); return -1; } if (value && value != Py_None && !PyUnicode_Check(value)) { - PyErr_Format(PyExc_ValueError, + PyErr_Format(PyExc_TypeError, "initial_value must be str or None, not %.200s", Py_TYPE(value)->tp_name); return -1; @@ -573,6 +597,9 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds) Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); + assert((newline != NULL && newline_obj != Py_None) || + (newline == NULL && newline_obj == Py_None)); + if (newline) { self->readnl = PyUnicode_FromString(newline); if (self->readnl == NULL) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 305289b..758d054 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -2044,7 +2044,7 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s, { PyObject *v; /* It might be possible to tighten this worst case */ - Py_ssize_t allocated = 5 * size; + Py_ssize_t allocated = 8 * size; int inShift = 0; Py_ssize_t i = 0; unsigned int base64bits = 0; @@ -2055,7 +2055,7 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s, if (size == 0) return PyBytes_FromStringAndSize(NULL, 0); - if (allocated / 5 != size) + if (allocated / 8 != size) return PyErr_NoMemory(); v = PyBytes_FromStringAndSize(NULL, allocated); diff --git a/Python/peephole.c b/Python/peephole.c index de1b2ac..0e70183 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -329,7 +329,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Bail out if an exception is set */ if (PyErr_Occurred()) - goto exitUnchanged; + goto exitError; /* Bypass optimization when the lineno table is too complex */ assert(PyBytes_Check(lineno_obj)); @@ -347,7 +347,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Make a modifiable copy of the code string */ codestr = (unsigned char *)PyMem_Malloc(codelen); if (codestr == NULL) - goto exitUnchanged; + goto exitError; codestr = (unsigned char *)memcpy(codestr, PyBytes_AS_STRING(code), codelen); @@ -362,11 +362,11 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Mapping to new jump targets after NOPs are removed */ addrmap = (int *)PyMem_Malloc(codelen * sizeof(int)); if (addrmap == NULL) - goto exitUnchanged; + goto exitError; blocks = markblocks(codestr, codelen); if (blocks == NULL) - goto exitUnchanged; + goto exitError; assert(PyList_Check(consts)); for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) { @@ -412,7 +412,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j)); h = load_global(codestr, i, name, consts); if (h < 0) - goto exitUnchanged; + goto exitError; else if (h == 0) continue; cumlc = lastlc + 1; @@ -664,6 +664,9 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, PyMem_Free(blocks); return code; + exitError: + code = NULL; + exitUnchanged: if (blocks != NULL) PyMem_Free(blocks); @@ -671,6 +674,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, PyMem_Free(addrmap); if (codestr != NULL) PyMem_Free(codestr); - Py_INCREF(code); + Py_XINCREF(code); return code; } |