Merge pull request #5007 from DimitrisJim/pylibs_upgrade_uno

Bump some Python libraries to 3.11
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2023-06-13 11:38:00 +09:00
commit a6a92128f0
13 files changed
+630 -313

No files matched your search

Vendored
+49 -16
View File
@@ -138,7 +138,11 @@ import struct
import builtins
import warnings
__all__ = ["Error", "open", "openfp"]
__all__ = ["Error", "open"]
warnings._deprecated(__name__, remove=(3, 13))
class Error(Exception):
pass
@@ -251,7 +255,9 @@ def _write_float(f, x):
_write_ulong(f, himant)
_write_ulong(f, lomant)
from chunk import Chunk
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
from chunk import Chunk
from collections import namedtuple
_aifc_params = namedtuple('_aifc_params',
@@ -447,21 +453,33 @@ class Aifc_read:
#
def _alaw2lin(self, data):
import audioop
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
return audioop.alaw2lin(data, 2)
def _ulaw2lin(self, data):
import audioop
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
return audioop.ulaw2lin(data, 2)
def _adpcm2lin(self, data):
import audioop
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
if not hasattr(self, '_adpcmstate'):
# first time
self._adpcmstate = None
data, self._adpcmstate = audioop.adpcm2lin(data, 2, self._adpcmstate)
return data
def _sowt2lin(self, data):
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
return audioop.byteswap(data, 2)
def _read_comm_chunk(self, chunk):
self._nchannels = _read_short(chunk)
self._nframes = _read_long(chunk)
@@ -497,6 +515,8 @@ class Aifc_read:
self._convert = self._ulaw2lin
elif self._comptype in (b'alaw', b'ALAW'):
self._convert = self._alaw2lin
elif self._comptype in (b'sowt', b'SOWT'):
self._convert = self._sowt2lin
else:
raise Error('unsupported compression type')
self._sampwidth = 2
@@ -659,7 +679,7 @@ class Aifc_write:
if self._nframeswritten:
raise Error('cannot change parameters after starting to write')
if comptype not in (b'NONE', b'ulaw', b'ULAW',
b'alaw', b'ALAW', b'G722'):
b'alaw', b'ALAW', b'G722', b'sowt', b'SOWT'):
raise Error('unsupported compression type')
self._comptype = comptype
self._compname = compname
@@ -680,7 +700,7 @@ class Aifc_write:
if self._nframeswritten:
raise Error('cannot change parameters after starting to write')
if comptype not in (b'NONE', b'ulaw', b'ULAW',
b'alaw', b'ALAW', b'G722'):
b'alaw', b'ALAW', b'G722', b'sowt', b'SOWT'):
raise Error('unsupported compression type')
self.setnchannels(nchannels)
self.setsampwidth(sampwidth)
@@ -764,28 +784,43 @@ class Aifc_write:
#
def _lin2alaw(self, data):
import audioop
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
return audioop.lin2alaw(data, 2)
def _lin2ulaw(self, data):
import audioop
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
return audioop.lin2ulaw(data, 2)
def _lin2adpcm(self, data):
import audioop
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
if not hasattr(self, '_adpcmstate'):
self._adpcmstate = None
data, self._adpcmstate = audioop.lin2adpcm(data, 2, self._adpcmstate)
return data
def _lin2sowt(self, data):
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
import audioop
return audioop.byteswap(data, 2)
def _ensure_header_written(self, datasize):
if not self._nframeswritten:
if self._comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
if self._comptype in (b'ULAW', b'ulaw',
b'ALAW', b'alaw', b'G722',
b'sowt', b'SOWT'):
if not self._sampwidth:
self._sampwidth = 2
if self._sampwidth != 2:
raise Error('sample width must be 2 when compressing '
'with ulaw/ULAW, alaw/ALAW or G7.22 (ADPCM)')
'with ulaw/ULAW, alaw/ALAW, sowt/SOWT '
'or G7.22 (ADPCM)')
if not self._nchannels:
raise Error('# channels not specified')
if not self._sampwidth:
@@ -801,6 +836,8 @@ class Aifc_write:
self._convert = self._lin2ulaw
elif self._comptype in (b'alaw', b'ALAW'):
self._convert = self._lin2alaw
elif self._comptype in (b'sowt', b'SOWT'):
self._convert = self._lin2sowt
def _write_header(self, initlength):
if self._aifc and self._comptype != b'NONE':
@@ -920,10 +957,6 @@ def open(f, mode=None):
else:
raise Error("mode must be 'r', 'rb', 'w', or 'wb'")
def openfp(f, mode=None):
warnings.warn("aifc.openfp is deprecated since Python 3.7. "
"Use aifc.open instead.", DeprecationWarning, stacklevel=2)
return open(f, mode=mode)
if __name__ == '__main__':
import sys
Vendored
+33 -13
View File
@@ -13,6 +13,11 @@
This module defines a number of utilities for use by CGI scripts
written in Python.
The global variable maxlen can be set to an integer indicating the maximum size
of a POST request. POST requests larger than this size will result in a
ValueError being raised during parsing. The default value of this variable is 0,
meaning the request size is unlimited.
"""
# History
@@ -41,12 +46,16 @@ from email.message import Message
import html
import locale
import tempfile
import warnings
__all__ = ["MiniFieldStorage", "FieldStorage", "parse", "parse_multipart",
"parse_header", "test", "print_exception", "print_environ",
"print_form", "print_directory", "print_arguments",
"print_environ_usage"]
warnings._deprecated(__name__, remove=(3,13))
# Logging support
# ===============
@@ -77,9 +86,11 @@ def initlog(*allargs):
"""
global log, logfile, logfp
warnings.warn("cgi.log() is deprecated as of 3.10. Use logging instead",
DeprecationWarning, stacklevel=2)
if logfile and not logfp:
try:
logfp = open(logfile, "a")
logfp = open(logfile, "a", encoding="locale")
except OSError:
pass
if not logfp:
@@ -115,7 +126,8 @@ log = initlog # The current logging function
# 0 ==> unlimited input
maxlen = 0
def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
def parse(fp=None, environ=os.environ, keep_blank_values=0,
strict_parsing=0, separator='&'):
"""Parse a query in the environment or from a file (default stdin)
Arguments, all optional:
@@ -134,6 +146,9 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
strict_parsing: flag indicating what to do with parsing errors.
If false (the default), errors are silently ignored.
If true, errors raise a ValueError exception.
separator: str. The symbol to use for separating the query arguments.
Defaults to &.
"""
if fp is None:
fp = sys.stdin
@@ -154,7 +169,7 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
if environ['REQUEST_METHOD'] == 'POST':
ctype, pdict = parse_header(environ['CONTENT_TYPE'])
if ctype == 'multipart/form-data':
return parse_multipart(fp, pdict)
return parse_multipart(fp, pdict, separator=separator)
elif ctype == 'application/x-www-form-urlencoded':
clength = int(environ['CONTENT_LENGTH'])
if maxlen and clength > maxlen:
@@ -178,10 +193,10 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
qs = ""
environ['QUERY_STRING'] = qs # XXX Shouldn't, really
return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing,
encoding=encoding)
encoding=encoding, separator=separator)
def parse_multipart(fp, pdict, encoding="utf-8", errors="replace"):
def parse_multipart(fp, pdict, encoding="utf-8", errors="replace", separator='&'):
"""Parse multipart input.
Arguments:
@@ -194,15 +209,18 @@ def parse_multipart(fp, pdict, encoding="utf-8", errors="replace"):
value is a list of values for that field. For non-file fields, the value
is a list of strings.
"""
# RFC 2026, Section 5.1 : The "multipart" boundary delimiters are always
# RFC 2046, Section 5.1 : The "multipart" boundary delimiters are always
# represented as 7bit US-ASCII.
boundary = pdict['boundary'].decode('ascii')
ctype = "multipart/form-data; boundary={}".format(boundary)
headers = Message()
headers.set_type(ctype)
headers['Content-Length'] = pdict['CONTENT-LENGTH']
try:
headers['Content-Length'] = pdict['CONTENT-LENGTH']
except KeyError:
pass
fs = FieldStorage(fp, headers=headers, encoding=encoding, errors=errors,
environ={'REQUEST_METHOD': 'POST'})
environ={'REQUEST_METHOD': 'POST'}, separator=separator)
return {k: fs.getlist(k) for k in fs}
def _parseparam(s):
@@ -312,7 +330,7 @@ class FieldStorage:
def __init__(self, fp=None, headers=None, outerboundary=b'',
environ=os.environ, keep_blank_values=0, strict_parsing=0,
limit=None, encoding='utf-8', errors='replace',
max_num_fields=None):
max_num_fields=None, separator='&'):
"""Constructor. Read multipart/* until last part.
Arguments, all optional:
@@ -360,6 +378,7 @@ class FieldStorage:
self.keep_blank_values = keep_blank_values
self.strict_parsing = strict_parsing
self.max_num_fields = max_num_fields
self.separator = separator
if 'REQUEST_METHOD' in environ:
method = environ['REQUEST_METHOD'].upper()
self.qs_on_post = None
@@ -586,7 +605,7 @@ class FieldStorage:
query = urllib.parse.parse_qsl(
qs, self.keep_blank_values, self.strict_parsing,
encoding=self.encoding, errors=self.errors,
max_num_fields=self.max_num_fields)
max_num_fields=self.max_num_fields, separator=self.separator)
self.list = [MiniFieldStorage(key, value) for key, value in query]
self.skip_lines()
@@ -602,7 +621,7 @@ class FieldStorage:
query = urllib.parse.parse_qsl(
self.qs_on_post, self.keep_blank_values, self.strict_parsing,
encoding=self.encoding, errors=self.errors,
max_num_fields=self.max_num_fields)
max_num_fields=self.max_num_fields, separator=self.separator)
self.list.extend(MiniFieldStorage(key, value) for key, value in query)
klass = self.FieldStorageClass or self.__class__
@@ -646,7 +665,7 @@ class FieldStorage:
else self.limit - self.bytes_read
part = klass(self.fp, headers, ib, environ, keep_blank_values,
strict_parsing, limit,
self.encoding, self.errors, max_num_fields)
self.encoding, self.errors, max_num_fields, self.separator)
if max_num_fields is not None:
max_num_fields -= 1
@@ -736,7 +755,8 @@ class FieldStorage:
last_line_lfend = True
_read = 0
while 1:
if self.limit is not None and _read >= self.limit:
if self.limit is not None and 0 <= self.limit <= _read:
break
line = self.fp.readline(1<<16) # bytes
self.bytes_read += len(line)
+17 -6
View File
@@ -31,6 +31,11 @@ import tempfile
import time
import tokenize
import traceback
import warnings
from html import escape as html_escape
warnings._deprecated(__name__, remove=(3, 13))
def reset():
"""Return a string that resets the CGI and browser to a known state."""
@@ -105,10 +110,16 @@ def html(einfo, context=5):
etype = etype.__name__
pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
date = time.ctime(time.time())
head = '<body bgcolor="#f0f0f8">' + pydoc.html.heading(
'<big><big>%s</big></big>' %
strong(pydoc.html.escape(str(etype))),
'#ffffff', '#6622aa', pyver + '<br>' + date) + '''
head = f'''
<body bgcolor="#f0f0f8">
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#6622aa">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br>
<big><big><strong>{html_escape(str(etype))}</strong></big></big></font></td>
<td align=right valign=bottom>
<font color="#ffffff" face="helvetica, arial">{pyver}<br>{date}</font></td>
</tr></table>
<p>A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.</p>'''
@@ -181,8 +192,8 @@ function calls leading up to the error, in the order they occurred.</p>'''
<!-- The above is a description of an error in a Python program, formatted
for a Web browser because the 'cgitb' module was enabled. In case you
are not reading this in a Web browser, here is the original traceback:
for a web browser because the 'cgitb' module was enabled. In case you
are not reading this in a web browser, here is the original traceback:
%s
-->
+5 -1
View File
@@ -48,6 +48,10 @@ specifies whether or not chunks are aligned on 2-byte boundaries. The
default is 1, i.e. aligned.
"""
import warnings
warnings._deprecated(__name__, remove=(3, 13))
class Chunk:
def __init__(self, file, align=True, bigendian=True, inclheader=False):
import struct
@@ -64,7 +68,7 @@ class Chunk:
try:
self.chunksize = struct.unpack_from(strflag+'L', file.read(4))[0]
except struct.error:
raise EOFError
raise EOFError from None
if inclheader:
self.chunksize = self.chunksize - 8 # subtract header
self.size_read = 0
Vendored
+5 -5
View File
@@ -310,10 +310,10 @@ class Cmd:
names = self.get_names()
cmds_doc = []
cmds_undoc = []
help = {}
topics = set()
for name in names:
if name[:5] == 'help_':
help[name[5:]]=1
topics.add(name[5:])
names.sort()
# There can be duplicates if routines overridden
prevname = ''
@@ -323,16 +323,16 @@ class Cmd:
continue
prevname = name
cmd=name[3:]
if cmd in help:
if cmd in topics:
cmds_doc.append(cmd)
del help[cmd]
topics.remove(cmd)
elif getattr(self, name).__doc__:
cmds_doc.append(cmd)
else:
cmds_undoc.append(cmd)
self.stdout.write("%s\n"%str(self.doc_leader))
self.print_topics(self.doc_header, cmds_doc, 15,80)
self.print_topics(self.misc_header, list(help.keys()),15,80)
self.print_topics(self.misc_header, sorted(topics),15,80)
self.print_topics(self.undoc_header, cmds_undoc, 15,80)
def print_topics(self, header, cmds, cmdlen, maxcol):
+29 -60
View File
@@ -10,30 +10,6 @@ and:
syntax error (OverflowError and ValueError can be produced by
malformed literals).
Approach:
First, check if the source consists entirely of blank lines and
comments; if so, replace it with 'pass', because the built-in
parser doesn't always do the right thing for these.
Compile three times: as is, with \n, and with \n\n appended. If it
compiles as is, it's complete. If it compiles with one \n appended,
we expect more. If it doesn't compile either way, we compare the
error we get when compiling with \n or \n\n appended. If the errors
are the same, the code is broken. But if the errors are different, we
expect more. Not intuitive; not even guaranteed to hold in future
releases; but this matches the compiler's behavior from Python 1.4
through 2.2, at least.
Caveat:
It is possible (but not likely) that the parser stops parsing with a
successful outcome before reaching the end of the source; in this
case, trailing symbols may be ignored instead of causing an error.
For example, a backslash followed by two newlines may be followed by
arbitrary garbage. This will be fixed once the API for the parser is
better.
The two interfaces are:
compile_command(source, filename, symbol):
@@ -64,54 +40,50 @@ _features = [getattr(__future__, fname)
__all__ = ["compile_command", "Compile", "CommandCompiler"]
PyCF_DONT_IMPLY_DEDENT = 0x200 # Matches pythonrun.h
# The following flags match the values from Include/cpython/compile.h
# Caveat emptor: These flags are undocumented on purpose and depending
# on their effect outside the standard library is **unsupported**.
PyCF_DONT_IMPLY_DEDENT = 0x200
PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
def _maybe_compile(compiler, source, filename, symbol):
# Check for source consisting of only blank lines and comments
# Check for source consisting of only blank lines and comments.
for line in source.split("\n"):
line = line.strip()
if line and line[0] != '#':
break # Leave it alone
break # Leave it alone.
else:
if symbol != "eval":
source = "pass" # Replace it with a 'pass' statement
err = err1 = err2 = None
code = code1 = code2 = None
try:
code = compiler(source, filename, symbol)
except SyntaxError:
pass
# Catch syntax warnings after the first compile
# to emit warnings (SyntaxWarning, DeprecationWarning) at most once.
# Disable compiler warnings when checking for incomplete input.
with warnings.catch_warnings():
warnings.simplefilter("error")
warnings.simplefilter("ignore", (SyntaxWarning, DeprecationWarning))
try:
code1 = compiler(source + "\n", filename, symbol)
except SyntaxError as e:
err1 = e
compiler(source, filename, symbol)
except SyntaxError: # Let other compile() errors propagate.
try:
compiler(source + "\n", filename, symbol)
return None
except SyntaxError as e:
if "incomplete input" in str(e):
return None
# fallthrough
try:
code2 = compiler(source + "\n\n", filename, symbol)
except SyntaxError as e:
err2 = e
return compiler(source, filename, symbol)
try:
if code:
return code
if not code1 and repr(err1) == repr(err2):
raise err1
finally:
err1 = err2 = None
def _is_syntax_error(err1, err2):
rep1 = repr(err1)
rep2 = repr(err2)
if "was never closed" in rep1 and "was never closed" in rep2:
return False
if rep1 == rep2:
return True
return False
def _compile(source, filename, symbol):
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT)
def compile_command(source, filename="<input>", symbol="single"):
r"""Compile a command and determine whether it is incomplete.
@@ -134,15 +106,13 @@ def compile_command(source, filename="<input>", symbol="single"):
"""
return _maybe_compile(_compile, source, filename, symbol)
class Compile:
"""Instances of this class behave much like the built-in compile
function, but if one is used to compile text containing a future
statement, it "remembers" and compiles all subsequent program texts
with the statement in force."""
def __init__(self):
self.flags = PyCF_DONT_IMPLY_DEDENT
self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
def __call__(self, source, filename, symbol):
codeob = compile(source, filename, symbol, self.flags, True)
@@ -151,7 +121,6 @@ class Compile:
self.flags |= feature.compiler_flag
return codeob
class CommandCompiler:
"""Instances of this class have __call__ methods identical in
signature to compile_command; the difference is that if the
+17 -11
View File
@@ -1,10 +1,14 @@
"""Conversion functions between RGB and other color systems.
This modules provides two functions for each color system ABC:
rgb_to_abc(r, g, b) --> a, b, c
abc_to_rgb(a, b, c) --> r, g, b
All inputs and outputs are triples of floats in the range [0.0...1.0]
(with the exception of I and Q, which covers a slightly larger range).
Inputs outside the valid range may cause exceptions or invalid outputs.
Supported color systems:
RGB: Red, Green, Blue components
YIQ: Luminance, Chrominance (used by composite video signals)
@@ -71,17 +75,18 @@ def yiq_to_rgb(y, i, q):
def rgb_to_hls(r, g, b):
maxc = max(r, g, b)
minc = min(r, g, b)
# XXX Can optimize (maxc+minc) and (maxc-minc)
l = (minc+maxc)/2.0
sumc = (maxc+minc)
rangec = (maxc-minc)
l = sumc/2.0
if minc == maxc:
return 0.0, l, 0.0
if l <= 0.5:
s = (maxc-minc) / (maxc+minc)
s = rangec / sumc
else:
s = (maxc-minc) / (2.0-maxc-minc)
rc = (maxc-r) / (maxc-minc)
gc = (maxc-g) / (maxc-minc)
bc = (maxc-b) / (maxc-minc)
s = rangec / (2.0-sumc)
rc = (maxc-r) / rangec
gc = (maxc-g) / rangec
bc = (maxc-b) / rangec
if r == maxc:
h = bc-gc
elif g == maxc:
@@ -120,13 +125,14 @@ def _v(m1, m2, hue):
def rgb_to_hsv(r, g, b):
maxc = max(r, g, b)
minc = min(r, g, b)
rangec = (maxc-minc)
v = maxc
if minc == maxc:
return 0.0, 0.0, v
s = (maxc-minc) / maxc
rc = (maxc-r) / (maxc-minc)
gc = (maxc-g) / (maxc-minc)
bc = (maxc-b) / (maxc-minc)
s = rangec / maxc
rc = (maxc-r) / rangec
gc = (maxc-g) / rangec
bc = (maxc-b) / rangec
if r == maxc:
h = bc-gc
elif g == maxc:
+11 -8
View File
@@ -1,4 +1,3 @@
import cgi
import os
import sys
import tempfile
@@ -6,6 +5,10 @@ import unittest
from collections import namedtuple
from io import StringIO, BytesIO
from test import support
from test.support import warnings_helper
cgi = warnings_helper.import_deprecated("cgi")
class HackedSysModule:
# The regression test will have real values in sys.argv, which
@@ -50,7 +53,7 @@ def do_test(buf, method):
return ComparableException(err)
parse_strict_test_cases = [
("", ValueError("bad query field: ''")),
("", {}),
("&", ValueError("bad query field: ''")),
("&&", ValueError("bad query field: ''")),
# Should the next few really be valid?
@@ -123,8 +126,6 @@ class CgiTests(unittest.TestCase):
'file': [b'Testing 123.\n'], 'title': ['']}
self.assertEqual(result, expected)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_parse_multipart_without_content_length(self):
POSTDATA = '''--JfISa01
Content-Disposition: form-data; name="submit-name"
@@ -174,6 +175,8 @@ Content-Length: 3
fs = cgi.FieldStorage(headers={'content-type':'text/plain'})
self.assertRaises(TypeError, bool, fs)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_strict(self):
for orig, expect in parse_strict_test_cases:
# Test basic parsing
@@ -200,8 +203,6 @@ Content-Length: 3
else:
self.assertEqual(fs.getvalue(key), expect_val[0])
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_separator(self):
parse_semicolon = [
("x=1;y=2.0", {'x': ['1'], 'y': ['2.0']}),
@@ -226,6 +227,7 @@ Content-Length: 3
else:
self.assertEqual(fs.getvalue(key), expect_val[0])
@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_log(self):
cgi.log("Testing")
@@ -578,8 +580,9 @@ this is the content of the fake file
("form-data", {"name": "files", "filename": 'fo"o;bar'}))
def test_all(self):
not_exported = {"logfile", "logfp", "initlog", "dolog", "nolog",
"closelog", "log", "maxlen", "valid_boundary"}
not_exported = {
"logfile", "logfp", "initlog", "dolog", "nolog", "closelog", "log",
"maxlen", "valid_boundary"}
support.check__all__(self, cgi, not_exported=not_exported)
+9 -6
View File
@@ -1,8 +1,9 @@
from test.support.os_helper import temp_dir
from test.support.script_helper import assert_python_failure
from test.support.warnings_helper import import_deprecated
import unittest
import sys
import cgitb
cgitb = import_deprecated("cgitb")
class TestCgitb(unittest.TestCase):
@@ -31,7 +32,7 @@ class TestCgitb(unittest.TestCase):
def test_text(self):
try:
raise ValueError("Hello World")
except ValueError as err:
except ValueError:
text = cgitb.text(sys.exc_info())
self.assertIn("ValueError", text)
self.assertIn("Hello World", text)
@@ -41,8 +42,9 @@ class TestCgitb(unittest.TestCase):
rc, out, err = assert_python_failure(
'-c',
('import cgitb; cgitb.enable(logdir=%s); '
'raise ValueError("Hello World")') % repr(tracedir))
out = out.decode(sys.getfilesystemencoding())
'raise ValueError("Hello World")') % repr(tracedir),
PYTHONIOENCODING='utf-8')
out = out.decode()
self.assertIn("ValueError", out)
self.assertIn("Hello World", out)
self.assertIn("<strong>&lt;module&gt;</strong>", out)
@@ -56,8 +58,9 @@ class TestCgitb(unittest.TestCase):
rc, out, err = assert_python_failure(
'-c',
('import cgitb; cgitb.enable(format="text", logdir=%s); '
'raise ValueError("Hello World")') % repr(tracedir))
out = out.decode(sys.getfilesystemencoding())
'raise ValueError("Hello World")') % repr(tracedir),
PYTHONIOENCODING='utf-8')
out = out.decode()
self.assertIn("ValueError", out)
self.assertIn("Hello World", out)
self.assertNotIn('<p>', out)
+34 -11
View File
@@ -6,10 +6,10 @@ Original by Michael Schneider
import cmd
import sys
import doctest
import unittest
import io
from test import support
from test.support import import_helper
class samplecmdclass(cmd.Cmd):
"""
@@ -70,7 +70,7 @@ class samplecmdclass(cmd.Cmd):
>>> mycmd.complete_help("12")
[]
>>> sorted(mycmd.complete_help(""))
['add', 'exit', 'help', 'shell']
['add', 'exit', 'help', 'life', 'meaning', 'shell']
Test for the function do_help():
>>> mycmd.do_help("testet")
@@ -79,12 +79,20 @@ class samplecmdclass(cmd.Cmd):
help text for add
>>> mycmd.onecmd("help add")
help text for add
>>> mycmd.onecmd("help meaning") # doctest: +NORMALIZE_WHITESPACE
Try and be nice to people, avoid eating fat, read a good book every
now and then, get some walking in, and try to live together in peace
and harmony with people of all creeds and nations.
>>> mycmd.do_help("")
<BLANKLINE>
Documented commands (type help <topic>):
========================================
add help
<BLANKLINE>
Miscellaneous help topics:
==========================
life meaning
<BLANKLINE>
Undocumented commands:
======================
exit shell
@@ -115,17 +123,22 @@ class samplecmdclass(cmd.Cmd):
This test includes the preloop(), postloop(), default(), emptyline(),
parseline(), do_help() functions
>>> mycmd.use_rawinput=0
>>> mycmd.cmdqueue=["", "add", "add 4 5", "help", "help add","exit"]
>>> mycmd.cmdloop()
>>> mycmd.cmdqueue=["add", "add 4 5", "", "help", "help add", "exit"]
>>> mycmd.cmdloop() # doctest: +REPORT_NDIFF
Hello from preloop
help text for add
*** invalid number of arguments
9
9
<BLANKLINE>
Documented commands (type help <topic>):
========================================
add help
<BLANKLINE>
Miscellaneous help topics:
==========================
life meaning
<BLANKLINE>
Undocumented commands:
======================
exit shell
@@ -165,6 +178,17 @@ class samplecmdclass(cmd.Cmd):
print("help text for add")
return
def help_meaning(self):
print("Try and be nice to people, avoid eating fat, read a "
"good book every now and then, get some walking in, "
"and try to live together in peace and harmony with "
"people of all creeds and nations.")
return
def help_life(self):
print("Always look on the bright side of life")
return
def do_exit(self, arg):
return True
@@ -220,13 +244,12 @@ class TestAlternateInput(unittest.TestCase):
"(Cmd) *** Unknown syntax: EOF\n"))
def test_main(verbose=None):
from test import test_cmd
support.run_doctest(test_cmd, verbose)
support.run_unittest(TestAlternateInput)
def load_tests(loader, tests, pattern):
tests.addTest(doctest.DocTestSuite())
return tests
def test_coverage(coverdir):
trace = import_helper.import_module('trace')
trace = support.import_module('trace')
tracer=trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,],
trace=0, count=1)
tracer.run('import importlib; importlib.reload(cmd); test_main()')
@@ -240,4 +263,4 @@ if __name__ == "__main__":
elif "-i" in sys.argv:
samplecmdclass().cmdloop()
else:
test_main()
unittest.main()
+356
View File
@@ -0,0 +1,356 @@
"""
Test cases for codeop.py
Nick Mathewson
"""
import sys
import unittest
import warnings
from test import support
from test.support import warnings_helper
from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT
import io
if support.is_jython:
def unify_callables(d):
for n,v in d.items():
if hasattr(v, '__call__'):
d[n] = True
return d
class CodeopTests(unittest.TestCase):
def assertValid(self, str, symbol='single'):
'''succeed iff str is a valid piece of code'''
if support.is_jython:
code = compile_command(str, "<input>", symbol)
self.assertTrue(code)
if symbol == "single":
d,r = {},{}
saved_stdout = sys.stdout
sys.stdout = io.StringIO()
try:
exec(code, d)
exec(compile(str,"<input>","single"), r)
finally:
sys.stdout = saved_stdout
elif symbol == 'eval':
ctx = {'a': 2}
d = { 'value': eval(code,ctx) }
r = { 'value': eval(str,ctx) }
self.assertEqual(unify_callables(r),unify_callables(d))
else:
expected = compile(str, "<input>", symbol, PyCF_DONT_IMPLY_DEDENT)
self.assertEqual(compile_command(str, "<input>", symbol), expected)
def assertIncomplete(self, str, symbol='single'):
'''succeed iff str is the start of a valid piece of code'''
self.assertEqual(compile_command(str, symbol=symbol), None)
def assertInvalid(self, str, symbol='single', is_syntax=1):
'''succeed iff str is the start of an invalid piece of code'''
try:
compile_command(str,symbol=symbol)
self.fail("No exception raised for invalid code")
except SyntaxError:
self.assertTrue(is_syntax)
except OverflowError:
self.assertTrue(not is_syntax)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_valid(self):
av = self.assertValid
# special case
if not support.is_jython:
self.assertEqual(compile_command(""),
compile("pass", "<input>", 'single',
PyCF_DONT_IMPLY_DEDENT))
self.assertEqual(compile_command("\n"),
compile("pass", "<input>", 'single',
PyCF_DONT_IMPLY_DEDENT))
else:
av("")
av("\n")
av("a = 1")
av("\na = 1")
av("a = 1\n")
av("a = 1\n\n")
av("\n\na = 1\n\n")
av("def x():\n pass\n")
av("if 1:\n pass\n")
av("\n\nif 1: pass\n")
av("\n\nif 1: pass\n\n")
av("def x():\n\n pass\n")
av("def x():\n pass\n \n")
av("def x():\n pass\n \n")
av("pass\n")
av("3**3\n")
av("if 9==3:\n pass\nelse:\n pass\n")
av("if 1:\n pass\n if 1:\n pass\n else:\n pass\n")
av("#a\n#b\na = 3\n")
av("#a\n\n \na=3\n")
av("a=3\n\n")
av("a = 9+ \\\n3")
av("3**3","eval")
av("(lambda z: \n z**3)","eval")
av("9+ \\\n3","eval")
av("9+ \\\n3\n","eval")
av("\n\na**3","eval")
av("\n \na**3","eval")
av("#a\n#b\na**3","eval")
av("\n\na = 1\n\n")
av("\n\nif 1: a=1\n\n")
av("if 1:\n pass\n if 1:\n pass\n else:\n pass\n")
av("#a\n\n \na=3\n\n")
av("\n\na**3","eval")
av("\n \na**3","eval")
av("#a\n#b\na**3","eval")
av("def f():\n try: pass\n finally: [x for x in (1,2)]\n")
av("def f():\n pass\n#foo\n")
av("@a.b.c\ndef f():\n pass\n")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_incomplete(self):
ai = self.assertIncomplete
ai("(a **")
ai("(a,b,")
ai("(a,b,(")
ai("(a,b,(")
ai("a = (")
ai("a = {")
ai("b + {")
ai("print([1,\n2,")
ai("print({1:1,\n2:3,")
ai("print((1,\n2,")
ai("if 9==3:\n pass\nelse:")
ai("if 9==3:\n pass\nelse:\n")
ai("if 9==3:\n pass\nelse:\n pass")
ai("if 1:")
ai("if 1:\n")
ai("if 1:\n pass\n if 1:\n pass\n else:")
ai("if 1:\n pass\n if 1:\n pass\n else:\n")
ai("if 1:\n pass\n if 1:\n pass\n else:\n pass")
ai("def x():")
ai("def x():\n")
ai("def x():\n\n")
ai("def x():\n pass")
ai("def x():\n pass\n ")
ai("def x():\n pass\n ")
ai("\n\ndef x():\n pass")
ai("a = 9+ \\")
ai("a = 'a\\")
ai("a = '''xy")
ai("","eval")
ai("\n","eval")
ai("(","eval")
ai("(9+","eval")
ai("9+ \\","eval")
ai("lambda z: \\","eval")
ai("if True:\n if True:\n if True: \n")
ai("@a(")
ai("@a(b")
ai("@a(b,")
ai("@a(b,c")
ai("@a(b,c,")
ai("from a import (")
ai("from a import (b")
ai("from a import (b,")
ai("from a import (b,c")
ai("from a import (b,c,")
ai("[")
ai("[a")
ai("[a,")
ai("[a,b")
ai("[a,b,")
ai("{")
ai("{a")
ai("{a:")
ai("{a:b")
ai("{a:b,")
ai("{a:b,c")
ai("{a:b,c:")
ai("{a:b,c:d")
ai("{a:b,c:d,")
ai("a(")
ai("a(b")
ai("a(b,")
ai("a(b,c")
ai("a(b,c,")
ai("a[")
ai("a[b")
ai("a[b,")
ai("a[b:")
ai("a[b:c")
ai("a[b:c:")
ai("a[b:c:d")
ai("def a(")
ai("def a(b")
ai("def a(b,")
ai("def a(b,c")
ai("def a(b,c,")
ai("(")
ai("(a")
ai("(a,")
ai("(a,b")
ai("(a,b,")
ai("if a:\n pass\nelif b:")
ai("if a:\n pass\nelif b:\n pass\nelse:")
ai("while a:")
ai("while a:\n pass\nelse:")
ai("for a in b:")
ai("for a in b:\n pass\nelse:")
ai("try:")
ai("try:\n pass\nexcept:")
ai("try:\n pass\nfinally:")
ai("try:\n pass\nexcept:\n pass\nfinally:")
ai("with a:")
ai("with a as b:")
ai("class a:")
ai("class a(")
ai("class a(b")
ai("class a(b,")
ai("class a():")
ai("[x for")
ai("[x for x in")
ai("[x for x in (")
ai("(x for")
ai("(x for x in")
ai("(x for x in (")
def test_invalid(self):
ai = self.assertInvalid
ai("a b")
ai("a @")
ai("a b @")
ai("a ** @")
ai("a = ")
ai("a = 9 +")
ai("def x():\n\npass\n")
ai("\n\n if 1: pass\n\npass")
ai("a = 9+ \\\n")
ai("a = 'a\\ ")
ai("a = 'a\\\n")
ai("a = 1","eval")
ai("]","eval")
ai("())","eval")
ai("[}","eval")
ai("9+","eval")
ai("lambda z:","eval")
ai("a b","eval")
ai("return 2.3")
ai("if (a == 1 and b = 2): pass")
ai("del 1")
ai("del (1,)")
ai("del [1]")
ai("del '1'")
ai("[i for i in range(10)] = (1, 2, 3)")
def test_invalid_exec(self):
ai = self.assertInvalid
ai("raise = 4", symbol="exec")
ai('def a-b', symbol='exec')
ai('await?', symbol='exec')
ai('=!=', symbol='exec')
ai('a await raise b', symbol='exec')
ai('a await raise b?+1', symbol='exec')
def test_filename(self):
self.assertEqual(compile_command("a = 1\n", "abc").co_filename,
compile("a = 1\n", "abc", 'single').co_filename)
self.assertNotEqual(compile_command("a = 1\n", "abc").co_filename,
compile("a = 1\n", "def", 'single').co_filename)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_warning(self):
# Test that the warning is only returned once.
with warnings_helper.check_warnings(
(".*literal", SyntaxWarning),
(".*invalid", DeprecationWarning),
) as w:
compile_command(r"'\e' is 0")
self.assertEqual(len(w.warnings), 2)
# bpo-41520: check SyntaxWarning treated as an SyntaxError
with warnings.catch_warnings(), self.assertRaises(SyntaxError):
warnings.simplefilter('error', SyntaxWarning)
compile_command('1 is 1', symbol='exec')
# Check DeprecationWarning treated as an SyntaxError
with warnings.catch_warnings(), self.assertRaises(SyntaxError):
warnings.simplefilter('error', DeprecationWarning)
compile_command(r"'\e'", symbol='exec')
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_incomplete_warning(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
self.assertIncomplete("'\\e' + (")
self.assertEqual(w, [])
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_invalid_warning(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
self.assertInvalid("'\\e' 1")
self.assertEqual(len(w), 1)
self.assertEqual(w[0].category, DeprecationWarning)
self.assertRegex(str(w[0].message), 'invalid escape sequence')
self.assertEqual(w[0].filename, '<input>')
if __name__ == "__main__":
unittest.main()
-137
View File
@@ -1,137 +0,0 @@
# Python test set -- part 2, opcodes
import unittest
from test import ann_module, support
class OpcodeTest(unittest.TestCase):
def test_try_inside_for_loop(self):
n = 0
for i in range(10):
n = n+i
try: 1/0
except NameError: pass
except ZeroDivisionError: pass
except TypeError: pass
try: pass
except: pass
try: pass
finally: pass
n = n+i
if n != 90:
self.fail('try inside for')
def test_setup_annotations_line(self):
# check that SETUP_ANNOTATIONS does not create spurious line numbers
try:
with open(ann_module.__file__, encoding="utf-8") as f:
txt = f.read()
co = compile(txt, ann_module.__file__, 'exec')
self.assertEqual(co.co_firstlineno, 1)
except OSError:
pass
def test_default_annotations_exist(self):
class C: pass
self.assertEqual(C.__annotations__, {})
def test_use_existing_annotations(self):
ns = {'__annotations__': {1: 2}}
exec('x: int', ns)
self.assertEqual(ns['__annotations__'], {'x': int, 1: 2})
def test_do_not_recreate_annotations(self):
# Don't rely on the existence of the '__annotations__' global.
with support.swap_item(globals(), '__annotations__', {}):
del globals()['__annotations__']
class C:
del __annotations__
with self.assertRaises(NameError):
x: int
def test_raise_class_exceptions(self):
class AClass(Exception): pass
class BClass(AClass): pass
class CClass(Exception): pass
class DClass(AClass):
def __init__(self, ignore):
pass
try: raise AClass()
except: pass
try: raise AClass()
except AClass: pass
try: raise BClass()
except AClass: pass
try: raise BClass()
except CClass: self.fail()
except: pass
a = AClass()
b = BClass()
try:
raise b
except AClass as v:
self.assertEqual(v, b)
else:
self.fail("no exception")
# not enough arguments
##try: raise BClass, a
##except TypeError: pass
##else: self.fail("no exception")
try: raise DClass(a)
except DClass as v:
self.assertIsInstance(v, DClass)
else:
self.fail("no exception")
def test_compare_function_objects(self):
f = eval('lambda: None')
g = eval('lambda: None')
self.assertNotEqual(f, g)
f = eval('lambda a: a')
g = eval('lambda a: a')
self.assertNotEqual(f, g)
f = eval('lambda a=1: a')
g = eval('lambda a=1: a')
self.assertNotEqual(f, g)
f = eval('lambda: 0')
g = eval('lambda: 1')
self.assertNotEqual(f, g)
f = eval('lambda: None')
g = eval('lambda a: None')
self.assertNotEqual(f, g)
f = eval('lambda a: None')
g = eval('lambda b: None')
self.assertNotEqual(f, g)
f = eval('lambda a: None')
g = eval('lambda a=None: None')
self.assertNotEqual(f, g)
f = eval('lambda a=0: None')
g = eval('lambda a=1: None')
self.assertNotEqual(f, g)
def test_modulo_of_string_subclasses(self):
class MyString(str):
def __mod__(self, value):
return 42
self.assertEqual(MyString() % 3, 42)
if __name__ == '__main__':
unittest.main()
+65 -39
View File
@@ -33,9 +33,8 @@ def _showwarnmsg_impl(msg):
pass
def _formatwarnmsg_impl(msg):
s = ("%s:%s: %s: %s\n"
% (msg.filename, msg.lineno, msg.category.__name__,
msg.message))
category = msg.category.__name__
s = f"{msg.filename}:{msg.lineno}: {category}: {msg.message}\n"
if msg.line is None:
try:
@@ -55,11 +54,20 @@ def _formatwarnmsg_impl(msg):
if msg.source is not None:
try:
import tracemalloc
tb = tracemalloc.get_object_traceback(msg.source)
# Logging a warning should not raise a new exception:
# catch Exception, not only ImportError and RecursionError.
except Exception:
# When a warning is logged during Python shutdown, tracemalloc
# and the import machinery don't work anymore
# don't suggest to enable tracemalloc if it's not available
tracing = True
tb = None
else:
tracing = tracemalloc.is_tracing()
try:
tb = tracemalloc.get_object_traceback(msg.source)
except Exception:
# When a warning is logged during Python shutdown, tracemalloc
# and the import machinery don't work anymore
tb = None
if tb is not None:
s += 'Object allocated at (most recent call last):\n'
@@ -77,6 +85,9 @@ def _formatwarnmsg_impl(msg):
if line:
line = line.strip()
s += ' %s\n' % line
elif not tracing:
s += (f'{category}: Enable tracemalloc to get the object '
f'allocation traceback\n')
return s
# Keep a reference to check if the function was replaced
@@ -113,7 +124,7 @@ def _formatwarnmsg(msg):
if fw is not _formatwarning_orig:
# warnings.formatwarning() was replaced
return fw(msg.message, msg.category,
msg.filename, msg.lineno, line=msg.line)
msg.filename, msg.lineno, msg.line)
return _formatwarnmsg_impl(msg)
def filterwarnings(action, message="", category=Warning, module="", lineno=0,
@@ -200,7 +211,6 @@ def _processoptions(args):
# Helper for _processoptions()
def _setoption(arg):
import re
parts = arg.split(':')
if len(parts) > 5:
raise _OptionError("too many fields (max 5): %r" % (arg,))
@@ -209,11 +219,13 @@ def _setoption(arg):
action, message, category, module, lineno = [s.strip()
for s in parts]
action = _getaction(action)
message = re.escape(message)
category = _getcategory(category)
module = re.escape(module)
if message or module:
import re
if message:
message = re.escape(message)
if module:
module = module + '$'
module = re.escape(module) + r'\Z'
if lineno:
try:
lineno = int(lineno)
@@ -237,26 +249,21 @@ def _getaction(action):
# Helper for _setoption()
def _getcategory(category):
import re
if not category:
return Warning
if re.match("^[a-zA-Z0-9_]+$", category):
try:
cat = eval(category)
except NameError:
raise _OptionError("unknown warning category: %r" % (category,)) from None
if '.' not in category:
import builtins as m
klass = category
else:
i = category.rfind(".")
module = category[:i]
klass = category[i+1:]
module, _, klass = category.rpartition('.')
try:
m = __import__(module, None, None, [klass])
except ImportError:
raise _OptionError("invalid module name: %r" % (module,)) from None
try:
cat = getattr(m, klass)
except AttributeError:
raise _OptionError("unknown warning category: %r" % (category,)) from None
try:
cat = getattr(m, klass)
except AttributeError:
raise _OptionError("unknown warning category: %r" % (category,)) from None
if not issubclass(cat, Warning):
raise _OptionError("invalid warning category: %r" % (category,))
return cat
@@ -303,28 +310,16 @@ def warn(message, category=None, stacklevel=1, source=None):
raise ValueError
except ValueError:
globals = sys.__dict__
filename = "sys"
lineno = 1
else:
globals = frame.f_globals
filename = frame.f_code.co_filename
lineno = frame.f_lineno
if '__name__' in globals:
module = globals['__name__']
else:
module = "<string>"
filename = globals.get('__file__')
if filename:
fnl = filename.lower()
if fnl.endswith(".pyc"):
filename = filename[:-1]
else:
if module == "__main__":
try:
filename = sys.argv[0]
except AttributeError:
# embedded interpreters don't have sys.argv, see bug #839151
filename = '__main__'
if not filename:
filename = module
registry = globals.setdefault("__warningregistry__", {})
warn_explicit(message, category, filename, lineno, module, registry,
globals, source)
@@ -437,9 +432,13 @@ class catch_warnings(object):
named 'warnings' and imported under that name. This argument is only useful
when testing the warnings module itself.
If the 'action' argument is not None, the remaining arguments are passed
to warnings.simplefilter() as if it were called immediately on entering the
context.
"""
def __init__(self, *, record=False, module=None):
def __init__(self, *, record=False, module=None,
action=None, category=Warning, lineno=0, append=False):
"""Specify whether to record warnings and if an alternative module
should be used other than sys.modules['warnings'].
@@ -450,6 +449,10 @@ class catch_warnings(object):
self._record = record
self._module = sys.modules['warnings'] if module is None else module
self._entered = False
if action is None:
self._filter = None
else:
self._filter = (action, category, lineno, append)
def __repr__(self):
args = []
@@ -469,6 +472,8 @@ class catch_warnings(object):
self._module._filters_mutated()
self._showwarning = self._module.showwarning
self._showwarnmsg_impl = self._module._showwarnmsg_impl
if self._filter is not None:
simplefilter(*self._filter)
if self._record:
log = []
self._module._showwarnmsg_impl = log.append
@@ -488,6 +493,27 @@ class catch_warnings(object):
self._module._showwarnmsg_impl = self._showwarnmsg_impl
_DEPRECATED_MSG = "{name!r} is deprecated and slated for removal in Python {remove}"
def _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info):
"""Warn that *name* is deprecated or should be removed.
RuntimeError is raised if *remove* specifies a major/minor tuple older than
the current Python version or the same version but past the alpha.
The *message* argument is formatted with *name* and *remove* as a Python
version (e.g. "3.11").
"""
remove_formatted = f"{remove[0]}.{remove[1]}"
if (_version[:2] > remove) or (_version[:2] == remove and _version[3] != "alpha"):
msg = f"{name!r} was slated for removal after Python {remove_formatted} alpha"
raise RuntimeError(msg)
else:
msg = message.format(name=name, remove=remove_formatted)
warn(msg, DeprecationWarning, stacklevel=3)
# Private utility function called by _PyErr_WarnUnawaitedCoroutine
def _warn_unawaited_coroutine(coro):
msg_lines = [