Skip to content

Commit

Permalink
Sync with 'main' bco. pythonGH-27654
Browse files Browse the repository at this point in the history
  • Loading branch information
Erlend E. Aasland committed Aug 8, 2021
2 parents 3ed9af6 + 2b496e7 commit 476edeb
Show file tree
Hide file tree
Showing 24 changed files with 326 additions and 111 deletions.
4 changes: 0 additions & 4 deletions Doc/bugs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ taken on the bug.
Article which goes into some detail about how to create a useful bug report.
This describes what kind of information is useful and why it is useful.

`Bug Report Writing Guidelines <https://developer.mozilla.org/en-US/docs/Mozilla/QA/Bug_writing_guidelines>`_
Information about writing a good bug report. Some of this is specific to the
Mozilla project, but describes general good practices.

.. _contributing-to-python:

Getting started contributing to Python yourself
Expand Down
34 changes: 23 additions & 11 deletions Doc/library/csv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ The :mod:`csv` module defines the following functions:
:class:`Dialect` class or one of the strings returned by the
:func:`list_dialects` function. The other optional *fmtparams* keyword arguments
can be given to override individual formatting parameters in the current
dialect. For full details about the dialect and formatting parameters, see
section :ref:`csv-fmt-params`. To make it
dialect. For full details about dialects and formatting parameters, see
the :ref:`csv-fmt-params` section. To make it
as easy as possible to interface with modules which implement the DB API, the
value :const:`None` is written as the empty string. While this isn't a
reversible transformation, it makes it easier to dump SQL NULL data values to
Expand All @@ -117,7 +117,7 @@ The :mod:`csv` module defines the following functions:
Associate *dialect* with *name*. *name* must be a string. The
dialect can be specified either by passing a sub-class of :class:`Dialect`, or
by *fmtparams* keyword arguments, or both, with keyword arguments overriding
parameters of the dialect. For full details about the dialect and formatting
parameters of the dialect. For full details about dialects and formatting
parameters, see section :ref:`csv-fmt-params`.


Expand Down Expand Up @@ -225,9 +225,21 @@ The :mod:`csv` module defines the following classes:

.. class:: Dialect

The :class:`Dialect` class is a container class relied on primarily for its
attributes, which are used to define the parameters for a specific
:class:`reader` or :class:`writer` instance.
The :class:`Dialect` class is a container class whose attributes contain
information for how to handle doublequotes, whitespace, delimiters, etc.
Due to the lack of a strict CSV specification, different applications
produce subtly different CSV data. :class:`Dialect` instances define how
:class:`reader` and :class:`writer` instances behave.

All available :class:`Dialect` names are returned by :func:`list_dialects`,
and they can be registered with specific :class:`reader` and :class:`writer`
classes through their initializer (``__init__``) functions like this::

import csv

with open('students.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile, dialect='unix')
^^^^^^^^^^^^^^


.. class:: excel()
Expand Down Expand Up @@ -419,8 +431,8 @@ Reader objects (:class:`DictReader` instances and objects returned by the

Return the next row of the reader's iterable object as a list (if the object
was returned from :func:`reader`) or a dict (if it is a :class:`DictReader`
instance), parsed according to the current dialect. Usually you should call
this as ``next(reader)``.
instance), parsed according to the current :class:`Dialect`. Usually you
should call this as ``next(reader)``.


Reader objects have the following public attributes:
Expand Down Expand Up @@ -460,9 +472,9 @@ read CSV files (assuming they support complex numbers at all).

.. method:: csvwriter.writerow(row)

Write the *row* parameter to the writer's file object, formatted according to
the current dialect. Return the return value of the call to the *write* method
of the underlying file object.
Write the *row* parameter to the writer's file object, formatted according
to the current :class:`Dialect`. Return the return value of the call to the
*write* method of the underlying file object.

.. versionchanged:: 3.5
Added support of arbitrary iterables.
Expand Down
5 changes: 5 additions & 0 deletions Doc/library/errno.rst
Original file line number Diff line number Diff line change
Expand Up @@ -637,3 +637,8 @@ defined by the module. The specific list of defined symbols is available as

Quota exceeded

.. data:: EQFULL

Interface output queue is full

.. versionadded:: 3.11
17 changes: 9 additions & 8 deletions Doc/tutorial/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ For example, the following code will print B, C, D in that order::
Note that if the *except clauses* were reversed (with ``except B`` first), it
would have printed B, B, B --- the first matching *except clause* is triggered.

The last *except clause* may omit the exception name(s), to serve as a wildcard.
Use this with extreme caution, since it is easy to mask a real programming error
in this way! It can also be used to print an error message and then re-raise
the exception (allowing a caller to handle the exception as well)::
All exceptions inherit from :exc:`BaseException`, and so it can be used to serve
as a wildcard. Use this with extreme caution, since it is easy to mask a real
programming error in this way! It can also be used to print an error message and
then re-raise the exception (allowing a caller to handle the exception as well)::

import sys

Expand All @@ -162,10 +162,13 @@ the exception (allowing a caller to handle the exception as well)::
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
except BaseException as err:
print(f"Unexpected {err=}, {type(err)=}")
raise

Alternatively the last except clause may omit the exception name(s), however the exception
value must then be retrieved from ``sys.exc_info()[1]``.

The :keyword:`try` ... :keyword:`except` statement has an optional *else
clause*, which, when present, must follow all *except clauses*. It is useful
for code that must be executed if the *try clause* does not raise an exception.
Expand Down Expand Up @@ -493,5 +496,3 @@ used in a way that ensures they are always cleaned up promptly and correctly. ::
After the statement is executed, the file *f* is always closed, even if a
problem was encountered while processing the lines. Objects which, like files,
provide predefined clean-up actions will indicate this in their documentation.


24 changes: 12 additions & 12 deletions Lib/functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,84 +88,84 @@ def wraps(wrapped,

def _gt_from_lt(self, other, NotImplemented=NotImplemented):
'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).'
op_result = self.__lt__(other)
op_result = type(self).__lt__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result and self != other

def _le_from_lt(self, other, NotImplemented=NotImplemented):
'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).'
op_result = self.__lt__(other)
op_result = type(self).__lt__(self, other)
if op_result is NotImplemented:
return op_result
return op_result or self == other

def _ge_from_lt(self, other, NotImplemented=NotImplemented):
'Return a >= b. Computed by @total_ordering from (not a < b).'
op_result = self.__lt__(other)
op_result = type(self).__lt__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result

def _ge_from_le(self, other, NotImplemented=NotImplemented):
'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).'
op_result = self.__le__(other)
op_result = type(self).__le__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result or self == other

def _lt_from_le(self, other, NotImplemented=NotImplemented):
'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).'
op_result = self.__le__(other)
op_result = type(self).__le__(self, other)
if op_result is NotImplemented:
return op_result
return op_result and self != other

def _gt_from_le(self, other, NotImplemented=NotImplemented):
'Return a > b. Computed by @total_ordering from (not a <= b).'
op_result = self.__le__(other)
op_result = type(self).__le__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result

def _lt_from_gt(self, other, NotImplemented=NotImplemented):
'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).'
op_result = self.__gt__(other)
op_result = type(self).__gt__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result and self != other

def _ge_from_gt(self, other, NotImplemented=NotImplemented):
'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).'
op_result = self.__gt__(other)
op_result = type(self).__gt__(self, other)
if op_result is NotImplemented:
return op_result
return op_result or self == other

def _le_from_gt(self, other, NotImplemented=NotImplemented):
'Return a <= b. Computed by @total_ordering from (not a > b).'
op_result = self.__gt__(other)
op_result = type(self).__gt__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result

def _le_from_ge(self, other, NotImplemented=NotImplemented):
'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).'
op_result = self.__ge__(other)
op_result = type(self).__ge__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result or self == other

def _gt_from_ge(self, other, NotImplemented=NotImplemented):
'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).'
op_result = self.__ge__(other)
op_result = type(self).__ge__(self, other)
if op_result is NotImplemented:
return op_result
return op_result and self != other

def _lt_from_ge(self, other, NotImplemented=NotImplemented):
'Return a < b. Computed by @total_ordering from (not a >= b).'
op_result = self.__ge__(other)
op_result = type(self).__ge__(self, other)
if op_result is NotImplemented:
return op_result
return not op_result
Expand Down
3 changes: 1 addition & 2 deletions Lib/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,7 @@ def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=
dirs.remove('CVS') # don't visit CVS directories
"""
sys.audit("os.fwalk", top, topdown, onerror, follow_symlinks, dir_fd)
if not isinstance(top, int) or not hasattr(top, '__index__'):
top = fspath(top)
top = fspath(top)
# Note: To guard against symlink races, we use the standard
# lstat()/open()/fstat() trick.
if not follow_symlinks:
Expand Down
33 changes: 30 additions & 3 deletions Lib/sqlite3/test/dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import threading
import unittest

from test.support import check_disallow_instantiation, threading_helper
from test.support import check_disallow_instantiation, threading_helper, bigmemtest
from test.support.os_helper import TESTFN, unlink


Expand Down Expand Up @@ -758,9 +758,35 @@ def test_script_error_normal(self):
def test_cursor_executescript_as_bytes(self):
con = sqlite.connect(":memory:")
cur = con.cursor()
with self.assertRaises(ValueError) as cm:
with self.assertRaises(TypeError):
cur.executescript(b"create table test(foo); insert into test(foo) values (5);")
self.assertEqual(str(cm.exception), 'script argument must be unicode.')

def test_cursor_executescript_with_null_characters(self):
con = sqlite.connect(":memory:")
cur = con.cursor()
with self.assertRaises(ValueError):
cur.executescript("""
create table a(i);\0
insert into a(i) values (5);
""")

def test_cursor_executescript_with_surrogates(self):
con = sqlite.connect(":memory:")
cur = con.cursor()
with self.assertRaises(UnicodeEncodeError):
cur.executescript("""
create table a(s);
insert into a(s) values ('\ud8ff');
""")

@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
@bigmemtest(size=2**31, memuse=3, dry_run=False)
def test_cursor_executescript_too_large_script(self, maxsize):
con = sqlite.connect(":memory:")
cur = con.cursor()
for size in 2**31-1, 2**31:
with self.assertRaises(sqlite.DataError):
cur.executescript("create table a(s);".ljust(size))

def test_connection_execute(self):
con = sqlite.connect(":memory:")
Expand Down Expand Up @@ -969,6 +995,7 @@ def suite():
CursorTests,
ExtensionTests,
ModuleTests,
OpenTests,
SqliteOnConflictTests,
ThreadTests,
UninitialisedConnectionTests,
Expand Down
29 changes: 27 additions & 2 deletions Lib/sqlite3/test/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import sqlite3 as sqlite

from test.support.os_helper import TESTFN, unlink

from .userfunctions import with_tracebacks

class CollationTests(unittest.TestCase):
def test_create_collation_not_string(self):
Expand Down Expand Up @@ -145,7 +145,6 @@ def progress():
""")
self.assertTrue(progress_calls)


def test_opcode_count(self):
"""
Test that the opcode argument is respected.
Expand Down Expand Up @@ -198,6 +197,32 @@ def progress():
con.execute("select 1 union select 2 union select 3").fetchall()
self.assertEqual(action, 0, "progress handler was not cleared")

@with_tracebacks(['bad_progress', 'ZeroDivisionError'])
def test_error_in_progress_handler(self):
con = sqlite.connect(":memory:")
def bad_progress():
1 / 0
con.set_progress_handler(bad_progress, 1)
with self.assertRaises(sqlite.OperationalError):
con.execute("""
create table foo(a, b)
""")

@with_tracebacks(['__bool__', 'ZeroDivisionError'])
def test_error_in_progress_handler_result(self):
con = sqlite.connect(":memory:")
class BadBool:
def __bool__(self):
1 / 0
def bad_progress():
return BadBool()
con.set_progress_handler(bad_progress, 1)
with self.assertRaises(sqlite.OperationalError):
con.execute("""
create table foo(a, b)
""")


class TraceCallbackTests(unittest.TestCase):
def test_trace_callback_used(self):
"""
Expand Down
23 changes: 22 additions & 1 deletion Lib/sqlite3/test/regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# 3. This notice may not be removed or altered from any source distribution.

import datetime
import sys
import unittest
import sqlite3 as sqlite
import weakref
Expand Down Expand Up @@ -273,7 +274,7 @@ def test_connection_call(self):
Call a connection with a non-string SQL request: check error handling
of the statement constructor.
"""
self.assertRaises(TypeError, self.con, 1)
self.assertRaises(TypeError, self.con, b"select 1")

def test_collation(self):
def collation_cb(a, b):
Expand Down Expand Up @@ -344,6 +345,26 @@ def test_null_character(self):
self.assertRaises(ValueError, cur.execute, " \0select 2")
self.assertRaises(ValueError, cur.execute, "select 2\0")

def test_surrogates(self):
con = sqlite.connect(":memory:")
self.assertRaises(UnicodeEncodeError, con, "select '\ud8ff'")
self.assertRaises(UnicodeEncodeError, con, "select '\udcff'")
cur = con.cursor()
self.assertRaises(UnicodeEncodeError, cur.execute, "select '\ud8ff'")
self.assertRaises(UnicodeEncodeError, cur.execute, "select '\udcff'")

@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
@support.bigmemtest(size=2**31, memuse=4, dry_run=False)
def test_large_sql(self, maxsize):
# Test two cases: size+1 > INT_MAX and size+1 <= INT_MAX.
for size in (2**31, 2**31-2):
con = sqlite.connect(":memory:")
sql = "select 1".ljust(size)
self.assertRaises(sqlite.DataError, con, sql)
cur = con.cursor()
self.assertRaises(sqlite.DataError, cur.execute, sql)
del sql

def test_commit_cursor_reset(self):
"""
Connection.commit() did reset cursors, which made sqlite3
Expand Down
Loading

0 comments on commit 476edeb

Please sign in to comment.