Compare commits

...

7 Commits

Author SHA1 Message Date
Serhiy Storchaka 6dffa67b98
[3.8] bpo-26407: Do not mask errors in csv. (GH-20536) (GH-24021)
Unexpected errors in calling the __iter__ method are no longer
masked by TypeError in csv.reader(), csv.writer.writerow() and
csv.writer.writerows().
(cherry picked from commit c88239f864)
2021-01-01 19:42:23 +02:00
Serhiy Storchaka b863607d30
[3.8] bpo-39068: Fix race condition in base64 (GH-17627) (GH-24022)
There was a race condition in base64 in lazy initialization of multiple globals.
(cherry picked from commit 9655434cca)

Co-authored-by: Brandon Stansbury <brandonrstansbury@gmail.com>
2021-01-01 19:41:49 +02:00
Serhiy Storchaka 187785e2fa
[3.8] bpo-36589: Fix the error handling in curses.update_lines_cols(). (GH-12766) (GH-24023)
Return None instead of 1.
(cherry picked from commit 2bc343417a)

Co-authored-by: Zackery Spytz <zspytz@gmail.com>
2021-01-01 19:40:38 +02:00
Serhiy Storchaka 1a544e1dcf
[3.8] bpo-42425: Fix possible leak in initialization of errmap for OSError (GH-23446). (GH-24025)
(cherry picked from commit ed1007c0d7)
2021-01-01 19:40:11 +02:00
Serhiy Storchaka e3a9adba32
[3.8] bpo-42759: Fix equality comparison of Variable and Font in Tkinter (GH-23968) (GH-24026)
Objects which belong to different Tcl interpreters are now always
different, even if they have the same name.
(cherry picked from commit 1df56bc059)
2021-01-01 19:39:36 +02:00
Miss Islington (bot) 02639c3bc6
Bring Python into the new year. (GH-24036)
(cherry picked from commit de6f20a6de)

Co-authored-by: Dong-hee Na <donghee.na@python.org>
2021-01-01 09:28:23 -08:00
Miss Islington (bot) 381f3e4bfd
bpo-42794: Update test_nntplib to use offical group name for testing (GH-24037)
(cherry picked from commit ec3165320e)

Co-authored-by: Dong-hee Na <donghee.na@python.org>
2021-01-01 06:40:18 -08:00
26 changed files with 121 additions and 58 deletions

View File

@ -4,7 +4,7 @@ Copyright
Python and this documentation is:
Copyright © 2001-2020 Python Software Foundation. All rights reserved.
Copyright © 2001-2021 Python Software Foundation. All rights reserved.
Copyright © 2000 BeOpen.com. All rights reserved.

View File

@ -100,7 +100,7 @@ PSF LICENSE AGREEMENT FOR PYTHON |release|
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python |release| alone or in any derivative
version, provided, however, that PSF's License Agreement and PSF's notice of
copyright, i.e., "Copyright © 2001-2020 Python Software Foundation; All Rights
copyright, i.e., "Copyright © 2001-2021 Python Software Foundation; All Rights
Reserved" are retained in Python |release| alone or in any derivative version
prepared by Licensee.

View File

@ -84,7 +84,7 @@ analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.

View File

@ -320,7 +320,7 @@ def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False):
global _a85chars, _a85chars2
# Delay the initialization of tables to not waste memory
# if the function is never called
if _a85chars is None:
if _a85chars2 is None:
_a85chars = [bytes((i,)) for i in range(33, 118)]
_a85chars2 = [(a + b) for a in _a85chars for b in _a85chars]
@ -428,7 +428,7 @@ def b85encode(b, pad=False):
global _b85chars, _b85chars2
# Delay the initialization of tables to not waste memory
# if the function is never called
if _b85chars is None:
if _b85chars2 is None:
_b85chars = [bytes((i,)) for i in _b85alphabet]
_b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
return _85encode(b, _b85chars, _b85chars2, pad)

View File

@ -14,6 +14,12 @@ from itertools import permutations
from textwrap import dedent
from collections import OrderedDict
class BadIterable:
def __iter__(self):
raise OSError
class Test_Csv(unittest.TestCase):
"""
Test the underlying C csv parser in ways that are not appropriate
@ -40,9 +46,15 @@ class Test_Csv(unittest.TestCase):
def test_reader_arg_valid(self):
self._test_arg_valid(csv.reader, [])
self.assertRaises(OSError, csv.reader, BadIterable())
def test_writer_arg_valid(self):
self._test_arg_valid(csv.writer, StringIO())
class BadWriter:
@property
def write(self):
raise OSError
self.assertRaises(OSError, csv.writer, BadWriter())
def _test_default_attrs(self, ctor, *args):
obj = ctor(*args)
@ -141,6 +153,7 @@ class Test_Csv(unittest.TestCase):
self._write_test([None], '""')
self._write_error_test(csv.Error, [None], quoting = csv.QUOTE_NONE)
# Check that exceptions are passed up the chain
self._write_error_test(OSError, BadIterable())
class BadList:
def __len__(self):
return 10;
@ -230,6 +243,12 @@ class Test_Csv(unittest.TestCase):
fileobj.seek(0)
self.assertEqual(fileobj.read(), 'a\r\n""\r\n')
def test_writerows_errors(self):
with TemporaryFile("w+", newline='') as fileobj:
writer = csv.writer(fileobj)
self.assertRaises(TypeError, writer.writerows, None)
self.assertRaises(OSError, writer.writerows, BadIterable())
@support.cpython_only
def test_writerows_legacy_strings(self):
import _testcapi
@ -334,7 +353,6 @@ class Test_Csv(unittest.TestCase):
def test_roundtrip_quoteed_newlines(self):
with TemporaryFile("w+", newline='') as fileobj:
writer = csv.writer(fileobj)
self.assertRaises(TypeError, writer.writerows, None)
rows = [['a\nb','b'],['c','x\r\nd']]
writer.writerows(rows)
fileobj.seek(0)

View File

@ -82,7 +82,7 @@ class NetworkedNNTPTestsMixin:
desc = self.server.description(self.GROUP_NAME)
_check_desc(desc)
# Another sanity check
self.assertIn("Python", desc)
self.assertIn(self.DESC, desc)
# With a pattern
desc = self.server.description(self.GROUP_PAT)
_check_desc(desc)
@ -299,6 +299,7 @@ class NetworkedNNTPTests(NetworkedNNTPTestsMixin, unittest.TestCase):
NNTP_HOST = 'news.trigofacile.com'
GROUP_NAME = 'fr.comp.lang.python'
GROUP_PAT = 'fr.comp.lang.*'
DESC = 'Python'
NNTP_CLASS = NNTP
@ -332,8 +333,11 @@ class NetworkedNNTP_SSLTests(NetworkedNNTPTests):
# 400 connections per day are accepted from each IP address."
NNTP_HOST = 'nntp.aioe.org'
GROUP_NAME = 'comp.lang.python'
GROUP_PAT = 'comp.lang.*'
# bpo-42794: aioe.test is one of the official groups on this server
# used for testing: https://news.aioe.org/manual/aioe-hierarchy/
GROUP_NAME = 'aioe.test'
GROUP_PAT = 'aioe.*'
DESC = 'test'
NNTP_CLASS = getattr(nntplib, 'NNTP_SSL', None)

View File

@ -491,13 +491,11 @@ class Variable:
self._tk.call("trace", "vinfo", self._name))]
def __eq__(self, other):
"""Comparison for equality (==).
Note: if the Variable's master matters to behavior
also compare self._master == other._master
"""
return self.__class__.__name__ == other.__class__.__name__ \
and self._name == other._name
if not isinstance(other, Variable):
return NotImplemented
return (self._name == other._name
and self.__class__.__name__ == other.__class__.__name__
and self._tk == other._tk)
class StringVar(Variable):

View File

@ -100,7 +100,9 @@ class Font:
return self.name
def __eq__(self, other):
return isinstance(other, Font) and self.name == other.name
if not isinstance(other, Font):
return NotImplemented
return self.name == other.name and self._tk == other._tk
def __getitem__(self, key):
return self.cget(key)

View File

@ -63,14 +63,21 @@ class FontTest(AbstractTkTest, unittest.TestCase):
self.assertEqual(self.font.name, fontname)
self.assertEqual(str(self.font), fontname)
def test_eq(self):
def test_equality(self):
font1 = font.Font(root=self.root, name=fontname, exists=True)
font2 = font.Font(root=self.root, name=fontname, exists=True)
self.assertIsNot(font1, font2)
self.assertEqual(font1, font2)
self.assertNotEqual(font1, font1.copy())
self.assertNotEqual(font1, 0)
root2 = tkinter.Tk()
self.addCleanup(root2.destroy)
font3 = font.Font(root=root2, name=fontname, exists=True)
self.assertEqual(str(font1), str(font3))
self.assertNotEqual(font1, font3)
def test_measure(self):
self.assertIsInstance(self.font.measure('abc'), int)

View File

@ -1,6 +1,7 @@
import unittest
import gc
import tkinter
from test.support import ALWAYS_EQ
from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
TclError)
from tkinter.test.support import AbstractDefaultRootTest
@ -57,15 +58,30 @@ class TestVariable(TestBase):
del v2
self.assertFalse(self.info_exists("name"))
def test___eq__(self):
def test_equality(self):
# values doesn't matter, only class and name are checked
v1 = Variable(self.root, name="abc")
v2 = Variable(self.root, name="abc")
self.assertEqual(v1, v2)
v3 = Variable(self.root, name="abc")
v3 = Variable(self.root, name="cba")
self.assertNotEqual(v1, v3)
v4 = StringVar(self.root, name="abc")
self.assertNotEqual(v3, v4)
self.assertEqual(str(v1), str(v4))
self.assertNotEqual(v1, v4)
V = type('Variable', (), {})
self.assertNotEqual(v1, V())
self.assertNotEqual(v1, object())
self.assertEqual(v1, ALWAYS_EQ)
root2 = tkinter.Tk()
self.addCleanup(root2.destroy)
v5 = Variable(root2, name="abc")
self.assertEqual(str(v1), str(v5))
self.assertNotEqual(v1, v5)
def test_invalid_name(self):
with self.assertRaises(TypeError):

View File

@ -36,7 +36,7 @@
<key>CFBundleExecutable</key>
<string>IDLE</string>
<key>CFBundleGetInfoString</key>
<string>%version%, © 2001-2020 Python Software Foundation</string>
<string>%version%, © 2001-2021 Python Software Foundation</string>
<key>CFBundleIconFile</key>
<string>IDLE.icns</string>
<key>CFBundleIdentifier</key>

View File

@ -40,7 +40,7 @@
<key>CFBundleExecutable</key>
<string>Python Launcher</string>
<key>CFBundleGetInfoString</key>
<string>%VERSION%, © 2001-2020 Python Software Foundation</string>
<string>%VERSION%, © 2001-2021 Python Software Foundation</string>
<key>CFBundleIconFile</key>
<string>PythonLauncher.icns</string>
<key>CFBundleIdentifier</key>

View File

@ -37,7 +37,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>%version%, (c) 2001-2020 Python Software Foundation.</string>
<string>%version%, (c) 2001-2021 Python Software Foundation.</string>
<key>CFBundleName</key>
<string>Python</string>
<key>CFBundlePackageType</key>

View File

@ -1607,6 +1607,7 @@ Tage Stabell-Kulo
Quentin Stafford-Fraser
Frank Stajano
Joel Stanley
Brandon Stansbury
Anthony Starks
David Steele
Oliver Steele

View File

@ -0,0 +1,2 @@
The :func:`curses.update_lines_cols` function now returns ``None`` instead
of ``1`` on success.

View File

@ -0,0 +1,2 @@
Fix initialization race condition in :func:`a85encode` and :func:`b85encode`
in :mod:`base64`. Patch by Brandon Stansbury.

View File

@ -0,0 +1,3 @@
Unexpected errors in calling the ``__iter__`` method are no longer masked
by ``TypeError`` in :func:`csv.reader`, :func:`csv.writer.writerow` and
:meth:`csv.writer.writerows`.

View File

@ -0,0 +1,3 @@
Fixed equality comparison of :class:`tkinter.Variable` and
:class:`tkinter.font.Font`. Objects which belong to different Tcl
interpreters are now always different, even if they have the same name.

View File

@ -0,0 +1,2 @@
Update test_nntplib to use offical group name of news.aioe.org for testing.
Patch by Dong-hee Na.

View File

@ -958,8 +958,6 @@ csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args)
}
self->input_iter = PyObject_GetIter(iterator);
if (self->input_iter == NULL) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must be an iterator");
Py_DECREF(self);
return NULL;
}
@ -1165,10 +1163,14 @@ csv_writerow(WriterObj *self, PyObject *seq)
PyObject *iter, *field, *line, *result;
iter = PyObject_GetIter(seq);
if (iter == NULL)
return PyErr_Format(_csvstate_global->error_obj,
if (iter == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Format(_csvstate_global->error_obj,
"iterable expected, not %.200s",
seq->ob_type->tp_name);
Py_TYPE(seq)->tp_name);
}
return NULL;
}
/* Join all fields in internal buffer.
*/
@ -1258,8 +1260,6 @@ csv_writerows(WriterObj *self, PyObject *seqseq)
row_iter = PyObject_GetIter(seqseq);
if (row_iter == NULL) {
PyErr_SetString(PyExc_TypeError,
"writerows() argument must be iterable");
return NULL;
}
while ((row_obj = PyIter_Next(row_iter))) {

View File

@ -3757,15 +3757,18 @@ update_lines_cols(void)
}
/*[clinic input]
_curses.update_lines_cols -> int
_curses.update_lines_cols
[clinic start generated code]*/
static int
static PyObject *
_curses_update_lines_cols_impl(PyObject *module)
/*[clinic end generated code: output=0345e7f072ea711a input=3a87760f7d5197f0]*/
/*[clinic end generated code: output=423f2b1e63ed0f75 input=5f065ab7a28a5d90]*/
{
return update_lines_cols();
if (!update_lines_cols()) {
return NULL;
}
Py_RETURN_NONE;
}
#endif
@ -3849,8 +3852,10 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols)
result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm");
if (!result)
return NULL;
if (!update_lines_cols())
if (!update_lines_cols()) {
Py_DECREF(result);
return NULL;
}
return result;
}
@ -3886,8 +3891,10 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols)
result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term");
if (!result)
return NULL;
if (!update_lines_cols())
if (!update_lines_cols()) {
Py_DECREF(result);
return NULL;
}
return result;
}
#endif /* HAVE_CURSES_RESIZE_TERM */
@ -3958,12 +3965,18 @@ _curses_start_color_impl(PyObject *module)
c = PyLong_FromLong((long) COLORS);
if (c == NULL)
return NULL;
PyDict_SetItemString(ModDict, "COLORS", c);
if (PyDict_SetItemString(ModDict, "COLORS", c) < 0) {
Py_DECREF(c);
return NULL;
}
Py_DECREF(c);
cp = PyLong_FromLong((long) COLOR_PAIRS);
if (cp == NULL)
return NULL;
PyDict_SetItemString(ModDict, "COLOR_PAIRS", cp);
if (PyDict_SetItemString(ModDict, "COLOR_PAIRS", cp) < 0) {
Py_DECREF(cp);
return NULL;
}
Py_DECREF(cp);
Py_RETURN_NONE;
} else {

View File

@ -3799,23 +3799,13 @@ PyDoc_STRVAR(_curses_update_lines_cols__doc__,
#define _CURSES_UPDATE_LINES_COLS_METHODDEF \
{"update_lines_cols", (PyCFunction)_curses_update_lines_cols, METH_NOARGS, _curses_update_lines_cols__doc__},
static int
static PyObject *
_curses_update_lines_cols_impl(PyObject *module);
static PyObject *
_curses_update_lines_cols(PyObject *module, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
int _return_value;
_return_value = _curses_update_lines_cols_impl(module);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromLong((long)_return_value);
exit:
return return_value;
return _curses_update_lines_cols_impl(module);
}
#endif /* (defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)) */
@ -4569,4 +4559,4 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored))
#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
#define _CURSES_USE_DEFAULT_COLORS_METHODDEF
#endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */
/*[clinic end generated code: output=e5b3502f1d38dff0 input=a9049054013a1b77]*/
/*[clinic end generated code: output=820af7050893ed16 input=a9049054013a1b77]*/

View File

@ -2518,8 +2518,10 @@ _PyExc_Init(void)
do { \
PyObject *_code = PyLong_FromLong(CODE); \
assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) \
if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) { \
Py_XDECREF(_code); \
return _PyStatus_ERR("errmap insertion problem."); \
} \
Py_DECREF(_code); \
} while (0)

View File

@ -5,7 +5,7 @@
#include "winver.h"
#define PYTHON_COMPANY "Python Software Foundation"
#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2016 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC."
#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2021 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC."
#define MS_WINDOWS
#include "modsupport.h"

View File

@ -4,7 +4,7 @@
static const char cprt[] =
"\
Copyright (c) 2001-2020 Python Software Foundation.\n\
Copyright (c) 2001-2021 Python Software Foundation.\n\
All Rights Reserved.\n\
\n\
Copyright (c) 2000 BeOpen.com.\n\

View File

@ -18,7 +18,7 @@ This is Python version 3.8.7
:target: https://python.zulipchat.com
Copyright (c) 2001-2020 Python Software Foundation. All rights reserved.
Copyright (c) 2001-2021 Python Software Foundation. All rights reserved.
See the end of this file for further copyright and license information.
@ -246,7 +246,7 @@ See :pep:`569` for Python 3.8 release details.
Copyright and License Information
---------------------------------
Copyright (c) 2001-2020 Python Software Foundation. All rights reserved.
Copyright (c) 2001-2021 Python Software Foundation. All rights reserved.
Copyright (c) 2000 BeOpen.com. All rights reserved.