From 8af4c5fd7bbd35ea68ef532c554059f3598420dd Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Sun, 11 Jun 2023 17:27:59 +0300
Subject: [PATCH 1/8] Upgrade cmd.py and test_cmd.py from Python 3.11.

---
 Lib/cmd.py           | 10 +++++-----
 Lib/test/test_cmd.py | 45 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/Lib/cmd.py b/Lib/cmd.py
index 859e91096d..88ee7d3ddc 100644
--- a/Lib/cmd.py
+++ b/Lib/cmd.py
@@ -310,10 +310,10 @@ def do_help(self, arg):
             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 @@ def do_help(self, arg):
                         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):
diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py
index c9ffad485f..319801c71f 100644
--- a/Lib/test/test_cmd.py
+++ b/Lib/test/test_cmd.py
@@ -6,10 +6,10 @@
 
 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 @@ def help_add(self):
         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 @@ def test_input_reset_at_EOF(self):
              "(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 @@ def test_coverage(coverdir):
     elif "-i" in sys.argv:
         samplecmdclass().cmdloop()
     else:
-        test_main()
+        unittest.main()

From 3d76e1e1db5ed438cd4d9534ceb4c75289ec0b23 Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Sun, 11 Jun 2023 22:34:27 +0300
Subject: [PATCH 2/8] Upgrade aifc.py from Python 3.11.

---
 Lib/aifc.py | 65 ++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 49 insertions(+), 16 deletions(-)

diff --git a/Lib/aifc.py b/Lib/aifc.py
index 1916e7ef8e..5254987e22 100644
--- a/Lib/aifc.py
+++ b/Lib/aifc.py
@@ -138,7 +138,11 @@
 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 @@ def readframes(self, nframes):
     #
 
     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 @@ def _read_comm_chunk(self, chunk):
                     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 @@ def setcomptype(self, comptype, compname):
         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 @@ def setparams(self, params):
         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 @@ def close(self):
     #
 
     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 @@ def _init_compression(self):
             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

From 1be262db40c2867249dc153ce1807f5269f97110 Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Sun, 11 Jun 2023 23:46:59 +0300
Subject: [PATCH 3/8] Upgrade warnings.py from Python 3.11

---
 Lib/warnings.py | 104 ++++++++++++++++++++++++++++++------------------
 1 file changed, 65 insertions(+), 39 deletions(-)

diff --git a/Lib/warnings.py b/Lib/warnings.py
index 81f9864778..7d8c440012 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -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 @@ def __init__(self, *, record=False, module=None):
         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 @@ def __enter__(self):
         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 @@ def __exit__(self, *exc_info):
         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 = [

From 3150b4ded6b92c9dd2dc8cfcc542e784c95a7b92 Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Mon, 12 Jun 2023 00:08:49 +0300
Subject: [PATCH 4/8] Update cgi.py from Python 3.11

---
 Lib/cgi.py           | 46 +++++++++++++++++++++++++++++++-------------
 Lib/test/test_cgi.py | 19 ++++++++++--------
 2 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/Lib/cgi.py b/Lib/cgi.py
index c22c71b387..8787567be7 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -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 @@
 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 @@ def closelog():
 # 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 @@ def __init__(self, fp=None, headers=None, outerboundary=b'',
         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 @@ def read_urlencoded(self):
         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 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
             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 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
                 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 @@ def read_lines_to_outerboundary(self):
         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)
diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py
index cc736572b0..43164cff31 100644
--- a/Lib/test/test_cgi.py
+++ b/Lib/test/test_cgi.py
@@ -1,4 +1,3 @@
-import cgi
 import os
 import sys
 import tempfile
@@ -6,6 +5,10 @@
 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 @@ def test_parse_multipart(self):
                     '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 @@ def test_fieldstorage_invalid(self):
         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 @@ def test_strict(self):
                     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 @@ def test_separator(self):
                     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 @@ def test_parse_header(self):
             ("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)
 
 

From 854d3e4d807db8c82f621aa37711a27e7c481ae5 Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Mon, 12 Jun 2023 02:03:08 +0300
Subject: [PATCH 5/8] Update cgitb from Python 3.11

---
 Lib/cgitb.py           | 23 +++++++++++++++++------
 Lib/test/test_cgitb.py | 15 +++++++++------
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/Lib/cgitb.py b/Lib/cgitb.py
index 4f81271be3..8ce0e833a9 100644
--- a/Lib/cgitb.py
+++ b/Lib/cgitb.py
@@ -31,6 +31,11 @@
 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 @@ def reader(lnum=[lnum]):
 
 
 <!-- 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
 -->
diff --git a/Lib/test/test_cgitb.py b/Lib/test/test_cgitb.py
index 5cbb054a3c..501c7fcce2 100644
--- a/Lib/test/test_cgitb.py
+++ b/Lib/test/test_cgitb.py
@@ -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 @@ def test_html(self):
     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 @@ def test_syshook_no_logdir_default_format(self):
             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 @@ def test_syshook_no_logdir_text_format(self):
             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)

From 7e3183ef160522e4c7cb41ac2c78690a343bf76a Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Mon, 12 Jun 2023 12:30:52 +0300
Subject: [PATCH 6/8] Update chunk from Python 3.11

---
 Lib/chunk.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Lib/chunk.py b/Lib/chunk.py
index d94dd39807..618781efd1 100644
--- a/Lib/chunk.py
+++ b/Lib/chunk.py
@@ -48,6 +48,10 @@
 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 @@ def __init__(self, file, align=True, bigendian=True, inclheader=False):
         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

From 89323dadc22cd8beca5e7df645d3b5de79e08b21 Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Mon, 12 Jun 2023 14:42:10 +0300
Subject: [PATCH 7/8] Update codeop from Python 3.11

---
 Lib/codeop.py            |  95 ++++-------
 Lib/test/test_opcode.py  | 356 +++++++++++++++++++++++++++++++++++++++
 Lib/test/test_opcodes.py | 137 ---------------
 3 files changed, 388 insertions(+), 200 deletions(-)
 create mode 100644 Lib/test/test_opcode.py
 delete mode 100644 Lib/test/test_opcodes.py

diff --git a/Lib/codeop.py b/Lib/codeop.py
index e29c0b38c0..2213b69f23 100644
--- a/Lib/codeop.py
+++ b/Lib/codeop.py
@@ -10,30 +10,6 @@
   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 @@
 
 __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")
-
-        try:
-            code1 = compiler(source + "\n", filename, symbol)
-        except SyntaxError as e:
-            err1 = e
-
+        warnings.simplefilter("ignore", (SyntaxWarning, DeprecationWarning))
         try:
-            code2 = compiler(source + "\n\n", filename, symbol)
-        except SyntaxError as e:
-            err2 = e
-
-    try:
-        if code:
-            return code
-        if not code1 and repr(err1) == repr(err2):
-            raise err1
-    finally:
-        err1 = err2 = None
-
+            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
+
+    return compiler(source, filename, symbol)
+
+
+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 @@ def __call__(self, source, filename, symbol):
                 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
diff --git a/Lib/test/test_opcode.py b/Lib/test/test_opcode.py
new file mode 100644
index 0000000000..170eb1cb1d
--- /dev/null
+++ b/Lib/test/test_opcode.py
@@ -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()
diff --git a/Lib/test/test_opcodes.py b/Lib/test/test_opcodes.py
deleted file mode 100644
index e880c3f1ac..0000000000
--- a/Lib/test/test_opcodes.py
+++ /dev/null
@@ -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()

From 436be2b96aef95bac54e9c250c44d395cdf9c627 Mon Sep 17 00:00:00 2001
From: DimitrisJim <d.f.hilliard@gmail.com>
Date: Mon, 12 Jun 2023 15:28:55 +0300
Subject: [PATCH 8/8] Upgrade colorsys from Python 3.11

---
 Lib/colorsys.py | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/Lib/colorsys.py b/Lib/colorsys.py
index 12b432537b..9bdc83e377 100644
--- a/Lib/colorsys.py
+++ b/Lib/colorsys.py
@@ -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: