Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Doc/library/mmap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
Writable :term:`bytes-like object` is now accepted.


.. method:: flush()
flush(offset, size, /)
.. method:: flush([offset[, size]])

Flushes changes made to the in-memory copy of a file back to disk. Without
use of this call there is no guarantee that changes are written back before
Expand All @@ -230,6 +229,12 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
on error under Windows. A zero value was returned on success; an
exception was raised on error under Unix.

.. versionchanged:: next
Allow specifying *offset* without *size*. Previously, both *offset*
and *size* parameters were required together. Now *offset* can be
specified alone, and the flush operation will extend from *offset*
to the end of the mmap.


.. method:: madvise(option[, start[, length]])

Expand Down
6 changes: 6 additions & 0 deletions Doc/library/sqlite3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,9 @@ Cursor objects
If the *size* parameter is used, then it is best for it to retain the same
value from one :meth:`fetchmany` call to the next.

.. versionchanged:: next
Negative *size* values are rejected by raising :exc:`ValueError`.

.. method:: fetchall()

Return all (remaining) rows of a query result as a :class:`list`.
Expand Down Expand Up @@ -1638,6 +1641,9 @@ Cursor objects
Read/write attribute that controls the number of rows returned by :meth:`fetchmany`.
The default value is 1 which means a single row would be fetched per call.

.. versionchanged:: next
Negative values are rejected by raising :exc:`ValueError`.

.. attribute:: connection

Read-only attribute that provides the SQLite database :class:`Connection`
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_mmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,18 @@ def test_access_violations(self):
self.assertEqual(stdout.strip(), b'')
self.assertEqual(stderr.strip(), b'')

def test_flush_parameters(self):
with open(TESTFN, 'wb+') as f:
f.write(b'x' * PAGESIZE * 3)
f.flush()

m = mmap.mmap(f.fileno(), PAGESIZE * 3)
self.addCleanup(m.close)

m.flush()
m.flush(PAGESIZE)
m.flush(PAGESIZE, PAGESIZE)


class LargeMmapTests(unittest.TestCase):

Expand Down
102 changes: 95 additions & 7 deletions Lib/test/test_source_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ def test_tokenizer_fstring_warning_in_first_line(self):
os.unlink(TESTFN)


BUFSIZ = 2**13

class AbstractSourceEncodingTest:

def test_default_coding(self):
Expand All @@ -184,14 +186,20 @@ def test_first_coding_line(self):
self.check_script_output(src, br"'\xc3\u20ac'")

def test_second_coding_line(self):
src = (b'#\n'
src = (b'#!/usr/bin/python\n'
b'#coding:iso8859-15\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_second_coding_line_empty_first_line(self):
src = (b'\n'
b'#coding:iso8859-15\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_third_coding_line(self):
# Only first two lines are tested for a magic comment.
src = (b'#\n'
src = (b'#!/usr/bin/python\n'
b'#\n'
b'#coding:iso8859-15\n'
b'print(ascii("\xc3\xa4"))\n')
Expand All @@ -209,13 +217,52 @@ def test_double_coding_same_line(self):
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_double_coding_utf8(self):
src = (b'#coding:utf-8\n'
b'#coding:latin1\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xe4'")

def test_long_first_coding_line(self):
src = (b'#' + b' '*BUFSIZ + b'coding:iso8859-15\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_long_second_coding_line(self):
src = (b'#!/usr/bin/python\n'
b'#' + b' '*BUFSIZ + b'coding:iso8859-15\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_long_coding_line(self):
src = (b'#coding:iso-8859-15' + b' '*BUFSIZ + b'\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_long_coding_name(self):
src = (b'#coding:iso-8859-1-' + b'x'*BUFSIZ + b'\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\xa4'")

def test_long_first_utf8_line(self):
src = b'#' + b'\xc3\xa4'*(BUFSIZ//2) + b'\n'
self.check_script_output(src, b'')
src = b'# ' + b'\xc3\xa4'*(BUFSIZ//2) + b'\n'
self.check_script_output(src, b'')

def test_long_second_utf8_line(self):
src = b'\n#' + b'\xc3\xa4'*(BUFSIZ//2) + b'\n'
self.check_script_output(src, b'')
src = b'\n# ' + b'\xc3\xa4'*(BUFSIZ//2) + b'\n'
self.check_script_output(src, b'')

def test_first_non_utf8_coding_line(self):
src = (b'#coding:iso-8859-15 \xa4\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")

def test_second_non_utf8_coding_line(self):
src = (b'\n'
src = (b'#!/usr/bin/python\n'
b'#coding:iso-8859-15 \xa4\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xc3\u20ac'")
Expand All @@ -224,27 +271,56 @@ def test_utf8_bom(self):
src = (b'\xef\xbb\xbfprint(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xe4'")

def test_utf8_bom_utf8_comments(self):
src = (b'\xef\xbb\xbf#\xc3\xa4\n'
b'#\xc3\xa4\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xe4'")

def test_utf8_bom_and_utf8_coding_line(self):
src = (b'\xef\xbb\xbf#coding:utf-8\n'
b'print(ascii("\xc3\xa4"))\n')
self.check_script_output(src, br"'\xe4'")

def test_utf8_non_utf8_comment_line_error(self):
src = (b'#coding: utf8\n'
b'#\n'
b'#\xa4\n'
b'raise RuntimeError\n')
self.check_script_error(src,
br"'utf-8' codec can't decode byte|"
br"encoding problem: utf8")

def test_crlf(self):
src = (b'print(ascii("""\r\n"""))\n')
out = self.check_script_output(src, br"'\n'")
self.check_script_output(src, br"'\n'")

def test_crcrlf(self):
src = (b'print(ascii("""\r\r\n"""))\n')
out = self.check_script_output(src, br"'\n\n'")
self.check_script_output(src, br"'\n\n'")

def test_crcrcrlf(self):
src = (b'print(ascii("""\r\r\r\n"""))\n')
out = self.check_script_output(src, br"'\n\n\n'")
self.check_script_output(src, br"'\n\n\n'")

def test_crcrcrlf2(self):
src = (b'#coding:iso-8859-1\n'
b'print(ascii("""\r\r\r\n"""))\n')
out = self.check_script_output(src, br"'\n\n\n'")
self.check_script_output(src, br"'\n\n\n'")

def test_nul_in_first_coding_line(self):
src = (b'#coding:iso8859-15\x00\n'
b'\n'
b'\n'
b'raise RuntimeError\n')
self.check_script_error(src, br"source code (string )?cannot contain null bytes")

def test_nul_in_second_coding_line(self):
src = (b'#!/usr/bin/python\n'
b'#coding:iso8859-15\x00\n'
b'\n'
b'raise RuntimeError\n')
self.check_script_error(src, br"source code (string )?cannot contain null bytes")


class UTF8ValidatorTest(unittest.TestCase):
Expand Down Expand Up @@ -324,6 +400,10 @@ def check_script_output(self, src, expected):
out = stdout.getvalue().encode('latin1')
self.assertEqual(out.rstrip(), expected)

def check_script_error(self, src, expected):
with self.assertRaisesRegex(SyntaxError, expected.decode()) as cm:
exec(src)


class FileSourceEncodingTest(AbstractSourceEncodingTest, unittest.TestCase):

Expand All @@ -335,6 +415,14 @@ def check_script_output(self, src, expected):
res = script_helper.assert_python_ok(fn)
self.assertEqual(res.out.rstrip(), expected)

def check_script_error(self, src, expected):
with tempfile.TemporaryDirectory() as tmpd:
fn = os.path.join(tmpd, 'test.py')
with open(fn, 'wb') as fp:
fp.write(src)
res = script_helper.assert_python_failure(fn)
self.assertRegex(res.err.rstrip().splitlines()[-1], b'SyntaxError.*?' + expected)


if __name__ == "__main__":
unittest.main()
40 changes: 39 additions & 1 deletion Lib/test/test_sqlite3/test_dbapi.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 contextlib
import functools
import os
import sqlite3 as sqlite
import subprocess
Expand Down Expand Up @@ -1060,7 +1061,7 @@ def test_array_size(self):
# now set to 2
self.cu.arraysize = 2

# now make the query return 3 rows
# now make the query return 2 rows from a table of 3 rows
self.cu.execute("delete from test")
self.cu.execute("insert into test(name) values ('A')")
self.cu.execute("insert into test(name) values ('B')")
Expand All @@ -1070,13 +1071,50 @@ def test_array_size(self):

self.assertEqual(len(res), 2)

def test_invalid_array_size(self):
UINT32_MAX = (1 << 32) - 1
setter = functools.partial(setattr, self.cu, 'arraysize')

self.assertRaises(TypeError, setter, 1.0)
self.assertRaises(ValueError, setter, -3)
self.assertRaises(OverflowError, setter, UINT32_MAX + 1)

def test_fetchmany(self):
# no active SQL statement
res = self.cu.fetchmany()
self.assertEqual(res, [])
res = self.cu.fetchmany(1000)
self.assertEqual(res, [])

# test default parameter
self.cu.execute("select name from test")
res = self.cu.fetchmany()
self.assertEqual(len(res), 1)

# test when the number of requested rows exceeds the actual count
self.cu.execute("select name from test")
res = self.cu.fetchmany(100)
self.assertEqual(len(res), 1)
res = self.cu.fetchmany(100)
self.assertEqual(res, [])

# test when size = 0
self.cu.execute("select name from test")
res = self.cu.fetchmany(0)
self.assertEqual(res, [])
res = self.cu.fetchmany(100)
self.assertEqual(len(res), 1)
res = self.cu.fetchmany(100)
self.assertEqual(res, [])

def test_invalid_fetchmany(self):
UINT32_MAX = (1 << 32) - 1
fetchmany = self.cu.fetchmany

self.assertRaises(TypeError, fetchmany, 1.0)
self.assertRaises(ValueError, fetchmany, -3)
self.assertRaises(OverflowError, fetchmany, UINT32_MAX + 1)

def test_fetchmany_kw_arg(self):
"""Checks if fetchmany works with keyword arguments"""
self.cu.execute("select name from test")
Expand Down
Loading
Loading