mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Update some libs to 3.14.6 (#8102)
This commit is contained in:
1 parent
eccbc5e658
commit
1dc57e816a
17 files changed
+603
-353
No files matched your search
Vendored
+73
-48
@@ -1,14 +1,17 @@
|
||||
"""Test program for the fcntl C module.
|
||||
"""
|
||||
import errno
|
||||
import multiprocessing
|
||||
import platform
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import unittest
|
||||
from multiprocessing import Process
|
||||
from test.support import verbose, cpython_only
|
||||
from test.support import (
|
||||
cpython_only, get_pagesize, is_apple, requires_subprocess, verbose, is_emscripten
|
||||
)
|
||||
from test.support.import_helper import import_module
|
||||
from test.support.os_helper import TESTFN, unlink
|
||||
from test.support.os_helper import TESTFN, unlink, make_bad_fd
|
||||
|
||||
|
||||
# Skip test if no fcntl module.
|
||||
@@ -16,37 +19,6 @@ fcntl = import_module('fcntl')
|
||||
|
||||
|
||||
|
||||
def get_lockdata():
|
||||
try:
|
||||
os.O_LARGEFILE
|
||||
except AttributeError:
|
||||
start_len = "ll"
|
||||
else:
|
||||
start_len = "qq"
|
||||
|
||||
if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd'))
|
||||
or sys.platform == 'darwin'):
|
||||
if struct.calcsize('l') == 8:
|
||||
off_t = 'l'
|
||||
pid_t = 'i'
|
||||
else:
|
||||
off_t = 'lxxxx'
|
||||
pid_t = 'l'
|
||||
lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0,
|
||||
fcntl.F_WRLCK, 0)
|
||||
elif sys.platform.startswith('gnukfreebsd'):
|
||||
lockdata = struct.pack('qqihhi', 0, 0, 0, fcntl.F_WRLCK, 0, 0)
|
||||
elif sys.platform in ['hp-uxB', 'unixware7']:
|
||||
lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
|
||||
else:
|
||||
lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
|
||||
if lockdata:
|
||||
if verbose:
|
||||
print('struct.pack: ', repr(lockdata))
|
||||
return lockdata
|
||||
|
||||
lockdata = get_lockdata()
|
||||
|
||||
class BadFile:
|
||||
def __init__(self, fn):
|
||||
self.fn = fn
|
||||
@@ -78,12 +50,45 @@ class TestFcntl(unittest.TestCase):
|
||||
self.f.close()
|
||||
unlink(TESTFN)
|
||||
|
||||
@staticmethod
|
||||
def get_lockdata():
|
||||
try:
|
||||
os.O_LARGEFILE
|
||||
except AttributeError:
|
||||
start_len = "ll"
|
||||
else:
|
||||
start_len = "qq"
|
||||
|
||||
if (
|
||||
sys.platform.startswith(('netbsd', 'freebsd', 'openbsd'))
|
||||
or is_apple
|
||||
):
|
||||
if struct.calcsize('l') == 8:
|
||||
off_t = 'l'
|
||||
pid_t = 'i'
|
||||
else:
|
||||
off_t = 'lxxxx'
|
||||
pid_t = 'l'
|
||||
lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0,
|
||||
fcntl.F_WRLCK, 0)
|
||||
elif sys.platform.startswith('gnukfreebsd'):
|
||||
lockdata = struct.pack('qqihhi', 0, 0, 0, fcntl.F_WRLCK, 0, 0)
|
||||
elif sys.platform in ['hp-uxB', 'unixware7']:
|
||||
lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
|
||||
else:
|
||||
lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
|
||||
if lockdata:
|
||||
if verbose:
|
||||
print('struct.pack: ', repr(lockdata))
|
||||
return lockdata
|
||||
|
||||
def test_fcntl_fileno(self):
|
||||
# the example from the library docs
|
||||
self.f = open(TESTFN, 'wb')
|
||||
rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
if verbose:
|
||||
print('Status from fcntl with O_NONBLOCK: ', rv)
|
||||
lockdata = self.get_lockdata()
|
||||
rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETLKW, lockdata)
|
||||
if verbose:
|
||||
print('String from fcntl with F_SETLKW: ', repr(rv))
|
||||
@@ -95,6 +100,7 @@ class TestFcntl(unittest.TestCase):
|
||||
rv = fcntl.fcntl(self.f, fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
if verbose:
|
||||
print('Status from fcntl with O_NONBLOCK: ', rv)
|
||||
lockdata = self.get_lockdata()
|
||||
rv = fcntl.fcntl(self.f, fcntl.F_SETLKW, lockdata)
|
||||
if verbose:
|
||||
print('String from fcntl with F_SETLKW: ', repr(rv))
|
||||
@@ -112,7 +118,9 @@ class TestFcntl(unittest.TestCase):
|
||||
|
||||
@cpython_only
|
||||
def test_fcntl_bad_file_overflow(self):
|
||||
from _testcapi import INT_MAX, INT_MIN
|
||||
_testcapi = import_module("_testcapi")
|
||||
INT_MAX = _testcapi.INT_MAX
|
||||
INT_MIN = _testcapi.INT_MIN
|
||||
# Issue 15989
|
||||
with self.assertRaises(OverflowError):
|
||||
fcntl.fcntl(INT_MAX + 1, fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
@@ -124,19 +132,25 @@ class TestFcntl(unittest.TestCase):
|
||||
fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
|
||||
@unittest.skipIf(
|
||||
platform.machine().startswith('arm') and platform.system() == 'Linux',
|
||||
"ARM Linux returns EINVAL for F_NOTIFY DN_MULTISHOT")
|
||||
(platform.machine().startswith("arm") and platform.system() == "Linux")
|
||||
or platform.system() == "Android",
|
||||
"this platform returns EINVAL for F_NOTIFY DN_MULTISHOT")
|
||||
def test_fcntl_64_bit(self):
|
||||
# Issue #1309352: fcntl shouldn't fail when the third arg fits in a
|
||||
# Issue GH-42434: fcntl shouldn't fail when the third arg fits in a
|
||||
# C 'long' but not in a C 'int'.
|
||||
try:
|
||||
cmd = fcntl.F_NOTIFY
|
||||
# This flag is larger than 2**31 in 64-bit builds
|
||||
# DN_MULTISHOT is >= 2**31 in 64-bit builds
|
||||
flags = fcntl.DN_MULTISHOT
|
||||
except AttributeError:
|
||||
self.skipTest("F_NOTIFY or DN_MULTISHOT unavailable")
|
||||
fd = os.open(os.path.dirname(os.path.abspath(TESTFN)), os.O_RDONLY)
|
||||
try:
|
||||
try:
|
||||
fcntl.fcntl(fd, cmd, fcntl.DN_DELETE)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EINVAL:
|
||||
self.skipTest("F_NOTIFY not available by this environment")
|
||||
fcntl.fcntl(fd, cmd, flags)
|
||||
finally:
|
||||
os.close(fd)
|
||||
@@ -155,27 +169,27 @@ class TestFcntl(unittest.TestCase):
|
||||
self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH)
|
||||
self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH)
|
||||
|
||||
# TODO RustPython
|
||||
@unittest.skipUnless(sys.platform == 'linux', 'test requires Linux')
|
||||
@unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
|
||||
@requires_subprocess()
|
||||
def test_lockf_exclusive(self):
|
||||
self.f = open(TESTFN, 'wb+')
|
||||
cmd = fcntl.LOCK_EX | fcntl.LOCK_NB
|
||||
fcntl.lockf(self.f, cmd)
|
||||
p = Process(target=try_lockf_on_other_process_fail, args=(TESTFN, cmd))
|
||||
mp = multiprocessing.get_context('spawn')
|
||||
p = mp.Process(target=try_lockf_on_other_process_fail, args=(TESTFN, cmd))
|
||||
p.start()
|
||||
p.join()
|
||||
fcntl.lockf(self.f, fcntl.LOCK_UN)
|
||||
self.assertEqual(p.exitcode, 0)
|
||||
|
||||
# TODO RustPython
|
||||
@unittest.skipUnless(sys.platform == 'linux', 'test requires Linux')
|
||||
@unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
|
||||
@requires_subprocess()
|
||||
def test_lockf_share(self):
|
||||
self.f = open(TESTFN, 'wb+')
|
||||
cmd = fcntl.LOCK_SH | fcntl.LOCK_NB
|
||||
fcntl.lockf(self.f, cmd)
|
||||
p = Process(target=try_lockf_on_other_process, args=(TESTFN, cmd))
|
||||
mp = multiprocessing.get_context('spawn')
|
||||
p = mp.Process(target=try_lockf_on_other_process, args=(TESTFN, cmd))
|
||||
p.start()
|
||||
p.join()
|
||||
fcntl.lockf(self.f, fcntl.LOCK_UN)
|
||||
@@ -183,7 +197,7 @@ class TestFcntl(unittest.TestCase):
|
||||
|
||||
@cpython_only
|
||||
def test_flock_overflow(self):
|
||||
import _testcapi
|
||||
_testcapi = import_module("_testcapi")
|
||||
self.assertRaises(OverflowError, fcntl.flock, _testcapi.INT_MAX+1,
|
||||
fcntl.LOCK_SH)
|
||||
|
||||
@@ -197,14 +211,16 @@ class TestFcntl(unittest.TestCase):
|
||||
@unittest.skipUnless(
|
||||
hasattr(fcntl, "F_SETPIPE_SZ") and hasattr(fcntl, "F_GETPIPE_SZ"),
|
||||
"F_SETPIPE_SZ and F_GETPIPE_SZ are not available on all platforms.")
|
||||
@unittest.skipIf(is_emscripten, "Emscripten pipefs doesn't support these")
|
||||
def test_fcntl_f_pipesize(self):
|
||||
test_pipe_r, test_pipe_w = os.pipe()
|
||||
try:
|
||||
# Get the default pipesize with F_GETPIPE_SZ
|
||||
pipesize_default = fcntl.fcntl(test_pipe_w, fcntl.F_GETPIPE_SZ)
|
||||
pipesize = pipesize_default // 2 # A new value to detect change.
|
||||
if pipesize < 512: # the POSIX minimum
|
||||
raise unittest.SkitTest(
|
||||
pagesize_default = get_pagesize()
|
||||
if pipesize < pagesize_default: # the POSIX minimum
|
||||
raise unittest.SkipTest(
|
||||
'default pipesize too small to perform test.')
|
||||
fcntl.fcntl(test_pipe_w, fcntl.F_SETPIPE_SZ, pipesize)
|
||||
self.assertEqual(fcntl.fcntl(test_pipe_w, fcntl.F_GETPIPE_SZ),
|
||||
@@ -213,6 +229,15 @@ class TestFcntl(unittest.TestCase):
|
||||
os.close(test_pipe_r)
|
||||
os.close(test_pipe_w)
|
||||
|
||||
@unittest.skipUnless(hasattr(fcntl, 'F_DUPFD'), 'need fcntl.F_DUPFD')
|
||||
def test_bad_fd(self):
|
||||
# gh-134744: Test error handling
|
||||
fd = make_bad_fd()
|
||||
with self.assertRaises(OSError):
|
||||
fcntl.fcntl(fd, fcntl.F_DUPFD, 0)
|
||||
with self.assertRaises(OSError):
|
||||
fcntl.fcntl(fd, fcntl.F_DUPFD, b'\0' * 1024)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Vendored
+172
-48
@@ -1,45 +1,79 @@
|
||||
import array
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import threading
|
||||
import unittest
|
||||
from test.support import get_attribute
|
||||
from test import support
|
||||
from test.support import os_helper, threading_helper
|
||||
from test.support.import_helper import import_module
|
||||
import os, struct
|
||||
fcntl = import_module('fcntl')
|
||||
termios = import_module('termios')
|
||||
get_attribute(termios, 'TIOCGPGRP') #Can't run tests without this feature
|
||||
|
||||
try:
|
||||
tty = open("/dev/tty", "rb")
|
||||
except OSError:
|
||||
raise unittest.SkipTest("Unable to open /dev/tty")
|
||||
else:
|
||||
with tty:
|
||||
# Skip if another process is in foreground
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ")
|
||||
rpgrp = struct.unpack("i", r)[0]
|
||||
if rpgrp not in (os.getpgrp(), os.getsid(0)):
|
||||
raise unittest.SkipTest("Neither the process group nor the session "
|
||||
"are attached to /dev/tty")
|
||||
del tty, r, rpgrp
|
||||
class IoctlTestsTty(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
TIOCGPGRP = support.get_attribute(termios, 'TIOCGPGRP')
|
||||
try:
|
||||
tty = open("/dev/tty", "rb")
|
||||
except OSError:
|
||||
raise unittest.SkipTest("Unable to open /dev/tty")
|
||||
with tty:
|
||||
# Skip if another process is in foreground
|
||||
r = fcntl.ioctl(tty, TIOCGPGRP, struct.pack("i", 0))
|
||||
rpgrp = struct.unpack("i", r)[0]
|
||||
if rpgrp not in (os.getpgrp(), os.getsid(0)):
|
||||
raise unittest.SkipTest("Neither the process group nor the session "
|
||||
"are attached to /dev/tty")
|
||||
|
||||
try:
|
||||
import pty
|
||||
except ImportError:
|
||||
pty = None
|
||||
|
||||
class IoctlTests(unittest.TestCase):
|
||||
def test_ioctl(self):
|
||||
def test_ioctl_immutable_buf(self):
|
||||
# If this process has been put into the background, TIOCGPGRP returns
|
||||
# the session ID instead of the process group id.
|
||||
ids = (os.getpgrp(), os.getsid(0))
|
||||
with open("/dev/tty", "rb") as tty:
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ")
|
||||
rpgrp = struct.unpack("i", r)[0]
|
||||
# string
|
||||
buf = " "*8
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf)
|
||||
self.assertIsInstance(r, bytes)
|
||||
rpgrp = memoryview(r).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
def _check_ioctl_mutate_len(self, nbytes=None):
|
||||
# bytes
|
||||
buf = b" "*8
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf)
|
||||
self.assertIsInstance(r, bytes)
|
||||
rpgrp = memoryview(r).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
# read-only buffer
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, memoryview(buf))
|
||||
self.assertIsInstance(r, bytes)
|
||||
rpgrp = memoryview(r).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
def test_ioctl_mutable_buf(self):
|
||||
ids = (os.getpgrp(), os.getsid(0))
|
||||
with open("/dev/tty", "rb") as tty:
|
||||
buf = bytearray(b" "*8)
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf)
|
||||
self.assertEqual(r, 0)
|
||||
rpgrp = memoryview(buf).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
def test_ioctl_no_mutate_buf(self):
|
||||
ids = (os.getpgrp(), os.getsid(0))
|
||||
with open("/dev/tty", "rb") as tty:
|
||||
buf = bytearray(b" "*8)
|
||||
save_buf = bytes(buf)
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, False)
|
||||
self.assertEqual(bytes(buf), save_buf)
|
||||
self.assertIsInstance(r, bytes)
|
||||
rpgrp = memoryview(r).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
def _create_int_buf(self, nbytes=None):
|
||||
buf = array.array('i')
|
||||
intsize = buf.itemsize
|
||||
ids = (os.getpgrp(), os.getsid(0))
|
||||
# A fill value unlikely to be in `ids`
|
||||
fill = -12345
|
||||
if nbytes is not None:
|
||||
@@ -48,45 +82,135 @@ class IoctlTests(unittest.TestCase):
|
||||
self.assertEqual(len(buf) * intsize, nbytes) # sanity check
|
||||
else:
|
||||
buf.append(fill)
|
||||
return buf
|
||||
|
||||
def _check_ioctl_mutate_len(self, nbytes=None):
|
||||
ids = (os.getpgrp(), os.getsid(0))
|
||||
buf = self._create_int_buf(nbytes)
|
||||
with open("/dev/tty", "rb") as tty:
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, True)
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf)
|
||||
rpgrp = buf[0]
|
||||
self.assertEqual(r, 0)
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
def _check_ioctl_not_mutate_len(self, nbytes=None):
|
||||
ids = (os.getpgrp(), os.getsid(0))
|
||||
buf = self._create_int_buf(nbytes)
|
||||
save_buf = bytes(buf)
|
||||
with open("/dev/tty", "rb") as tty:
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, False)
|
||||
self.assertIsInstance(r, bytes)
|
||||
self.assertEqual(len(r), len(save_buf))
|
||||
self.assertEqual(bytes(buf), save_buf)
|
||||
rpgrp = array.array('i', r)[0]
|
||||
rpgrp = memoryview(r).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
buf = bytes(buf)
|
||||
with open("/dev/tty", "rb") as tty:
|
||||
r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, True)
|
||||
self.assertIsInstance(r, bytes)
|
||||
self.assertEqual(len(r), len(save_buf))
|
||||
self.assertEqual(buf, save_buf)
|
||||
rpgrp = array.array('i', r)[0]
|
||||
rpgrp = memoryview(r).cast('i')[0]
|
||||
self.assertIn(rpgrp, ids)
|
||||
|
||||
def test_ioctl_mutate(self):
|
||||
self._check_ioctl_mutate_len()
|
||||
self._check_ioctl_not_mutate_len()
|
||||
|
||||
def test_ioctl_mutate_1024(self):
|
||||
# Issue #9758: a mutable buffer of exactly 1024 bytes wouldn't be
|
||||
# copied back after the system call.
|
||||
self._check_ioctl_mutate_len(1024)
|
||||
self._check_ioctl_not_mutate_len(1024)
|
||||
|
||||
def test_ioctl_mutate_2048(self):
|
||||
# Test with a larger buffer, just for the record.
|
||||
self._check_ioctl_mutate_len(2048)
|
||||
self.assertRaises(ValueError, self._check_ioctl_not_mutate_len, 2048)
|
||||
|
||||
def test_ioctl_signed_unsigned_code_param(self):
|
||||
if not pty:
|
||||
raise unittest.SkipTest('pty module required')
|
||||
mfd, sfd = pty.openpty()
|
||||
try:
|
||||
if termios.TIOCSWINSZ < 0:
|
||||
set_winsz_opcode_maybe_neg = termios.TIOCSWINSZ
|
||||
set_winsz_opcode_pos = termios.TIOCSWINSZ & 0xffffffff
|
||||
else:
|
||||
set_winsz_opcode_pos = termios.TIOCSWINSZ
|
||||
set_winsz_opcode_maybe_neg, = struct.unpack("i",
|
||||
struct.pack("I", termios.TIOCSWINSZ))
|
||||
|
||||
our_winsz = struct.pack("HHHH",80,25,0,0)
|
||||
# test both with a positive and potentially negative ioctl code
|
||||
new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz)
|
||||
new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz)
|
||||
finally:
|
||||
os.close(mfd)
|
||||
os.close(sfd)
|
||||
@unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
|
||||
class IoctlTestsPty(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.master_fd, self.slave_fd = os.openpty()
|
||||
self.addCleanup(os.close, self.slave_fd)
|
||||
self.addCleanup(os.close, self.master_fd)
|
||||
|
||||
@unittest.skipUnless(hasattr(termios, 'TCFLSH'), 'requires termios.TCFLSH')
|
||||
def test_ioctl_clear_input_or_output(self):
|
||||
wfd = self.slave_fd
|
||||
rfd = self.master_fd
|
||||
# The data is buffered in the input buffer on Linux, and in
|
||||
# the output buffer on other platforms.
|
||||
inbuf = sys.platform in ('linux', 'android')
|
||||
|
||||
os.write(wfd, b'abcdef')
|
||||
self.assertEqual(os.read(rfd, 2), b'ab')
|
||||
if inbuf:
|
||||
# don't flush input
|
||||
fcntl.ioctl(rfd, termios.TCFLSH, termios.TCOFLUSH)
|
||||
else:
|
||||
# don't flush output
|
||||
fcntl.ioctl(wfd, termios.TCFLSH, termios.TCIFLUSH)
|
||||
self.assertEqual(os.read(rfd, 2), b'cd')
|
||||
if inbuf:
|
||||
# flush input
|
||||
fcntl.ioctl(rfd, termios.TCFLSH, termios.TCIFLUSH)
|
||||
else:
|
||||
# flush output
|
||||
fcntl.ioctl(wfd, termios.TCFLSH, termios.TCOFLUSH)
|
||||
os.write(wfd, b'ABCDEF')
|
||||
self.assertEqual(os.read(rfd, 1024), b'ABCDEF')
|
||||
|
||||
@support.skip_android_selinux('tcflow')
|
||||
@unittest.skipUnless(sys.platform in ('linux', 'android'), 'only works on Linux')
|
||||
@unittest.skipUnless(hasattr(termios, 'TCXONC'), 'requires termios.TCXONC')
|
||||
def test_ioctl_suspend_and_resume_output(self):
|
||||
wfd = self.slave_fd
|
||||
rfd = self.master_fd
|
||||
write_suspended = threading.Event()
|
||||
write_finished = threading.Event()
|
||||
|
||||
def writer():
|
||||
os.write(wfd, b'abc')
|
||||
self.assertTrue(write_suspended.wait(support.SHORT_TIMEOUT))
|
||||
os.write(wfd, b'def')
|
||||
write_finished.set()
|
||||
|
||||
with threading_helper.start_threads([threading.Thread(target=writer)]):
|
||||
self.assertEqual(os.read(rfd, 3), b'abc')
|
||||
try:
|
||||
try:
|
||||
fcntl.ioctl(wfd, termios.TCXONC, termios.TCOOFF)
|
||||
finally:
|
||||
write_suspended.set()
|
||||
self.assertFalse(write_finished.wait(0.5),
|
||||
'output was not suspended')
|
||||
finally:
|
||||
fcntl.ioctl(wfd, termios.TCXONC, termios.TCOON)
|
||||
self.assertTrue(write_finished.wait(support.SHORT_TIMEOUT),
|
||||
'output was not resumed')
|
||||
self.assertEqual(os.read(rfd, 1024), b'def')
|
||||
|
||||
def test_ioctl_set_window_size(self):
|
||||
# (rows, columns, xpixel, ypixel)
|
||||
our_winsz = struct.pack("HHHH", 20, 40, 0, 0)
|
||||
result = fcntl.ioctl(self.master_fd, termios.TIOCSWINSZ, our_winsz)
|
||||
new_winsz = struct.unpack("HHHH", result)
|
||||
self.assertEqual(new_winsz[:2], (20, 40))
|
||||
|
||||
@unittest.skipUnless(hasattr(fcntl, 'FICLONE'), 'need fcntl.FICLONE')
|
||||
def test_bad_fd(self):
|
||||
# gh-134744: Test error handling
|
||||
fd = os_helper.make_bad_fd()
|
||||
with self.assertRaises(OSError):
|
||||
fcntl.ioctl(fd, fcntl.FICLONE, fd)
|
||||
with self.assertRaises(OSError):
|
||||
fcntl.ioctl(fd, fcntl.FICLONE, b'\0' * 1024)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
Vendored
+2
-2
@@ -58,7 +58,7 @@ class StatsTestCase(unittest.TestCase):
|
||||
temp_storage_new.close()
|
||||
os.remove(temp_storage_new.name)
|
||||
|
||||
@unittest.skipUnless(cProfile, 'TODO: RUSTPYTHON; _lsprof not implemented')
|
||||
@unittest.skipUnless(cProfile, "TODO: RUSTPYTHON; _lsprof not implemented")
|
||||
def test_load_equivalent_to_init(self):
|
||||
stats = pstats.Stats()
|
||||
self.temp_storage = tempfile.NamedTemporaryFile(delete=False)
|
||||
@@ -136,7 +136,7 @@ class StatsTestCase(unittest.TestCase):
|
||||
SortKey.TIME,
|
||||
'calls')
|
||||
|
||||
@unittest.skipUnless(cProfile, 'TODO: RUSTPYTHON; _lsprof not implemented')
|
||||
@unittest.skipUnless(cProfile, "TODO: RUSTPYTHON; _lsprof not implemented")
|
||||
def test_get_stats_profile(self):
|
||||
def pass1(): pass
|
||||
def pass2(): pass
|
||||
|
||||
Vendored
+13
@@ -117,6 +117,19 @@ class TestMiscellaneous(unittest.TestCase):
|
||||
recursive_table_toml = nest_count * "key = {" + nest_count * "}"
|
||||
tomllib.loads(recursive_table_toml)
|
||||
|
||||
def test_key_recursion_limit(self):
|
||||
nest_count = tomllib._parser.MAX_KEY_PARTS - 2
|
||||
nested_key_toml = "a." * nest_count + "a = 1"
|
||||
tomllib.loads(nested_key_toml)
|
||||
|
||||
nest_count = tomllib._parser.MAX_KEY_PARTS + 2
|
||||
nested_key_toml = "a." * nest_count + "a = 1"
|
||||
with self.assertRaisesRegex(
|
||||
RecursionError,
|
||||
r"TOML key has more than the allowed [0-9]+ parts",
|
||||
):
|
||||
tomllib.loads(nested_key_toml)
|
||||
|
||||
def test_types_import(self):
|
||||
"""Test that `_types` module runs.
|
||||
|
||||
|
||||
Vendored
+7
@@ -485,6 +485,13 @@ class DeferredEvaluationTests(unittest.TestCase):
|
||||
ns = run_code("x: [y for y in range(10)]")
|
||||
self.assertEqual(ns["__annotate__"](1), {"x": list(range(10))})
|
||||
|
||||
def test_class_annotation_dunder_classdict(self):
|
||||
ns = run_code("""
|
||||
class C:
|
||||
__classdict__: int
|
||||
""")
|
||||
self.assertEqual(ns["C"].__annotations__, {"__classdict__": int})
|
||||
|
||||
def test_future_annotations(self):
|
||||
code = """
|
||||
from __future__ import annotations
|
||||
|
||||
Vendored
+20
@@ -675,6 +675,26 @@ class BasicTest(BaseTest):
|
||||
self.assertEqual(out, "".encode())
|
||||
self.assertEqual(err, "".encode())
|
||||
|
||||
# gh-149701: Test exit code is zero even when hashing is disabled
|
||||
@unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
|
||||
def test_deactivate_with_strict_bash_opts_and_hashing_disabled(self):
|
||||
bash = shutil.which("bash")
|
||||
if bash is None:
|
||||
self.skipTest("bash required for this test")
|
||||
rmtree(self.env_dir)
|
||||
builder = venv.EnvBuilder(clear=True)
|
||||
builder.create(self.env_dir)
|
||||
activate = os.path.join(self.env_dir, self.bindir, "activate")
|
||||
test_script = os.path.join(self.env_dir, "test_hash_disabled.sh")
|
||||
with open(test_script, "w") as f:
|
||||
f.write("set -euo pipefail\n"
|
||||
"set +h\n" # disable hashing
|
||||
f"source {activate}\n"
|
||||
"deactivate")
|
||||
out, err = check_output([bash, test_script])
|
||||
self.assertEqual(out, "".encode())
|
||||
self.assertEqual(err, "".encode())
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform == 'darwin', 'only relevant on macOS')
|
||||
def test_macos_env(self):
|
||||
|
||||
Vendored
+34
-24
@@ -1890,11 +1890,8 @@ class OtherTests(unittest.TestCase):
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "r") as zf:
|
||||
zip_info = zf.getinfo("test_source_date_epoch.txt")
|
||||
get_time = time.localtime(int(os.environ['SOURCE_DATE_EPOCH']))[:6]
|
||||
# Compare each element of the date_time tuple
|
||||
# Allow for a 1-second difference
|
||||
for z_time, g_time in zip(zip_info.date_time, get_time):
|
||||
self.assertAlmostEqual(z_time, g_time, delta=1)
|
||||
expected_utc = (2025, 1, 1, 7, 19, 58)
|
||||
self.assertEqual(zip_info.date_time, expected_utc)
|
||||
|
||||
def test_write_without_source_date_epoch(self):
|
||||
with os_helper.EnvironmentVarGuard() as env:
|
||||
@@ -1905,9 +1902,13 @@ class OtherTests(unittest.TestCase):
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "r") as zf:
|
||||
zip_info = zf.getinfo("test_no_source_date_epoch.txt")
|
||||
current_time = time.localtime()[:6]
|
||||
for z_time, c_time in zip(zip_info.date_time, current_time):
|
||||
self.assertAlmostEqual(z_time, c_time, delta=2)
|
||||
self.assertTimestampAlmostEqual(time.localtime(), zip_info.date_time, tolerance=2)
|
||||
|
||||
def assertTimestampAlmostEqual(self, time1, time2, tolerance):
|
||||
import datetime
|
||||
dt1 = datetime.datetime(*time1[:6])
|
||||
dt2 = datetime.datetime(*time2[:6])
|
||||
self.assertLessEqual((dt1 - dt2).total_seconds(), tolerance)
|
||||
|
||||
def test_close(self):
|
||||
"""Check that the zipfile is closed after the 'with' block."""
|
||||
@@ -3568,6 +3569,7 @@ class TestExecutablePrependedZip(unittest.TestCase):
|
||||
output = subprocess.check_output([self.exe_zip64, sys.executable])
|
||||
self.assertIn(b'number in executable: 5', output)
|
||||
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON; LookupError: unknown encoding: shift_jis")
|
||||
class EncodedMetadataTests(unittest.TestCase):
|
||||
file_names = ['\u4e00', '\u4e8c', '\u4e09'] # Han 'one', 'two', 'three'
|
||||
@@ -3646,29 +3648,23 @@ class EncodedMetadataTests(unittest.TestCase):
|
||||
|
||||
def test_read_after_append(self):
|
||||
newname = '\u56db' # Han 'four'
|
||||
expected_names = [name.encode('shift_jis').decode('cp437')
|
||||
for name in self.file_names[:2]] + self.file_names[2:]
|
||||
expected_names.append(newname)
|
||||
expected_content = (*self.file_content, b"newcontent")
|
||||
newname2 = 'fünf' # representable in cp437, but still stored as UTF-8
|
||||
expected_names = [*self.file_names, newname, newname2]
|
||||
mojibake_expected_names = [name.encode('shift_jis').decode('cp437')
|
||||
if i < 2 else name
|
||||
for i, name in enumerate(expected_names)]
|
||||
expected_content = (*self.file_content, b"newcontent", b"newcontent2")
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "a") as zipfp:
|
||||
zipfp.writestr(newname, "newcontent")
|
||||
self.assertEqual(sorted(zipfp.namelist()), sorted(expected_names))
|
||||
zipfp.writestr(newname2, "newcontent2")
|
||||
self.assertEqual(sorted(zipfp.namelist()), sorted(mojibake_expected_names))
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "r") as zipfp:
|
||||
self._test_read(zipfp, expected_names, expected_content)
|
||||
self._test_read(zipfp, mojibake_expected_names, expected_content)
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "r", metadata_encoding='shift_jis') as zipfp:
|
||||
self.assertEqual(sorted(zipfp.namelist()), sorted(expected_names))
|
||||
for i, (name, content) in enumerate(zip(expected_names, expected_content)):
|
||||
info = zipfp.getinfo(name)
|
||||
self.assertEqual(info.filename, name)
|
||||
self.assertEqual(info.file_size, len(content))
|
||||
if i < 2:
|
||||
with self.assertRaises(zipfile.BadZipFile):
|
||||
zipfp.read(name)
|
||||
else:
|
||||
self.assertEqual(zipfp.read(name), content)
|
||||
self._test_read(zipfp, expected_names, expected_content)
|
||||
|
||||
def test_write_with_metadata_encoding(self):
|
||||
ZF = zipfile.ZipFile
|
||||
@@ -3677,6 +3673,20 @@ class EncodedMetadataTests(unittest.TestCase):
|
||||
"^metadata_encoding is only"):
|
||||
ZF("nonesuch.zip", mode, metadata_encoding="shift_jis")
|
||||
|
||||
def test_add_comment(self):
|
||||
with zipfile.ZipFile(TESTFN, "r") as zipfp:
|
||||
mojibake_expected_names = zipfp.namelist()
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "a") as zipfp:
|
||||
zipfp.comment = b'comment'
|
||||
self.assertEqual(zipfp.namelist(), mojibake_expected_names)
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "r") as zipfp:
|
||||
self._test_read(zipfp, mojibake_expected_names, self.file_content)
|
||||
|
||||
with zipfile.ZipFile(TESTFN, "r", metadata_encoding='shift_jis') as zipfp:
|
||||
self._test_read(zipfp, self.file_names, self.file_content)
|
||||
|
||||
def test_cli_with_metadata_encoding(self):
|
||||
errmsg = "Non-conforming encodings not supported with -c."
|
||||
args = ["--metadata-encoding=shift_jis", "-c", "nonesuch", "nonesuch"]
|
||||
|
||||
Vendored
+143
-113
@@ -7,25 +7,25 @@ Checkbutton, Scale, Listbox, Scrollbar, OptionMenu, Spinbox
|
||||
LabelFrame and PanedWindow.
|
||||
|
||||
Properties of the widgets are specified with keyword arguments.
|
||||
Keyword arguments have the same name as the corresponding resource
|
||||
Keyword arguments have the same name as the corresponding options
|
||||
under Tk.
|
||||
|
||||
Widgets are positioned with one of the geometry managers Place, Pack
|
||||
or Grid. These managers can be called with methods place, pack, grid
|
||||
available in every Widget.
|
||||
|
||||
Actions are bound to events by resources (e.g. keyword argument
|
||||
command) or with the method bind.
|
||||
Actions are bound to events by options (e.g. the command
|
||||
keyword argument) or with the bind() method.
|
||||
|
||||
Example (Hello, World):
|
||||
import tkinter
|
||||
from tkinter.constants import *
|
||||
tk = tkinter.Tk()
|
||||
frame = tkinter.Frame(tk, relief=RIDGE, borderwidth=2)
|
||||
frame.pack(fill=BOTH,expand=1)
|
||||
frame.pack(fill=BOTH, expand=1)
|
||||
label = tkinter.Label(frame, text="Hello, World")
|
||||
label.pack(fill=X, expand=1)
|
||||
button = tkinter.Button(frame,text="Exit",command=tk.destroy)
|
||||
button = tkinter.Button(frame, text="Exit", command=tk.destroy)
|
||||
button.pack(side=BOTTOM)
|
||||
tk.mainloop()
|
||||
"""
|
||||
@@ -295,6 +295,8 @@ class Event:
|
||||
''.join(' %s=%s' % (k, attrs[k]) for k in keys if k in attrs)
|
||||
)
|
||||
|
||||
__class_getitem__ = classmethod(types.GenericAlias)
|
||||
|
||||
|
||||
_support_default_root = True
|
||||
_default_root = None
|
||||
@@ -498,10 +500,14 @@ class Variable:
|
||||
|
||||
Return the name of the callback.
|
||||
|
||||
This deprecated method wraps a deprecated Tcl method that will
|
||||
likely be removed in the future. Use trace_add() instead.
|
||||
This deprecated method wraps a deprecated Tcl method removed
|
||||
in Tcl 9.0. Use trace_add() instead.
|
||||
"""
|
||||
# TODO: Add deprecation warning
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"trace_variable() is deprecated and not supported with Tcl 9; "
|
||||
"use trace_add() instead.",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
cbname = self._register(callback)
|
||||
self._tk.call("trace", "variable", self._name, mode, cbname)
|
||||
return cbname
|
||||
@@ -514,10 +520,14 @@ class Variable:
|
||||
MODE is one of "r", "w", "u" for read, write, undefine.
|
||||
CBNAME is the name of the callback returned from trace_variable or trace.
|
||||
|
||||
This deprecated method wraps a deprecated Tcl method that will
|
||||
likely be removed in the future. Use trace_remove() instead.
|
||||
This deprecated method wraps a deprecated Tcl method removed
|
||||
in Tcl 9.0. Use trace_remove() instead.
|
||||
"""
|
||||
# TODO: Add deprecation warning
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"trace_vdelete() is deprecated and not supported with Tcl 9; "
|
||||
"use trace_remove() instead.",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
self._tk.call("trace", "vdelete", self._name, mode, cbname)
|
||||
cbname = self._tk.splitlist(cbname)[0]
|
||||
for m, ca in self.trace_info():
|
||||
@@ -533,10 +543,14 @@ class Variable:
|
||||
def trace_vinfo(self):
|
||||
"""Return all trace callback information.
|
||||
|
||||
This deprecated method wraps a deprecated Tcl method that will
|
||||
likely be removed in the future. Use trace_info() instead.
|
||||
This deprecated method wraps a deprecated Tcl method removed
|
||||
in Tcl 9.0. Use trace_info() instead.
|
||||
"""
|
||||
# TODO: Add deprecation warning
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"trace_vinfo() is deprecated and not supported with Tcl 9; "
|
||||
"use trace_info() instead.",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
return [self._tk.splitlist(x) for x in self._tk.splitlist(
|
||||
self._tk.call("trace", "vinfo", self._name))]
|
||||
|
||||
@@ -833,7 +847,7 @@ class Misc:
|
||||
The focus order first goes to the next child, then to
|
||||
the children of the child recursively and then to the
|
||||
next sibling which is higher in the stacking order. A
|
||||
widget is omitted if it has the takefocus resource set
|
||||
widget is omitted if it has the takefocus option set
|
||||
to 0."""
|
||||
name = self.tk.call('tk_focusNext', self._w)
|
||||
if not name: return None
|
||||
@@ -845,7 +859,7 @@ class Misc:
|
||||
if not name: return None
|
||||
return self._nametowidget(name)
|
||||
|
||||
def after(self, ms, func=None, *args):
|
||||
def after(self, ms, func=None, *args, **kw):
|
||||
"""Call function once after given time.
|
||||
|
||||
MS specifies the time in milliseconds. FUNC gives the
|
||||
@@ -859,7 +873,7 @@ class Misc:
|
||||
else:
|
||||
def callit():
|
||||
try:
|
||||
func(*args)
|
||||
func(*args, **kw)
|
||||
finally:
|
||||
try:
|
||||
self.deletecommand(name)
|
||||
@@ -873,13 +887,13 @@ class Misc:
|
||||
name = self._register(callit)
|
||||
return self.tk.call('after', ms, name)
|
||||
|
||||
def after_idle(self, func, *args):
|
||||
def after_idle(self, func, *args, **kw):
|
||||
"""Call FUNC once if the Tcl main loop has no event to
|
||||
process.
|
||||
|
||||
Return an identifier to cancel the scheduling with
|
||||
after_cancel."""
|
||||
return self.after('idle', func, *args)
|
||||
return self.after('idle', func, *args, **kw)
|
||||
|
||||
def after_cancel(self, id):
|
||||
"""Cancel scheduling of function identified with ID.
|
||||
@@ -1813,18 +1827,24 @@ class Misc:
|
||||
# These used to be defined in Widget:
|
||||
|
||||
def configure(self, cnf=None, **kw):
|
||||
"""Configure resources of a widget.
|
||||
"""Query or modify the configuration options of the widget.
|
||||
|
||||
The values for resources are specified as keyword
|
||||
arguments. To get an overview about
|
||||
the allowed keyword arguments call the method keys.
|
||||
If no arguments are specified, return a dictionary describing
|
||||
all of the available options for the widget.
|
||||
|
||||
If an option name is specified, then return a tuple describing
|
||||
the one named option.
|
||||
|
||||
If one or more keyword arguments are specified or a dictionary
|
||||
is specified, then modify the widget option(s) to have the given
|
||||
value(s).
|
||||
"""
|
||||
return self._configure('configure', cnf, kw)
|
||||
|
||||
config = configure
|
||||
|
||||
def cget(self, key):
|
||||
"""Return the resource value for a KEY given as string."""
|
||||
"""Return the current value of the configuration option."""
|
||||
return self.tk.call(self._w, 'cget', '-' + key)
|
||||
|
||||
__getitem__ = cget
|
||||
@@ -1833,7 +1853,7 @@ class Misc:
|
||||
self.configure({key: value})
|
||||
|
||||
def keys(self):
|
||||
"""Return a list of all resource names of this widget."""
|
||||
"""Return a list of all option names of this widget."""
|
||||
splitlist = self.tk.splitlist
|
||||
return [splitlist(x)[0][1:] for x in
|
||||
splitlist(self.tk.call(self._w, 'configure'))]
|
||||
@@ -1846,15 +1866,15 @@ class Misc:
|
||||
return '<%s.%s object %s>' % (
|
||||
self.__class__.__module__, self.__class__.__qualname__, self._w)
|
||||
|
||||
# Pack methods that apply to the master
|
||||
# Pack methods that apply to the container widget
|
||||
_noarg_ = ['_noarg_']
|
||||
|
||||
def pack_propagate(self, flag=_noarg_):
|
||||
"""Set or get the status for propagation of geometry information.
|
||||
|
||||
A boolean argument specifies whether the geometry information
|
||||
of the slaves will determine the size of this widget. If no argument
|
||||
is given the current setting will be returned.
|
||||
A boolean argument specifies whether the size of this container will
|
||||
be determined by the geometry information of its content.
|
||||
If no argument is given the current setting will be returned.
|
||||
"""
|
||||
if flag is Misc._noarg_:
|
||||
return self._getboolean(self.tk.call(
|
||||
@@ -1865,28 +1885,28 @@ class Misc:
|
||||
propagate = pack_propagate
|
||||
|
||||
def pack_slaves(self):
|
||||
"""Return a list of all slaves of this widget
|
||||
in its packing order."""
|
||||
"""Returns a list of all of the content widgets in the packing order
|
||||
for this container."""
|
||||
return [self._nametowidget(x) for x in
|
||||
self.tk.splitlist(
|
||||
self.tk.call('pack', 'slaves', self._w))]
|
||||
|
||||
slaves = pack_slaves
|
||||
|
||||
# Place method that applies to the master
|
||||
# Place method that applies to the container widget
|
||||
def place_slaves(self):
|
||||
"""Return a list of all slaves of this widget
|
||||
in its packing order."""
|
||||
"""Returns a list of all the content widgets for which this widget is
|
||||
the container."""
|
||||
return [self._nametowidget(x) for x in
|
||||
self.tk.splitlist(
|
||||
self.tk.call(
|
||||
'place', 'slaves', self._w))]
|
||||
|
||||
# Grid methods that apply to the master
|
||||
# Grid methods that apply to the container widget
|
||||
|
||||
def grid_anchor(self, anchor=None): # new in Tk 8.5
|
||||
"""The anchor value controls how to place the grid within the
|
||||
master when no row/column has any weight.
|
||||
container widget when no row/column has any weight.
|
||||
|
||||
The default anchor is nw."""
|
||||
self.tk.call('grid', 'anchor', self._w, anchor)
|
||||
@@ -1903,7 +1923,7 @@ class Misc:
|
||||
starts at that cell.
|
||||
|
||||
The returned integers specify the offset of the upper left
|
||||
corner in the master widget and the width and height.
|
||||
corner in the container widget and the width and height.
|
||||
"""
|
||||
args = ('grid', 'bbox', self._w)
|
||||
if column is not None and row is not None:
|
||||
@@ -1952,7 +1972,7 @@ class Misc:
|
||||
def grid_columnconfigure(self, index, cnf={}, **kw):
|
||||
"""Configure column INDEX of a grid.
|
||||
|
||||
Valid resources are minsize (minimum size of the column),
|
||||
Valid options are minsize (minimum size of the column),
|
||||
weight (how much does additional space propagate to this column)
|
||||
and pad (how much space to let additionally)."""
|
||||
return self._grid_configure('columnconfigure', index, cnf, kw)
|
||||
@@ -1961,7 +1981,7 @@ class Misc:
|
||||
|
||||
def grid_location(self, x, y):
|
||||
"""Return a tuple of column and row which identify the cell
|
||||
at which the pixel at position X and Y inside the master
|
||||
at which the pixel at position X and Y inside the container
|
||||
widget is located."""
|
||||
return self._getints(
|
||||
self.tk.call(
|
||||
@@ -1970,9 +1990,9 @@ class Misc:
|
||||
def grid_propagate(self, flag=_noarg_):
|
||||
"""Set or get the status for propagation of geometry information.
|
||||
|
||||
A boolean argument specifies whether the geometry information
|
||||
of the slaves will determine the size of this widget. If no argument
|
||||
is given, the current setting will be returned.
|
||||
A boolean argument specifies whether the size of this container will
|
||||
be determined by the geometry information of its content.
|
||||
If no argument is given the current setting will be returned.
|
||||
"""
|
||||
if flag is Misc._noarg_:
|
||||
return self._getboolean(self.tk.call(
|
||||
@@ -1983,7 +2003,7 @@ class Misc:
|
||||
def grid_rowconfigure(self, index, cnf={}, **kw):
|
||||
"""Configure row INDEX of a grid.
|
||||
|
||||
Valid resources are minsize (minimum size of the row),
|
||||
Valid options are minsize (minimum size of the row),
|
||||
weight (how much does additional space propagate to this row)
|
||||
and pad (how much space to let additionally)."""
|
||||
return self._grid_configure('rowconfigure', index, cnf, kw)
|
||||
@@ -1998,8 +2018,13 @@ class Misc:
|
||||
size = grid_size
|
||||
|
||||
def grid_slaves(self, row=None, column=None):
|
||||
"""Return a list of all slaves of this widget
|
||||
in its packing order."""
|
||||
"""Returns a list of the content widgets.
|
||||
|
||||
If no arguments are supplied, a list of all of the content in this
|
||||
container widget is returned, most recently managed first.
|
||||
If ROW or COLUMN is specified, only the content in the row or
|
||||
column is returned.
|
||||
"""
|
||||
args = ()
|
||||
if row is not None:
|
||||
args = args + ('-row', row)
|
||||
@@ -2451,9 +2476,7 @@ class Tk(Misc, Wm):
|
||||
self.tk = None
|
||||
if baseName is None:
|
||||
import os
|
||||
# TODO: RUSTPYTHON
|
||||
# baseName = os.path.basename(sys.argv[0])
|
||||
baseName = "" # sys.argv[0]
|
||||
baseName = os.path.basename(sys.argv[0])
|
||||
baseName, ext = os.path.splitext(baseName)
|
||||
if ext not in ('.py', '.pyc'):
|
||||
baseName = baseName + ext
|
||||
@@ -2587,8 +2610,8 @@ class Pack:
|
||||
before=widget - pack it before you will pack widget
|
||||
expand=bool - expand widget if parent size grows
|
||||
fill=NONE or X or Y or BOTH - fill widget if widget grows
|
||||
in=master - use master to contain this widget
|
||||
in_=master - see 'in' option description
|
||||
in=container - use the container widget to contain this widget
|
||||
in_=container - see 'in' option description
|
||||
ipadx=amount - add internal padding in x direction
|
||||
ipady=amount - add internal padding in y direction
|
||||
padx=amount - add padding in x direction
|
||||
@@ -2627,25 +2650,31 @@ class Place:
|
||||
|
||||
def place_configure(self, cnf={}, **kw):
|
||||
"""Place a widget in the parent widget. Use as options:
|
||||
in=master - master relative to which the widget is placed
|
||||
in_=master - see 'in' option description
|
||||
x=amount - locate anchor of this widget at position x of master
|
||||
y=amount - locate anchor of this widget at position y of master
|
||||
in=container - the container widget relative to which this widget is
|
||||
placed
|
||||
in_=container - see 'in' option description
|
||||
x=amount - locate anchor of this widget at position x of the
|
||||
container widget
|
||||
y=amount - locate anchor of this widget at position y of the
|
||||
container widget
|
||||
relx=amount - locate anchor of this widget between 0.0 and 1.0
|
||||
relative to width of master (1.0 is right edge)
|
||||
relative to width of the container widget (1.0 is
|
||||
right edge)
|
||||
rely=amount - locate anchor of this widget between 0.0 and 1.0
|
||||
relative to height of master (1.0 is bottom edge)
|
||||
anchor=NSEW (or subset) - position anchor according to given direction
|
||||
relative to height of the container widget (1.0 is
|
||||
bottom edge)
|
||||
anchor=NSEW (or subset) - position anchor according to given
|
||||
direction
|
||||
width=amount - width of this widget in pixel
|
||||
height=amount - height of this widget in pixel
|
||||
relwidth=amount - width of this widget between 0.0 and 1.0
|
||||
relative to width of master (1.0 is the same width
|
||||
as the master)
|
||||
relative to width of the container widget (1.0 is
|
||||
the same width as the container widget)
|
||||
relheight=amount - height of this widget between 0.0 and 1.0
|
||||
relative to height of master (1.0 is the same
|
||||
height as the master)
|
||||
relative to height of the container widget (1.0
|
||||
is the same height as the container widget)
|
||||
bordermode="inside" or "outside" - whether to take border width of
|
||||
master widget into account
|
||||
the container widget into account
|
||||
"""
|
||||
self.tk.call(
|
||||
('place', 'configure', self._w)
|
||||
@@ -2681,8 +2710,8 @@ class Grid:
|
||||
"""Position a widget in the parent widget in a grid. Use as options:
|
||||
column=number - use cell identified with given column (starting with 0)
|
||||
columnspan=number - this widget will span several columns
|
||||
in=master - use master to contain this widget
|
||||
in_=master - see 'in' option description
|
||||
in=container - use the container widget to contain this widget
|
||||
in_=container - see 'in' option description
|
||||
ipadx=amount - add internal padding in x direction
|
||||
ipady=amount - add internal padding in y direction
|
||||
padx=amount - add padding in x direction
|
||||
@@ -2805,7 +2834,7 @@ class Toplevel(BaseWidget, Wm):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a toplevel widget with the parent MASTER.
|
||||
|
||||
Valid resource names: background, bd, bg, borderwidth, class,
|
||||
Valid option names: background, bd, bg, borderwidth, class,
|
||||
colormap, container, cursor, height, highlightbackground,
|
||||
highlightcolor, highlightthickness, menu, relief, screen, takefocus,
|
||||
use, visual, width."""
|
||||
@@ -2882,7 +2911,7 @@ class Canvas(Widget, XView, YView):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a canvas widget with the parent MASTER.
|
||||
|
||||
Valid resource names: background, bd, bg, borderwidth, closeenough,
|
||||
Valid option names: background, bd, bg, borderwidth, closeenough,
|
||||
confine, cursor, height, highlightbackground, highlightcolor,
|
||||
highlightthickness, insertbackground, insertborderwidth,
|
||||
insertofftime, insertontime, insertwidth, offset, relief,
|
||||
@@ -3091,16 +3120,14 @@ class Canvas(Widget, XView, YView):
|
||||
self.tk.call((self._w, 'insert') + args)
|
||||
|
||||
def itemcget(self, tagOrId, option):
|
||||
"""Return the resource value for an OPTION for item TAGORID."""
|
||||
"""Return the value of OPTION for item TAGORID."""
|
||||
return self.tk.call(
|
||||
(self._w, 'itemcget') + (tagOrId, '-'+option))
|
||||
|
||||
def itemconfigure(self, tagOrId, cnf=None, **kw):
|
||||
"""Configure resources of an item TAGORID.
|
||||
"""Query or modify the configuration options of an item TAGORID.
|
||||
|
||||
The values for resources are specified as keyword
|
||||
arguments. To get an overview about
|
||||
the allowed keyword arguments call the method without arguments.
|
||||
Similar to configure() except that it applies to the specified item.
|
||||
"""
|
||||
return self._configure(('itemconfigure', tagOrId), cnf, kw)
|
||||
|
||||
@@ -3192,7 +3219,7 @@ class Checkbutton(Widget):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a checkbutton widget with the parent MASTER.
|
||||
|
||||
Valid resource names: activebackground, activeforeground, anchor,
|
||||
Valid option names: activebackground, activeforeground, anchor,
|
||||
background, bd, bg, bitmap, borderwidth, command, cursor,
|
||||
disabledforeground, fg, font, foreground, height,
|
||||
highlightbackground, highlightcolor, highlightthickness, image,
|
||||
@@ -3223,7 +3250,7 @@ class Checkbutton(Widget):
|
||||
self.tk.call(self._w, 'flash')
|
||||
|
||||
def invoke(self):
|
||||
"""Toggle the button and invoke a command if given as resource."""
|
||||
"""Toggle the button and invoke a command if given as option."""
|
||||
return self.tk.call(self._w, 'invoke')
|
||||
|
||||
def select(self):
|
||||
@@ -3241,7 +3268,7 @@ class Entry(Widget, XView):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct an entry widget with the parent MASTER.
|
||||
|
||||
Valid resource names: background, bd, bg, borderwidth, cursor,
|
||||
Valid option names: background, bd, bg, borderwidth, cursor,
|
||||
exportselection, fg, font, foreground, highlightbackground,
|
||||
highlightcolor, highlightthickness, insertbackground,
|
||||
insertborderwidth, insertofftime, insertontime, insertwidth,
|
||||
@@ -3327,7 +3354,7 @@ class Frame(Widget):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a frame widget with the parent MASTER.
|
||||
|
||||
Valid resource names: background, bd, bg, borderwidth, class,
|
||||
Valid option names: background, bd, bg, borderwidth, class,
|
||||
colormap, container, cursor, height, highlightbackground,
|
||||
highlightcolor, highlightthickness, relief, takefocus, visual, width."""
|
||||
cnf = _cnfmerge((cnf, kw))
|
||||
@@ -3371,7 +3398,7 @@ class Listbox(Widget, XView, YView):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a listbox widget with the parent MASTER.
|
||||
|
||||
Valid resource names: background, bd, bg, borderwidth, cursor,
|
||||
Valid option names: background, bd, bg, borderwidth, cursor,
|
||||
exportselection, fg, font, foreground, height, highlightbackground,
|
||||
highlightcolor, highlightthickness, relief, selectbackground,
|
||||
selectborderwidth, selectforeground, selectmode, setgrid, takefocus,
|
||||
@@ -3464,18 +3491,15 @@ class Listbox(Widget, XView, YView):
|
||||
return self.tk.getint(self.tk.call(self._w, 'size'))
|
||||
|
||||
def itemcget(self, index, option):
|
||||
"""Return the resource value for an ITEM and an OPTION."""
|
||||
"""Return the value of OPTION for item at INDEX."""
|
||||
return self.tk.call(
|
||||
(self._w, 'itemcget') + (index, '-'+option))
|
||||
|
||||
def itemconfigure(self, index, cnf=None, **kw):
|
||||
"""Configure resources of an ITEM.
|
||||
"""Query or modify the configuration options of an item at INDEX.
|
||||
|
||||
The values for resources are specified as keyword arguments.
|
||||
To get an overview about the allowed keyword arguments
|
||||
call the method without arguments.
|
||||
Valid resource names: background, bg, foreground, fg,
|
||||
selectbackground, selectforeground."""
|
||||
Similar to configure() except that it applies to the specified item.
|
||||
"""
|
||||
return self._configure(('itemconfigure', index), cnf, kw)
|
||||
|
||||
itemconfig = itemconfigure
|
||||
@@ -3487,7 +3511,7 @@ class Menu(Widget):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct menu widget with the parent MASTER.
|
||||
|
||||
Valid resource names: activebackground, activeborderwidth,
|
||||
Valid option names: activebackground, activeborderwidth,
|
||||
activeforeground, background, bd, bg, borderwidth, cursor,
|
||||
disabledforeground, fg, font, foreground, postcommand, relief,
|
||||
selectcolor, takefocus, tearoff, tearoffcommand, title, type."""
|
||||
@@ -3568,11 +3592,15 @@ class Menu(Widget):
|
||||
self.tk.call(self._w, 'delete', index1, index2)
|
||||
|
||||
def entrycget(self, index, option):
|
||||
"""Return the resource value of a menu item for OPTION at INDEX."""
|
||||
"""Return the value of OPTION for a menu item at INDEX."""
|
||||
return self.tk.call(self._w, 'entrycget', index, '-' + option)
|
||||
|
||||
def entryconfigure(self, index, cnf=None, **kw):
|
||||
"""Configure a menu item at INDEX."""
|
||||
"""Query or modify the configuration options of a menu item at INDEX.
|
||||
|
||||
Similar to configure() except that it applies to the specified
|
||||
menu item.
|
||||
"""
|
||||
return self._configure(('entryconfigure', index), cnf, kw)
|
||||
|
||||
entryconfig = entryconfigure
|
||||
@@ -3630,7 +3658,7 @@ class Radiobutton(Widget):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a radiobutton widget with the parent MASTER.
|
||||
|
||||
Valid resource names: activebackground, activeforeground, anchor,
|
||||
Valid option names: activebackground, activeforeground, anchor,
|
||||
background, bd, bg, bitmap, borderwidth, command, cursor,
|
||||
disabledforeground, fg, font, foreground, height,
|
||||
highlightbackground, highlightcolor, highlightthickness, image,
|
||||
@@ -3649,7 +3677,7 @@ class Radiobutton(Widget):
|
||||
self.tk.call(self._w, 'flash')
|
||||
|
||||
def invoke(self):
|
||||
"""Toggle the button and invoke a command if given as resource."""
|
||||
"""Toggle the button and invoke a command if given as option."""
|
||||
return self.tk.call(self._w, 'invoke')
|
||||
|
||||
def select(self):
|
||||
@@ -3663,7 +3691,7 @@ class Scale(Widget):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a scale widget with the parent MASTER.
|
||||
|
||||
Valid resource names: activebackground, background, bigincrement, bd,
|
||||
Valid option names: activebackground, background, bigincrement, bd,
|
||||
bg, borderwidth, command, cursor, digits, fg, font, foreground, from,
|
||||
highlightbackground, highlightcolor, highlightthickness, label,
|
||||
length, orient, relief, repeatdelay, repeatinterval, resolution,
|
||||
@@ -3702,7 +3730,7 @@ class Scrollbar(Widget):
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
"""Construct a scrollbar widget with the parent MASTER.
|
||||
|
||||
Valid resource names: activebackground, activerelief,
|
||||
Valid option names: activebackground, activerelief,
|
||||
background, bd, bg, borderwidth, command, cursor,
|
||||
elementborderwidth, highlightbackground,
|
||||
highlightcolor, highlightthickness, jump, orient,
|
||||
@@ -3946,7 +3974,11 @@ class Text(Widget, XView, YView):
|
||||
return self.tk.call(self._w, "image", "cget", index, option)
|
||||
|
||||
def image_configure(self, index, cnf=None, **kw):
|
||||
"""Configure an embedded image at INDEX."""
|
||||
"""Query or modify the configuration options of an embedded image at INDEX.
|
||||
|
||||
Similar to configure() except that it applies to the specified
|
||||
embedded image.
|
||||
"""
|
||||
return self._configure(('image', 'configure', index), cnf, kw)
|
||||
|
||||
def image_create(self, index, cnf={}, **kw):
|
||||
@@ -4084,7 +4116,10 @@ class Text(Widget, XView, YView):
|
||||
return self.tk.call(self._w, 'tag', 'cget', tagName, option)
|
||||
|
||||
def tag_configure(self, tagName, cnf=None, **kw):
|
||||
"""Configure a tag TAGNAME."""
|
||||
"""Query or modify the configuration options of a tag TAGNAME.
|
||||
|
||||
Similar to configure() except that it applies to the specified tag.
|
||||
"""
|
||||
return self._configure(('tag', 'configure', tagName), cnf, kw)
|
||||
|
||||
tag_config = tag_configure
|
||||
@@ -4142,7 +4177,11 @@ class Text(Widget, XView, YView):
|
||||
return self.tk.call(self._w, 'window', 'cget', index, option)
|
||||
|
||||
def window_configure(self, index, cnf=None, **kw):
|
||||
"""Configure an embedded window at INDEX."""
|
||||
"""Query or modify the configuration options of an embedded window at INDEX.
|
||||
|
||||
Similar to configure() except that it applies to the specified
|
||||
embedded window.
|
||||
"""
|
||||
return self._configure(('window', 'configure', index), cnf, kw)
|
||||
|
||||
window_config = window_configure
|
||||
@@ -4182,12 +4221,12 @@ class OptionMenu(Menubutton):
|
||||
|
||||
def __init__(self, master, variable, value, *values, **kwargs):
|
||||
"""Construct an optionmenu widget with the parent MASTER, with
|
||||
the resource textvariable set to VARIABLE, the initially selected
|
||||
the option textvariable set to VARIABLE, the initially selected
|
||||
value VALUE, the other menu values VALUES and an additional
|
||||
keyword argument command."""
|
||||
kw = {"borderwidth": 2, "textvariable": variable,
|
||||
"indicatoron": 1, "relief": RAISED, "anchor": "c",
|
||||
"highlightthickness": 2}
|
||||
"highlightthickness": 2, "name": kwargs.pop("name", None)}
|
||||
Widget.__init__(self, master, "menubutton", kw)
|
||||
self.widgetName = 'tk_optionMenu'
|
||||
menu = self.__menu = Menu(self, name="menu", tearoff=0)
|
||||
@@ -4284,7 +4323,7 @@ class PhotoImage(Image):
|
||||
def __init__(self, name=None, cnf={}, master=None, **kw):
|
||||
"""Create an image with NAME.
|
||||
|
||||
Valid resource names: data, format, file, gamma, height, palette,
|
||||
Valid option names: data, format, file, gamma, height, palette,
|
||||
width."""
|
||||
Image.__init__(self, 'photo', name, cnf, master, **kw)
|
||||
|
||||
@@ -4494,7 +4533,7 @@ class PhotoImage(Image):
|
||||
The FORMAT option specifies the name of the image file format
|
||||
handler to be used. If this option is not given, this method uses
|
||||
a format that consists of a tuple (one element per row) of strings
|
||||
containings space separated (one element per pixel/column) colors
|
||||
containing space-separated (one element per pixel/column) colors
|
||||
in “#RRGGBB” format (where RR is a pair of hexadecimal digits for
|
||||
the red channel, GG for green, and BB for blue).
|
||||
|
||||
@@ -4547,7 +4586,7 @@ class BitmapImage(Image):
|
||||
def __init__(self, name=None, cnf={}, master=None, **kw):
|
||||
"""Create a bitmap with NAME.
|
||||
|
||||
Valid resource names: background, data, file, foreground, maskdata, maskfile."""
|
||||
Valid option names: background, data, file, foreground, maskdata, maskfile."""
|
||||
Image.__init__(self, 'bitmap', name, cnf, master, **kw)
|
||||
|
||||
|
||||
@@ -4865,26 +4904,17 @@ class PanedWindow(Widget):
|
||||
return self.sash("place", index, x, y)
|
||||
|
||||
def panecget(self, child, option):
|
||||
"""Query a management option for window.
|
||||
|
||||
Option may be any value allowed by the paneconfigure subcommand
|
||||
"""
|
||||
"""Return the value of option for a child window."""
|
||||
return self.tk.call(
|
||||
(self._w, 'panecget') + (child, '-'+option))
|
||||
|
||||
def paneconfigure(self, tagOrId, cnf=None, **kw):
|
||||
"""Query or modify the management options for window.
|
||||
"""Query or modify the configuration options for a child window.
|
||||
|
||||
If no option is specified, returns a list describing all
|
||||
of the available options for pathName. If option is
|
||||
specified with no value, then the command returns a list
|
||||
describing the one named option (this list will be identical
|
||||
to the corresponding sublist of the value returned if no
|
||||
option is specified). If one or more option-value pairs are
|
||||
specified, then the command modifies the given widget
|
||||
option(s) to have the given value(s); in this case the
|
||||
command returns an empty string. The following options
|
||||
are supported:
|
||||
Similar to configure() except that it applies to the specified
|
||||
window.
|
||||
|
||||
The following options are supported:
|
||||
|
||||
after window
|
||||
Insert the window after the window specified. window
|
||||
|
||||
Vendored
+1
-1
@@ -23,7 +23,7 @@ class ScrolledText(Text):
|
||||
self.vbar = Scrollbar(self.frame)
|
||||
self.vbar.pack(side=RIGHT, fill=Y)
|
||||
|
||||
kw.update({'yscrollcommand': self.vbar.set})
|
||||
kw['yscrollcommand'] = self.vbar.set
|
||||
Text.__init__(self, self.frame, **kw)
|
||||
self.pack(side=LEFT, fill=BOTH, expand=True)
|
||||
self.vbar['command'] = self.yview
|
||||
|
||||
Vendored
+5
-2
@@ -321,6 +321,8 @@ def _tclobj_to_py(val):
|
||||
elif hasattr(val, 'typename'): # some other (single) Tcl object
|
||||
val = _convert_stringval(val)
|
||||
|
||||
if isinstance(val, tuple) and len(val) == 0:
|
||||
return ''
|
||||
return val
|
||||
|
||||
def tclobjs_to_py(adict):
|
||||
@@ -1587,7 +1589,7 @@ class OptionMenu(Menubutton):
|
||||
|
||||
def __init__(self, master, variable, default=None, *values, **kwargs):
|
||||
"""Construct a themed OptionMenu widget with master as the parent,
|
||||
the resource textvariable set to variable, the initially selected
|
||||
the option textvariable set to variable, the initially selected
|
||||
value specified by the default parameter, the menu values given by
|
||||
*values and additional keywords.
|
||||
|
||||
@@ -1601,7 +1603,8 @@ class OptionMenu(Menubutton):
|
||||
A callback that will be invoked after selecting an item.
|
||||
"""
|
||||
kw = {'textvariable': variable, 'style': kwargs.pop('style', None),
|
||||
'direction': kwargs.pop('direction', None)}
|
||||
'direction': kwargs.pop('direction', None),
|
||||
'name': kwargs.pop('name', None)}
|
||||
Menubutton.__init__(self, master, **kw)
|
||||
self['menu'] = tkinter.Menu(self, tearoff=False)
|
||||
|
||||
|
||||
Vendored
+13
-1
@@ -4,6 +4,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from types import MappingProxyType
|
||||
|
||||
from ._re import (
|
||||
@@ -18,10 +19,17 @@ from ._re import (
|
||||
TYPE_CHECKING = False
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable
|
||||
from typing import IO, Any
|
||||
from typing import IO, Any, Final
|
||||
|
||||
from ._types import Key, ParseFloat, Pos
|
||||
|
||||
# Pathologically excessive number of parts in a key runs into quadratic
|
||||
# behavior (e.g. in Flags.is_).
|
||||
# Even if keys aren't currently parsed using recursion, they name a
|
||||
# recursive structure, so it makes sense to limit it using getrecursionlimit()
|
||||
# and RecursionError.
|
||||
MAX_KEY_PARTS: Final = sys.getrecursionlimit()
|
||||
|
||||
ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
|
||||
|
||||
# Neither of these sets include quotation mark or backslash. They are
|
||||
@@ -462,6 +470,10 @@ def parse_key(src: str, pos: Pos) -> tuple[Pos, Key]:
|
||||
pos = skip_chars(src, pos, TOML_WS)
|
||||
pos, key_part = parse_key_part(src, pos)
|
||||
key += (key_part,)
|
||||
if len(key) > MAX_KEY_PARTS:
|
||||
raise RecursionError(
|
||||
f"TOML key has more than the allowed {MAX_KEY_PARTS} parts"
|
||||
)
|
||||
pos = skip_chars(src, pos, TOML_WS)
|
||||
|
||||
|
||||
|
||||
Vendored
-2
@@ -12,6 +12,4 @@ pretty = True
|
||||
# Enable most stricter settings
|
||||
enable_error_code = ignore-without-code
|
||||
strict = True
|
||||
strict_bytes = True
|
||||
local_partial_types = True
|
||||
warn_unreachable = True
|
||||
Vendored
+9
-10
@@ -74,10 +74,10 @@ def extract_tb(tb, limit=None):
|
||||
This is useful for alternate formatting of stack traces. If
|
||||
'limit' is omitted or None, all entries are extracted. A
|
||||
pre-processed stack trace entry is a FrameSummary object
|
||||
containing attributes filename, lineno, name, and line
|
||||
representing the information that is usually printed for a stack
|
||||
trace. The line is a string with leading and trailing
|
||||
whitespace stripped; if the source is not available it is None.
|
||||
representing the information that is usually printed for a
|
||||
stack trace. The line attribute is a string with
|
||||
leading and trailing whitespace stripped; if the source is not
|
||||
available the corresponding attribute is None.
|
||||
"""
|
||||
return StackSummary._extract_from_extended_frame_gen(
|
||||
_walk_tb_with_full_positions(tb), limit=limit)
|
||||
@@ -253,9 +253,8 @@ def extract_stack(f=None, limit=None):
|
||||
|
||||
The return value has the same format as for extract_tb(). The
|
||||
optional 'f' and 'limit' arguments have the same meaning as for
|
||||
print_stack(). Each item in the list is a quadruple (filename,
|
||||
line number, function name, text), and the entries are in order
|
||||
from oldest to newest stack frame.
|
||||
print_stack(). Each item in the list is a FrameSummary object,
|
||||
and the entries are in order from oldest to newest stack frame.
|
||||
"""
|
||||
if f is None:
|
||||
f = sys._getframe().f_back
|
||||
@@ -283,7 +282,7 @@ class FrameSummary:
|
||||
active when the frame was captured.
|
||||
- :attr:`name` The name of the function or method that was executing
|
||||
when the frame was captured.
|
||||
- :attr:`line` The text from the linecache module for the
|
||||
- :attr:`line` The text from the linecache module for the line
|
||||
of code that was running when the frame was captured.
|
||||
- :attr:`locals` Either None if locals were not supplied, or a dict
|
||||
mapping the name to the repr() of the variable.
|
||||
@@ -958,7 +957,7 @@ def _extract_caret_anchors_from_line_segment(segment):
|
||||
_WIDE_CHAR_SPECIFIERS = "WF"
|
||||
|
||||
def _display_width(line, offset=None):
|
||||
"""Calculate the extra amount of width space the given source
|
||||
"""Calculate the amount of width space the given source
|
||||
code segment might take if it were to be displayed on a fixed
|
||||
width output device. Supports wide unicode characters and emojis."""
|
||||
|
||||
@@ -1044,7 +1043,7 @@ class TracebackException:
|
||||
def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
|
||||
lookup_lines=True, capture_locals=False, compact=False,
|
||||
max_group_width=15, max_group_depth=10, save_exc_type=True, _seen=None):
|
||||
# NB: we need to accept exc_traceback, exc_value, exc_traceback to
|
||||
# NB: we need to accept exc_type, exc_value, exc_traceback to
|
||||
# permit backwards compat with the existing API, otherwise we
|
||||
# need stub thunk objects just to glue it together.
|
||||
# Handle loops in __cause__ or __context__.
|
||||
|
||||
Vendored
+11
-10
@@ -189,18 +189,19 @@ def get_original_bases(cls, /):
|
||||
class DynamicClassAttribute:
|
||||
"""Route attribute access on a class to __getattr__.
|
||||
|
||||
This is a descriptor, used to define attributes that act differently when
|
||||
accessed through an instance and through a class. Instance access remains
|
||||
normal, but access to an attribute through a class will be routed to the
|
||||
class's __getattr__ method; this is done by raising AttributeError.
|
||||
This is a descriptor, used to define attributes that act differently
|
||||
when accessed through an instance and through a class. Instance access
|
||||
remains normal, but access to an attribute through a class will be
|
||||
routed to the class's __getattr__ method; this is done by raising
|
||||
AttributeError.
|
||||
|
||||
This allows one to have properties active on an instance, and have virtual
|
||||
attributes on the class with the same name. (Enum used this between Python
|
||||
versions 3.4 - 3.9 .)
|
||||
This allows one to have properties active on an instance, and have
|
||||
virtual attributes on the class with the same name. (Enum used this
|
||||
between Python versions 3.4 - 3.9 .)
|
||||
|
||||
Subclass from this to use a different method of accessing virtual attributes
|
||||
and still be treated properly by the inspect module. (Enum uses this since
|
||||
Python 3.10 .)
|
||||
Subclass from this to use a different method of accessing virtual
|
||||
attributes and still be treated properly by the inspect module. (Enum
|
||||
uses this since Python 3.10 .)
|
||||
|
||||
"""
|
||||
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
|
||||
|
||||
Vendored
+62
-62
@@ -5,7 +5,7 @@ Among other things, the module includes the following:
|
||||
* Generic, Protocol, and internal machinery to support generic aliases.
|
||||
All subscripted types like X[int], Union[int, str] are generic aliases.
|
||||
* Various "special forms" that have unique meanings in type annotations:
|
||||
NoReturn, Never, ClassVar, Self, Concatenate, Unpack, and others.
|
||||
Any, Never, ClassVar, Self, Concatenate, Unpack, and others.
|
||||
* Classes whose instances can be type arguments to generic classes and functions:
|
||||
TypeVar, ParamSpec, TypeVarTuple.
|
||||
* Public helper functions: get_type_hints, overload, cast, final, and others.
|
||||
@@ -588,12 +588,12 @@ class _AnyMeta(type):
|
||||
class Any(metaclass=_AnyMeta):
|
||||
"""Special type indicating an unconstrained type.
|
||||
|
||||
- Any is compatible with every type.
|
||||
- Any assumed to have all methods.
|
||||
- All values assumed to be instances of Any.
|
||||
- Any is assignable to every type.
|
||||
- Any assumed to have all methods and attributes.
|
||||
- All values are assignable to Any.
|
||||
|
||||
Note that all the above statements are true from the point of view of
|
||||
static type checkers. At runtime, Any should not be used with instance
|
||||
static type checkers. At runtime, Any cannot be used with instance
|
||||
checks.
|
||||
"""
|
||||
|
||||
@@ -712,7 +712,7 @@ def ClassVar(self, parameters):
|
||||
|
||||
ClassVar accepts only types and cannot be further subscribed.
|
||||
|
||||
Note that ClassVar is not a class itself, and should not
|
||||
Note that ClassVar is not a class itself, and cannot
|
||||
be used with isinstance() or issubclass().
|
||||
"""
|
||||
item = _type_check(parameters, f'{self} accepts only single type.', allow_special_forms=True)
|
||||
@@ -742,7 +742,7 @@ def Final(self, parameters):
|
||||
|
||||
@_SpecialForm
|
||||
def Optional(self, parameters):
|
||||
"""Optional[X] is equivalent to Union[X, None]."""
|
||||
"""Optional[X] is equivalent to X | None."""
|
||||
arg = _type_check(parameters, f"{self} requires a single type.")
|
||||
return Union[arg, type(None)]
|
||||
|
||||
@@ -785,7 +785,7 @@ def Literal(self, *parameters):
|
||||
def TypeAlias(self, parameters):
|
||||
"""Special form for marking type aliases.
|
||||
|
||||
Use TypeAlias to indicate that an assignment should
|
||||
TypeAlias can be used to indicate that an assignment should
|
||||
be recognized as a proper type alias definition by type
|
||||
checkers.
|
||||
|
||||
@@ -1780,7 +1780,7 @@ def Unpack(self, parameters):
|
||||
def foo(**kwargs: Unpack[Movie]): ...
|
||||
|
||||
Note that there is only some runtime checking of this operator. Not
|
||||
everything the runtime allows may be accepted by static type checkers.
|
||||
everything the runtime allows is accepted by static type checkers.
|
||||
|
||||
For more information, see PEPs 646 and 692.
|
||||
"""
|
||||
@@ -2261,7 +2261,7 @@ def runtime_checkable(cls):
|
||||
Such protocol can be used with isinstance() and issubclass().
|
||||
Raise TypeError if applied to a non-protocol class.
|
||||
This allows a simple-minded structural check very similar to
|
||||
one trick ponies in collections.abc such as Iterable.
|
||||
one-trick ponies in collections.abc such as Iterable.
|
||||
|
||||
For example::
|
||||
|
||||
@@ -2328,8 +2328,8 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
|
||||
*, format=None):
|
||||
"""Return type hints for an object.
|
||||
|
||||
This is often the same as obj.__annotations__, but it handles
|
||||
forward references encoded as string literals and recursively replaces all
|
||||
This is often the same as annotationlib.get_annotations(obj) or obj.__annotations__,
|
||||
but it handles forward references encoded as string literals and recursively replaces all
|
||||
'Annotated[T, ...]' with 'T' (unless 'include_extras=True').
|
||||
|
||||
The argument may be a module, class, method, or function. The annotations
|
||||
@@ -2541,7 +2541,7 @@ def get_args(tp):
|
||||
|
||||
|
||||
def is_typeddict(tp):
|
||||
"""Check if an annotation is a TypedDict class.
|
||||
"""Check if an object is a TypedDict class.
|
||||
|
||||
For example::
|
||||
|
||||
@@ -2655,20 +2655,9 @@ _overload_registry = defaultdict(functools.partial(defaultdict, dict))
|
||||
def overload(func):
|
||||
"""Decorator for overloaded functions/methods.
|
||||
|
||||
In a stub file, place two or more stub definitions for the same
|
||||
function in a row, each decorated with @overload.
|
||||
|
||||
For example::
|
||||
|
||||
@overload
|
||||
def utf8(value: None) -> None: ...
|
||||
@overload
|
||||
def utf8(value: bytes) -> bytes: ...
|
||||
@overload
|
||||
def utf8(value: str) -> bytes: ...
|
||||
|
||||
In a non-stub file (i.e. a regular .py file), do the same but
|
||||
follow it with an implementation. The implementation should *not*
|
||||
In a non-stub file, place two or more stub definitions for the same
|
||||
function in a row, each decorated with @overload, followed
|
||||
by an implementation. The implementation should *not*
|
||||
be decorated with @overload::
|
||||
|
||||
@overload
|
||||
@@ -2680,6 +2669,16 @@ def overload(func):
|
||||
def utf8(value):
|
||||
... # implementation goes here
|
||||
|
||||
In a stub file or in an abstract method (for example, in a Protocol definition),
|
||||
the implementation may be omitted::
|
||||
|
||||
@overload
|
||||
def utf8(value: None) -> None: ...
|
||||
@overload
|
||||
def utf8(value: bytes) -> bytes: ...
|
||||
@overload
|
||||
def utf8(value: str) -> bytes: ...
|
||||
|
||||
The overloads for a function can be retrieved at runtime using the
|
||||
get_overloads() function.
|
||||
"""
|
||||
@@ -2714,7 +2713,7 @@ def final(f):
|
||||
"""Decorator to indicate final methods and final classes.
|
||||
|
||||
Use this decorator to indicate to type checkers that the decorated
|
||||
method cannot be overridden, and decorated class cannot be subclassed.
|
||||
method cannot be overridden, and the decorated class cannot be subclassed.
|
||||
|
||||
For example::
|
||||
|
||||
@@ -2756,7 +2755,7 @@ T_co = TypeVar('T_co', covariant=True) # Any type covariant containers.
|
||||
V_co = TypeVar('V_co', covariant=True) # Any type covariant containers.
|
||||
VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers.
|
||||
T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
|
||||
# Internal type variable used for Type[].
|
||||
# Internal type bound to class object types.
|
||||
CT_co = TypeVar('CT_co', covariant=True, bound=type)
|
||||
|
||||
|
||||
@@ -2847,7 +2846,7 @@ Type.__doc__ = \
|
||||
And a function that takes a class argument that's a subclass of
|
||||
User and returns an instance of the corresponding class::
|
||||
|
||||
def new_user[U](user_class: Type[U]) -> U:
|
||||
def new_user[U](user_class: type[U]) -> U:
|
||||
user = user_class()
|
||||
# (Here we could write the user object to a database)
|
||||
return user
|
||||
@@ -2860,7 +2859,7 @@ Type.__doc__ = \
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsInt(Protocol):
|
||||
"""An ABC with one abstract method __int__."""
|
||||
"""A protocol with one abstract method __int__."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -2871,7 +2870,7 @@ class SupportsInt(Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsFloat(Protocol):
|
||||
"""An ABC with one abstract method __float__."""
|
||||
"""A protocol with one abstract method __float__."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -2882,7 +2881,7 @@ class SupportsFloat(Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsComplex(Protocol):
|
||||
"""An ABC with one abstract method __complex__."""
|
||||
"""A protocol with one abstract method __complex__."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -2893,7 +2892,7 @@ class SupportsComplex(Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsBytes(Protocol):
|
||||
"""An ABC with one abstract method __bytes__."""
|
||||
"""A protocol with one abstract method __bytes__."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -2904,7 +2903,7 @@ class SupportsBytes(Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsIndex(Protocol):
|
||||
"""An ABC with one abstract method __index__."""
|
||||
"""A protocol with one abstract method __index__."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -2915,7 +2914,7 @@ class SupportsIndex(Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsAbs[T](Protocol):
|
||||
"""An ABC with one abstract method __abs__ that is covariant in its return type."""
|
||||
"""A protocol with one abstract method __abs__ that is covariant in its return type."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -2926,7 +2925,7 @@ class SupportsAbs[T](Protocol):
|
||||
|
||||
@runtime_checkable
|
||||
class SupportsRound[T](Protocol):
|
||||
"""An ABC with one abstract method __round__ that is covariant in its return type."""
|
||||
"""A protocol with one abstract method __round__ that is covariant in its return type."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -3043,7 +3042,7 @@ class NamedTupleMeta(type):
|
||||
|
||||
|
||||
def NamedTuple(typename, fields=_sentinel, /, **kwargs):
|
||||
"""Typed version of namedtuple.
|
||||
"""Typed version of collections.namedtuple.
|
||||
|
||||
Usage::
|
||||
|
||||
@@ -3055,8 +3054,8 @@ def NamedTuple(typename, fields=_sentinel, /, **kwargs):
|
||||
|
||||
Employee = collections.namedtuple('Employee', ['name', 'id'])
|
||||
|
||||
The resulting class has an extra __annotations__ attribute, giving a
|
||||
dict that maps field names to types. (The field names are also in
|
||||
The types for each field name can be retrieved by calling
|
||||
annotationlib.get_annotations(Employee). (The field names are also in
|
||||
the _fields attribute, which is part of the namedtuple API.)
|
||||
An alternative equivalent functional syntax is also accepted::
|
||||
|
||||
@@ -3145,7 +3144,7 @@ class _TypedDictMeta(type):
|
||||
|
||||
This method is called when TypedDict is subclassed,
|
||||
or when TypedDict is instantiated. This way
|
||||
TypedDict supports all three syntax forms described in its docstring.
|
||||
TypedDict classes can be created through both class-based and functional syntax.
|
||||
Subclasses and instances of TypedDict return actual dictionaries.
|
||||
"""
|
||||
for base in bases:
|
||||
@@ -3294,14 +3293,22 @@ def TypedDict(typename, fields=_sentinel, /, *, total=True):
|
||||
>>> Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
|
||||
True
|
||||
|
||||
The type info can be accessed via the Point2D.__annotations__ dict, and
|
||||
the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets.
|
||||
The type info can be accessed by calling annotationlib.get_annotations(Point2D), and
|
||||
via the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets.
|
||||
TypedDict supports an additional equivalent form::
|
||||
|
||||
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
|
||||
|
||||
By default, all keys must be present in a TypedDict. It is possible
|
||||
to override this by specifying totality::
|
||||
to override this by using the NotRequired and Required special forms::
|
||||
|
||||
class Point2D(TypedDict):
|
||||
x: int # the "x" key must always be present (Required is the default)
|
||||
y: NotRequired[int] # the "y" key can be omitted
|
||||
|
||||
This means that a Point2D TypedDict can have the "y" key omitted, but the "x" key must be present.
|
||||
Items are required by default, so the Required special form is not necessary in this example.
|
||||
In addition, the total argument to the TypedDict function can be used to make all items not required::
|
||||
|
||||
class Point2D(TypedDict, total=False):
|
||||
x: int
|
||||
@@ -3310,16 +3317,8 @@ def TypedDict(typename, fields=_sentinel, /, *, total=True):
|
||||
This means that a Point2D TypedDict can have any of the keys omitted. A type
|
||||
checker is only expected to support a literal False or True as the value of
|
||||
the total argument. True is the default, and makes all items defined in the
|
||||
class body be required.
|
||||
|
||||
The Required and NotRequired special forms can also be used to mark
|
||||
individual keys as being required or not required::
|
||||
|
||||
class Point2D(TypedDict):
|
||||
x: int # the "x" key must always be present (Required is the default)
|
||||
y: NotRequired[int] # the "y" key can be omitted
|
||||
|
||||
See PEP 655 for more details on Required and NotRequired.
|
||||
class body be required. The Required special form can be used to mark individual
|
||||
keys as required in a total=False TypedDict.
|
||||
|
||||
The ReadOnly special form can be used
|
||||
to mark individual keys as immutable for type checkers::
|
||||
@@ -3328,6 +3327,7 @@ def TypedDict(typename, fields=_sentinel, /, *, total=True):
|
||||
id: ReadOnly[int] # the "id" key must not be modified
|
||||
username: str # the "username" key can be changed
|
||||
|
||||
See PEPs 589, 655, and 705 for more information.
|
||||
"""
|
||||
if fields is _sentinel or fields is None:
|
||||
import warnings
|
||||
@@ -3374,7 +3374,7 @@ def Required(self, parameters):
|
||||
year: int
|
||||
|
||||
m = Movie(
|
||||
title='The Matrix', # typechecker error if key is omitted
|
||||
title='The Matrix', # type checker error if key is omitted
|
||||
year=1999,
|
||||
)
|
||||
|
||||
@@ -3396,7 +3396,7 @@ def NotRequired(self, parameters):
|
||||
year: NotRequired[int]
|
||||
|
||||
m = Movie(
|
||||
title='The Matrix', # typechecker error if key is omitted
|
||||
title='The Matrix', # type checker error if key is omitted
|
||||
year=1999,
|
||||
)
|
||||
"""
|
||||
@@ -3416,7 +3416,7 @@ def ReadOnly(self, parameters):
|
||||
|
||||
def mutate_movie(m: Movie) -> None:
|
||||
m["year"] = 1992 # allowed
|
||||
m["title"] = "The Matrix" # typechecker error
|
||||
m["title"] = "The Matrix" # type checker error
|
||||
|
||||
There is no runtime checking for this property.
|
||||
"""
|
||||
@@ -3503,8 +3503,8 @@ class IO(Generic[AnyStr]):
|
||||
classes (text vs. binary, read vs. write vs. read/write,
|
||||
append-only, unbuffered). The TextIO and BinaryIO subclasses
|
||||
below capture the distinctions between text vs. binary, which is
|
||||
pervasive in the interface; however we currently do not offer a
|
||||
way to track the other distinctions in the type system.
|
||||
pervasive in the interface. For more precise types, define a custom
|
||||
Protocol.
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
@@ -3594,7 +3594,7 @@ class IO(Generic[AnyStr]):
|
||||
|
||||
|
||||
class BinaryIO(IO[bytes]):
|
||||
"""Typed version of the return of open() in binary mode."""
|
||||
"""Typed approximation of the return of open() in binary mode."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -3608,7 +3608,7 @@ class BinaryIO(IO[bytes]):
|
||||
|
||||
|
||||
class TextIO(IO[str]):
|
||||
"""Typed version of the return of open() in text mode."""
|
||||
"""Typed approximation of the return of open() in text mode."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@@ -3675,7 +3675,7 @@ def dataclass_transform(
|
||||
field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = (),
|
||||
**kwargs: Any,
|
||||
) -> _IdentityCallable:
|
||||
"""Decorator to mark an object as providing dataclass-like behaviour.
|
||||
"""Decorator to mark an object as providing dataclass-like behavior.
|
||||
|
||||
The decorator can be applied to a function, class, or metaclass.
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -17,7 +17,7 @@ deactivate () {
|
||||
# Call hash to forget past locations. Without forgetting
|
||||
# past locations the $PATH changes we made may not be respected.
|
||||
# See "man bash" for more details. hash is usually a builtin of your shell
|
||||
hash -r 2> /dev/null
|
||||
hash -r 2> /dev/null || true
|
||||
|
||||
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||
@@ -73,4 +73,4 @@ fi
|
||||
|
||||
# Call hash to forget past commands. Without forgetting
|
||||
# past commands the $PATH changes we made may not be respected
|
||||
hash -r 2> /dev/null
|
||||
hash -r 2> /dev/null || true
|
||||
Vendored
+36
-28
@@ -566,8 +566,12 @@ class ZipInfo:
|
||||
return header + filename + extra
|
||||
|
||||
def _encodeFilenameFlags(self):
|
||||
if self.flag_bits & _MASK_UTF_FILENAME:
|
||||
encoding = 'ascii'
|
||||
else:
|
||||
encoding = 'cp437'
|
||||
try:
|
||||
return self.filename.encode('ascii'), self.flag_bits
|
||||
return self.filename.encode(encoding), self.flag_bits & ~_MASK_UTF_FILENAME
|
||||
except UnicodeEncodeError:
|
||||
return self.filename.encode('utf-8'), self.flag_bits | _MASK_UTF_FILENAME
|
||||
|
||||
@@ -620,11 +624,12 @@ class ZipInfo:
|
||||
def from_file(cls, filename, arcname=None, *, strict_timestamps=True):
|
||||
"""Construct an appropriate ZipInfo for a file on the filesystem.
|
||||
|
||||
filename should be the path to a file or directory on the filesystem.
|
||||
filename should be the path to a file or directory on the
|
||||
filesystem.
|
||||
|
||||
arcname is the name which it will have within the archive (by default,
|
||||
this will be the same as filename, but without a drive letter and with
|
||||
leading path separators removed).
|
||||
arcname is the name which it will have within the archive (by
|
||||
default, this will be the same as filename, but without a drive
|
||||
letter and with leading path separators removed).
|
||||
"""
|
||||
if isinstance(filename, os.PathLike):
|
||||
filename = os.fspath(filename)
|
||||
@@ -663,9 +668,12 @@ class ZipInfo:
|
||||
Return self.
|
||||
"""
|
||||
# gh-91279: Set the SOURCE_DATE_EPOCH to a specific timestamp
|
||||
epoch = os.environ.get('SOURCE_DATE_EPOCH')
|
||||
get_time = int(epoch) if epoch else time.time()
|
||||
self.date_time = time.localtime(get_time)[:6]
|
||||
source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH')
|
||||
|
||||
if source_date_epoch:
|
||||
self.date_time = time.gmtime(int(source_date_epoch))[:6]
|
||||
else:
|
||||
self.date_time = time.localtime(time.time())[:6]
|
||||
|
||||
self.compress_type = archive.compression
|
||||
self.compress_level = archive.compresslevel
|
||||
@@ -1392,19 +1400,19 @@ class ZipFile:
|
||||
mode: The mode can be either read 'r', write 'w', exclusive create 'x',
|
||||
or append 'a'.
|
||||
compression: ZIP_STORED (no compression), ZIP_DEFLATED (requires zlib),
|
||||
ZIP_BZIP2 (requires bz2), ZIP_LZMA (requires lzma), or
|
||||
ZIP_ZSTANDARD (requires compression.zstd).
|
||||
allowZip64: if True ZipFile will create files with ZIP64 extensions when
|
||||
needed, otherwise it will raise an exception when this would
|
||||
be necessary.
|
||||
compresslevel: None (default for the given compression type) or an integer
|
||||
specifying the level to pass to the compressor.
|
||||
When using ZIP_STORED or ZIP_LZMA this keyword has no effect.
|
||||
When using ZIP_DEFLATED integers 0 through 9 are accepted.
|
||||
When using ZIP_BZIP2 integers 1 through 9 are accepted.
|
||||
When using ZIP_ZSTANDARD integers -7 though 22 are common,
|
||||
see the CompressionParameter enum in compression.zstd for
|
||||
details.
|
||||
ZIP_BZIP2 (requires bz2), ZIP_LZMA (requires lzma), or
|
||||
ZIP_ZSTANDARD (requires compression.zstd).
|
||||
allowZip64: if True ZipFile will create files with ZIP64 extensions
|
||||
when needed, otherwise it will raise an exception when this
|
||||
would be necessary.
|
||||
compresslevel: None (default for the given compression type) or
|
||||
an integer specifying the level to pass to the compressor.
|
||||
When using ZIP_STORED or ZIP_LZMA this keyword has no effect.
|
||||
When using ZIP_DEFLATED integers 0 through 9 are accepted.
|
||||
When using ZIP_BZIP2 integers 1 through 9 are accepted.
|
||||
When using ZIP_ZSTANDARD integers -7 though 22 are common,
|
||||
see the CompressionParameter enum in compression.zstd for
|
||||
details.
|
||||
|
||||
"""
|
||||
|
||||
@@ -1414,8 +1422,8 @@ class ZipFile:
|
||||
|
||||
def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True,
|
||||
compresslevel=None, *, strict_timestamps=True, metadata_encoding=None):
|
||||
"""Open the ZIP file with mode read 'r', write 'w', exclusive create 'x',
|
||||
or append 'a'."""
|
||||
"""Open the ZIP file with mode read 'r', write 'w', exclusive create
|
||||
'x', or append 'a'."""
|
||||
if mode not in ('r', 'w', 'x', 'a'):
|
||||
raise ValueError("ZipFile requires mode 'r', 'w', 'x', or 'a'")
|
||||
|
||||
@@ -1693,10 +1701,10 @@ class ZipFile:
|
||||
|
||||
pwd is the password to decrypt files (only used for reading).
|
||||
|
||||
When writing, if the file size is not known in advance but may exceed
|
||||
2 GiB, pass force_zip64 to use the ZIP64 format, which can handle large
|
||||
files. If the size is known in advance, it is best to pass a ZipInfo
|
||||
instance for name, with zinfo.file_size set.
|
||||
When writing, if the file size is not known in advance but may
|
||||
exceed 2 GiB, pass force_zip64 to use the ZIP64 format, which can
|
||||
handle large files. If the size is known in advance, it is best to
|
||||
pass a ZipInfo instance for name, with zinfo.file_size set.
|
||||
"""
|
||||
if mode not in {"r", "w"}:
|
||||
raise ValueError('open() requires mode "r" or "w"')
|
||||
@@ -1808,7 +1816,7 @@ class ZipFile:
|
||||
zinfo.compress_size = 0
|
||||
zinfo.CRC = 0
|
||||
|
||||
zinfo.flag_bits = 0x00
|
||||
zinfo.flag_bits = _MASK_UTF_FILENAME
|
||||
if zinfo.compress_type == ZIP_LZMA:
|
||||
# Compressed data includes an end-of-stream (EOS) marker
|
||||
zinfo.flag_bits |= _MASK_COMPRESS_OPTION_1
|
||||
|
||||
Reference in new issue
Block a user