Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 09b4161

Browse files
committed
Merge branch 'main' into shared-testcase
2 parents 111f873 + 23dcea5 commit 09b4161

File tree

13 files changed

+188
-35
lines changed

13 files changed

+188
-35
lines changed

Doc/library/shutil.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ Directory and files operations
286286
.. versionadded:: 3.8
287287
The *dirs_exist_ok* parameter.
288288

289-
.. function:: rmtree(path, ignore_errors=False, onerror=None)
289+
.. function:: rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None)
290290

291291
.. index:: single: directory; deleting
292292

@@ -296,6 +296,9 @@ Directory and files operations
296296
handled by calling a handler specified by *onerror* or, if that is omitted,
297297
they raise an exception.
298298

299+
This function can support :ref:`paths relative to directory descriptors
300+
<dir_fd>`.
301+
299302
.. note::
300303

301304
On platforms that support the necessary fd-based functions a symlink
@@ -315,7 +318,7 @@ Directory and files operations
315318
*excinfo*, will be the exception information returned by
316319
:func:`sys.exc_info`. Exceptions raised by *onerror* will not be caught.
317320

318-
.. audit-event:: shutil.rmtree path shutil.rmtree
321+
.. audit-event:: shutil.rmtree path,dir_fd shutil.rmtree
319322

320323
.. versionchanged:: 3.3
321324
Added a symlink attack resistant version that is used automatically
@@ -325,6 +328,9 @@ Directory and files operations
325328
On Windows, will no longer delete the contents of a directory junction
326329
before removing the junction.
327330

331+
.. versionchanged:: 3.11
332+
The *dir_fd* parameter.
333+
328334
.. attribute:: rmtree.avoids_symlink_attacks
329335

330336
Indicates whether the current platform and implementation provides a

Doc/library/sqlite3.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,9 @@ Connection Objects
560560

561561
Passing :const:`None` as *trace_callback* will disable the trace callback.
562562

563+
For SQLite 3.14.0 and newer, bound parameters are expanded in the passed
564+
statement string.
565+
563566
.. note::
564567
Exceptions raised in the trace callback are not propagated. As a
565568
development and debugging aid, use
@@ -568,6 +571,9 @@ Connection Objects
568571

569572
.. versionadded:: 3.3
570573

574+
.. versionchanged:: 3.11
575+
Added support for expanded SQL statements.
576+
571577

572578
.. method:: enable_load_extension(enabled)
573579

@@ -836,11 +842,11 @@ Cursor Objects
836842

837843
.. method:: setinputsizes(sizes)
838844

839-
Required by the DB-API. Is a no-op in :mod:`sqlite3`.
845+
Required by the DB-API. Does nothing in :mod:`sqlite3`.
840846

841847
.. method:: setoutputsize(size [, column])
842848

843-
Required by the DB-API. Is a no-op in :mod:`sqlite3`.
849+
Required by the DB-API. Does nothing in :mod:`sqlite3`.
844850

845851
.. attribute:: rowcount
846852

Doc/whatsnew/3.11.rst

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,15 @@ Summary -- Release highlights
6565
6666
.. PEP-sized items next.
6767
68-
PEP-654: Exception Groups and ``except*``.
69-
(Contributed by Irit Katriel in :issue:`45292`.)
70-
PEP-673: ``Self`` Type.
71-
(Contributed by James Hilton-Balfe and Pradeep Kumar in :issue:`30924`.)
68+
New syntax features:
69+
70+
* :pep:`654`: Exception Groups and ``except*``.
71+
(Contributed by Irit Katriel in :issue:`45292`.)
72+
73+
New typing features:
74+
75+
* :pep:`673`: ``Self`` Type.
76+
(Contributed by James Hilton-Balfe and Pradeep Kumar in :issue:`30924`.)
7277

7378
New Features
7479
============
@@ -278,6 +283,13 @@ os
278283
(Contributed by Dong-hee Na in :issue:`44611`.)
279284

280285

286+
shutil
287+
------
288+
289+
* Add optional parameter *dir_fd* in :func:`shutil.rmtree`.
290+
(Contributed by Serhiy Storchaka in :issue:`46245`.)
291+
292+
281293
socket
282294
------
283295

@@ -322,6 +334,10 @@ sqlite3
322334
Instead we leave it to the SQLite library to handle these cases.
323335
(Contributed by Erlend E. Aasland in :issue:`44092`.)
324336

337+
* For SQLite 3.14.0 and newer, bound parameters are expanded in the statement
338+
string passed to the trace callback. See :meth:`~sqlite3.Connection.set_trace_callback`.
339+
(Contributed by Erlend E. Aasland in :issue:`45138`.)
340+
325341

326342
sys
327343
---

Lib/shutil.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -684,9 +684,14 @@ def _rmtree_safe_fd(topfd, path, onerror):
684684
os.scandir in os.supports_fd and
685685
os.stat in os.supports_follow_symlinks)
686686

687-
def rmtree(path, ignore_errors=False, onerror=None):
687+
def rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None):
688688
"""Recursively delete a directory tree.
689689
690+
If dir_fd is not None, it should be a file descriptor open to a directory;
691+
path will then be relative to that directory.
692+
dir_fd may not be implemented on your platform.
693+
If it is unavailable, using it will raise a NotImplementedError.
694+
690695
If ignore_errors is set, errors are ignored; otherwise, if onerror
691696
is set, it is called to handle the error with arguments (func,
692697
path, exc_info) where func is platform and implementation dependent;
@@ -695,7 +700,7 @@ def rmtree(path, ignore_errors=False, onerror=None):
695700
is false and onerror is None, an exception is raised.
696701
697702
"""
698-
sys.audit("shutil.rmtree", path)
703+
sys.audit("shutil.rmtree", path, dir_fd)
699704
if ignore_errors:
700705
def onerror(*args):
701706
pass
@@ -709,12 +714,12 @@ def onerror(*args):
709714
# Note: To guard against symlink races, we use the standard
710715
# lstat()/open()/fstat() trick.
711716
try:
712-
orig_st = os.lstat(path)
717+
orig_st = os.lstat(path, dir_fd=dir_fd)
713718
except Exception:
714719
onerror(os.lstat, path, sys.exc_info())
715720
return
716721
try:
717-
fd = os.open(path, os.O_RDONLY)
722+
fd = os.open(path, os.O_RDONLY, dir_fd=dir_fd)
718723
fd_closed = False
719724
except Exception:
720725
onerror(os.open, path, sys.exc_info())
@@ -725,7 +730,7 @@ def onerror(*args):
725730
try:
726731
os.close(fd)
727732
fd_closed = True
728-
os.rmdir(path)
733+
os.rmdir(path, dir_fd=dir_fd)
729734
except OSError:
730735
onerror(os.rmdir, path, sys.exc_info())
731736
else:
@@ -738,6 +743,8 @@ def onerror(*args):
738743
if not fd_closed:
739744
os.close(fd)
740745
else:
746+
if dir_fd is not None:
747+
raise NotImplementedError("dir_fd unavailable on this platform")
741748
try:
742749
if _rmtree_islink(path):
743750
# symlinks to directories are forbidden, see bug #1669

Lib/test/test_io.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ def test_invalid_operations(self):
426426
self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR)
427427
self.assertRaises(exc, fp.seek, -1, self.SEEK_END)
428428

429+
@unittest.skipIf(
430+
support.is_emscripten, "fstat() of a pipe fd is not supported"
431+
)
429432
def test_optional_abilities(self):
430433
# Test for OSError when optional APIs are not supported
431434
# The purpose of this test is to try fileno(), reading, writing and
@@ -3971,6 +3974,9 @@ def test_removed_u_mode(self):
39713974
self.open(os_helper.TESTFN, mode)
39723975
self.assertIn('invalid mode', str(cm.exception))
39733976

3977+
@unittest.skipIf(
3978+
support.is_emscripten, "fstat() of a pipe fd is not supported"
3979+
)
39743980
def test_open_pipe_with_append(self):
39753981
# bpo-27805: Ignore ESPIPE from lseek() in open().
39763982
r, w = os.pipe()
@@ -4134,9 +4140,15 @@ def test_pickling(self):
41344140
with self.open(os_helper.TESTFN, **kwargs) as f:
41354141
self.assertRaises(TypeError, pickle.dumps, f, protocol)
41364142

4143+
@unittest.skipIf(
4144+
support.is_emscripten, "fstat() of a pipe fd is not supported"
4145+
)
41374146
def test_nonblock_pipe_write_bigbuf(self):
41384147
self._test_nonblock_pipe_write(16*1024)
41394148

4149+
@unittest.skipIf(
4150+
support.is_emscripten, "fstat() of a pipe fd is not supported"
4151+
)
41404152
def test_nonblock_pipe_write_smallbuf(self):
41414153
self._test_nonblock_pipe_write(1024)
41424154

Lib/test/test_shutil.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,27 @@ def _raiser(*args, **kwargs):
405405
self.assertFalse(shutil._use_fd_functions)
406406
self.assertFalse(shutil.rmtree.avoids_symlink_attacks)
407407

408+
@unittest.skipUnless(shutil._use_fd_functions, "dir_fd is not supported")
409+
def test_rmtree_with_dir_fd(self):
410+
tmp_dir = self.mkdtemp()
411+
victim = 'killme'
412+
fullname = os.path.join(tmp_dir, victim)
413+
dir_fd = os.open(tmp_dir, os.O_RDONLY)
414+
self.addCleanup(os.close, dir_fd)
415+
os.mkdir(fullname)
416+
os.mkdir(os.path.join(fullname, 'subdir'))
417+
write_file(os.path.join(fullname, 'subdir', 'somefile'), 'foo')
418+
self.assertTrue(os.path.exists(fullname))
419+
shutil.rmtree(victim, dir_fd=dir_fd)
420+
self.assertFalse(os.path.exists(fullname))
421+
422+
@unittest.skipIf(shutil._use_fd_functions, "dir_fd is supported")
423+
def test_rmtree_with_dir_fd_unsupported(self):
424+
tmp_dir = self.mkdtemp()
425+
with self.assertRaises(NotImplementedError):
426+
shutil.rmtree(tmp_dir, dir_fd=0)
427+
self.assertTrue(os.path.exists(tmp_dir))
428+
408429
def test_rmtree_dont_delete_file(self):
409430
# When called on a file instead of a directory, don't delete it.
410431
handle, path = tempfile.mkstemp(dir=self.mkdtemp())

Lib/test/test_sqlite3/test_hooks.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@
2020
# misrepresented as being the original software.
2121
# 3. This notice may not be removed or altered from any source distribution.
2222

23-
import unittest
23+
import contextlib
2424
import sqlite3 as sqlite
25+
import unittest
2526

2627
from test.support.os_helper import TESTFN, unlink
28+
29+
from test.test_sqlite3.test_dbapi import memory_database, cx_limit
2730
from test.test_sqlite3.test_userfunctions import with_tracebacks
2831

32+
2933
class CollationTests(unittest.TestCase):
3034
def test_create_collation_not_string(self):
3135
con = sqlite.connect(":memory:")
@@ -224,6 +228,16 @@ def bad_progress():
224228

225229

226230
class TraceCallbackTests(unittest.TestCase):
231+
@contextlib.contextmanager
232+
def check_stmt_trace(self, cx, expected):
233+
try:
234+
traced = []
235+
cx.set_trace_callback(lambda stmt: traced.append(stmt))
236+
yield
237+
finally:
238+
self.assertEqual(traced, expected)
239+
cx.set_trace_callback(None)
240+
227241
def test_trace_callback_used(self):
228242
"""
229243
Test that the trace callback is invoked once it is set.
@@ -289,6 +303,51 @@ def trace(statement):
289303
con2.close()
290304
self.assertEqual(traced_statements, queries)
291305

306+
@unittest.skipIf(sqlite.sqlite_version_info < (3, 14, 0),
307+
"Requires SQLite 3.14.0 or newer")
308+
def test_trace_expanded_sql(self):
309+
expected = [
310+
"create table t(t)",
311+
"BEGIN ",
312+
"insert into t values(0)",
313+
"insert into t values(1)",
314+
"insert into t values(2)",
315+
"COMMIT",
316+
]
317+
with memory_database() as cx, self.check_stmt_trace(cx, expected):
318+
with cx:
319+
cx.execute("create table t(t)")
320+
cx.executemany("insert into t values(?)", ((v,) for v in range(3)))
321+
322+
@with_tracebacks(
323+
sqlite.DataError,
324+
regex="Expanded SQL string exceeds the maximum string length"
325+
)
326+
def test_trace_too_much_expanded_sql(self):
327+
# If the expanded string is too large, we'll fall back to the
328+
# unexpanded SQL statement. The resulting string length is limited by
329+
# SQLITE_LIMIT_LENGTH.
330+
template = "select 'b' as \"a\" from sqlite_master where \"a\"="
331+
category = sqlite.SQLITE_LIMIT_LENGTH
332+
with memory_database() as cx, cx_limit(cx, category=category) as lim:
333+
nextra = lim - (len(template) + 2) - 1
334+
ok_param = "a" * nextra
335+
bad_param = "a" * (nextra + 1)
336+
337+
unexpanded_query = template + "?"
338+
with self.check_stmt_trace(cx, [unexpanded_query]):
339+
cx.execute(unexpanded_query, (bad_param,))
340+
341+
expanded_query = f"{template}'{ok_param}'"
342+
with self.check_stmt_trace(cx, [expanded_query]):
343+
cx.execute(unexpanded_query, (ok_param,))
344+
345+
@with_tracebacks(ZeroDivisionError, regex="division by zero")
346+
def test_trace_bad_handler(self):
347+
with memory_database() as cx:
348+
cx.set_trace_callback(lambda stmt: 5/0)
349+
cx.execute("select 1")
350+
292351

293352
if __name__ == "__main__":
294353
unittest.main()

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,7 @@ LIBSUBDIRS= asyncio \
18691869
site-packages \
18701870
sqlite3 \
18711871
tkinter \
1872+
tomllib \
18721873
turtledemo \
18731874
unittest \
18741875
urllib \
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
For SQLite 3.14.0 and newer, bound parameters are expanded in the statement
2+
string passed to the :mod:`sqlite3` trace callback. Patch by Erlend E.
3+
Aasland.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add optional parameter *dir_fd* in :func:`shutil.rmtree`.

Modules/_sqlite/clinic/cursor.c.h

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)