Per discussion in [0], here is a patch set to remove support for Python versions older than 2.6.

[0]: https://www.postgresql.org/message-id/6d3b7b69-0970-4d40-671a-268c46e93...@2ndquadrant.com

--
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 2ab6474ac961bc4b061062ab9121d89735c12657 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 9 Dec 2019 11:14:02 +0100
Subject: [PATCH 1/2] Remove support for Python older than 2.6

---
 config/python.m4                              |   4 +-
 configure                                     |   4 +-
 doc/src/sgml/installation.sgml                |   2 +-
 doc/src/sgml/plpython.sgml                    |  16 +-
 src/pl/plpython/expected/README               |   4 -
 src/pl/plpython/expected/plpython_error_0.out | 447 -----------------
 .../expected/plpython_subtransaction.out      |  65 ---
 .../expected/plpython_subtransaction_0.out    | 448 ------------------
 .../expected/plpython_subtransaction_5.out    | 448 ------------------
 src/pl/plpython/plpy_elog.c                   |   6 -
 src/pl/plpython/plpython.h                    |  29 --
 .../plpython/sql/plpython_subtransaction.sql  |  37 --
 12 files changed, 7 insertions(+), 1503 deletions(-)
 delete mode 100644 src/pl/plpython/expected/plpython_error_0.out
 delete mode 100644 src/pl/plpython/expected/plpython_subtransaction_0.out
 delete mode 100644 src/pl/plpython/expected/plpython_subtransaction_5.out

diff --git a/config/python.m4 b/config/python.m4
index c51aa4e332..d41aeb2876 100644
--- a/config/python.m4
+++ b/config/python.m4
@@ -37,8 +37,8 @@ python_majorversion=`echo "$python_fullversion" | sed 
'[s/^\([0-9]*\).*/\1/]'`
 python_minorversion=`echo "$python_fullversion" | sed 
'[s/^[0-9]*\.\([0-9]*\).*/\1/]'`
 python_version=`echo "$python_fullversion" | sed 
'[s/^\([0-9]*\.[0-9]*\).*/\1/]'`
 # Reject unsupported Python versions as soon as practical.
-if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 4; then
-  AC_MSG_ERROR([Python version $python_version is too old (version 2.4 or 
later is required)])
+if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 6; then
+  AC_MSG_ERROR([Python version $python_version is too old (version 2.6 or 
later is required)])
 fi
 
 AC_MSG_CHECKING([for Python distutils module])
diff --git a/configure b/configure
index 3d9bd0bdf8..da62d23552 100755
--- a/configure
+++ b/configure
@@ -9614,8 +9614,8 @@ python_majorversion=`echo "$python_fullversion" | sed 
's/^\([0-9]*\).*/\1/'`
 python_minorversion=`echo "$python_fullversion" | sed 
's/^[0-9]*\.\([0-9]*\).*/\1/'`
 python_version=`echo "$python_fullversion" | sed 's/^\([0-9]*\.[0-9]*\).*/\1/'`
 # Reject unsupported Python versions as soon as practical.
-if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 4; then
-  as_fn_error $? "Python version $python_version is too old (version 2.4 or 
later is required)" "$LINENO" 5
+if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 6; then
+  as_fn_error $? "Python version $python_version is too old (version 2.6 or 
later is required)" "$LINENO" 5
 fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python distutils module" 
>&5
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 9c10a897f1..bcbcea2162 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -196,7 +196,7 @@ <title>Requirements</title>
       language, you need a <productname>Python</productname>
       installation with the header files and
       the <application>distutils</application> module.  The minimum
-      required version is <productname>Python</productname> 2.4.
+      required version is <productname>Python</productname> 2.6.
       <productname>Python 3</productname> is supported if it's
       version 3.1 or later; but see
       <xref linkend="plpython-python23"/>
diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index 4c2f7e85fd..31a0dd3e40 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -1335,9 +1335,8 @@ <title>Older Python Versions</title>
 
    <para>
     Context managers syntax using the <literal>with</literal> keyword
-    is available by default in Python 2.6.  If using PL/Python with an
-    older Python version, it is still possible to use explicit
-    subtransactions, although not as transparently.  You can call the
+    is available by default in Python 2.6.  For compatibility with
+    older Python versions, you can call the
     subtransaction manager's <literal>__enter__</literal> and
     <literal>__exit__</literal> functions using the
     <literal>enter</literal> and <literal>exit</literal> convenience
@@ -1367,17 +1366,6 @@ <title>Older Python Versions</title>
 $$ LANGUAGE plpythonu;
 </programlisting>
    </para>
-
-   <note>
-    <para>
-     Although context managers were implemented in Python 2.5, to use
-     the <literal>with</literal> syntax in that version you need to
-     use a <ulink
-     url="https://docs.python.org/release/2.5/ref/future.html";>future
-     statement</ulink>.  Because of implementation details, however,
-     you cannot use future statements in PL/Python functions.
-    </para>
-   </note>
   </sect2>
  </sect1>
 
diff --git a/src/pl/plpython/expected/README b/src/pl/plpython/expected/README
index b890563377..d735ae989b 100644
--- a/src/pl/plpython/expected/README
+++ b/src/pl/plpython/expected/README
@@ -1,12 +1,8 @@
 Guide to alternative expected files:
 
-plpython_error_0.out                   Python 2.4 and older
 plpython_error_5.out                   Python 3.5 and newer
 
 plpython_unicode.out                   server encoding != SQL_ASCII
 plpython_unicode_3.out                 server encoding == SQL_ASCII
 
-plpython_subtransaction_0.out  Python 2.4 and older (without with statement)
-plpython_subtransaction_5.out  Python 2.5 (without with statement)
-
 plpython_types_3.out                   Python 3.x
diff --git a/src/pl/plpython/expected/plpython_error_0.out 
b/src/pl/plpython/expected/plpython_error_0.out
deleted file mode 100644
index 290902b182..0000000000
--- a/src/pl/plpython/expected/plpython_error_0.out
+++ /dev/null
@@ -1,447 +0,0 @@
--- test error handling, i forgot to restore Warn_restart in
--- the trigger handler once. the errors and subsequent core dump were
--- interesting.
-/* Flat out Python syntax error
- */
-CREATE FUNCTION python_syntax_error() RETURNS text
-        AS
-'.syntaxerror'
-        LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "python_syntax_error"
-DETAIL:  SyntaxError: invalid syntax (line 2)
-/* With check_function_bodies = false the function should get defined
- * and the error reported when called
- */
-SET check_function_bodies = false;
-CREATE FUNCTION python_syntax_error() RETURNS text
-        AS
-'.syntaxerror'
-        LANGUAGE plpythonu;
-SELECT python_syntax_error();
-ERROR:  could not compile PL/Python function "python_syntax_error"
-DETAIL:  SyntaxError: invalid syntax (line 2)
-/* Run the function twice to check if the hashtable entry gets cleaned up */
-SELECT python_syntax_error();
-ERROR:  could not compile PL/Python function "python_syntax_error"
-DETAIL:  SyntaxError: invalid syntax (line 2)
-RESET check_function_bodies;
-/* Flat out syntax error
- */
-CREATE FUNCTION sql_syntax_error() RETURNS text
-        AS
-'plpy.execute("syntax error")'
-        LANGUAGE plpythonu;
-SELECT sql_syntax_error();
-ERROR:  spiexceptions.SyntaxError: syntax error at or near "syntax"
-LINE 1: syntax error
-        ^
-QUERY:  syntax error
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "sql_syntax_error", line 1, in <module>
-    plpy.execute("syntax error")
-PL/Python function "sql_syntax_error"
-/* check the handling of uncaught python exceptions
- */
-CREATE FUNCTION exception_index_invalid(text) RETURNS text
-       AS
-'return args[1]'
-       LANGUAGE plpythonu;
-SELECT exception_index_invalid('test');
-ERROR:  IndexError: list index out of range
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "exception_index_invalid", line 1, in <module>
-    return args[1]
-PL/Python function "exception_index_invalid"
-/* check handling of nested exceptions
- */
-CREATE FUNCTION exception_index_invalid_nested() RETURNS text
-       AS
-'rv = plpy.execute("SELECT test5(''foo'')")
-return rv[0]'
-       LANGUAGE plpythonu;
-SELECT exception_index_invalid_nested();
-ERROR:  spiexceptions.UndefinedFunction: function test5(unknown) does not exist
-LINE 1: SELECT test5('foo')
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-QUERY:  SELECT test5('foo')
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "exception_index_invalid_nested", line 1, in <module>
-    rv = plpy.execute("SELECT test5('foo')")
-PL/Python function "exception_index_invalid_nested"
-/* a typo
- */
-CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
-       AS
-'if "plan" not in SD:
-       q = "SELECT fname FROM users WHERE lname = $1"
-       SD["plan"] = plpy.prepare(q, [ "test" ])
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
-       return rv[0]["fname"]
-return None
-'
-       LANGUAGE plpythonu;
-SELECT invalid_type_uncaught('rick');
-ERROR:  spiexceptions.UndefinedObject: type "test" does not exist
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "invalid_type_uncaught", line 3, in <module>
-    SD["plan"] = plpy.prepare(q, [ "test" ])
-PL/Python function "invalid_type_uncaught"
-/* for what it's worth catch the exception generated by
- * the typo, and return None
- */
-CREATE FUNCTION invalid_type_caught(a text) RETURNS text
-       AS
-'if "plan" not in SD:
-       q = "SELECT fname FROM users WHERE lname = $1"
-       try:
-               SD["plan"] = plpy.prepare(q, [ "test" ])
-       except plpy.SPIError, ex:
-               plpy.notice(str(ex))
-               return None
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
-       return rv[0]["fname"]
-return None
-'
-       LANGUAGE plpythonu;
-SELECT invalid_type_caught('rick');
-NOTICE:  type "test" does not exist
- invalid_type_caught 
----------------------
- 
-(1 row)
-
-/* for what it's worth catch the exception generated by
- * the typo, and reraise it as a plain error
- */
-CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
-       AS
-'if "plan" not in SD:
-       q = "SELECT fname FROM users WHERE lname = $1"
-       try:
-               SD["plan"] = plpy.prepare(q, [ "test" ])
-       except plpy.SPIError, ex:
-               plpy.error(str(ex))
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
-       return rv[0]["fname"]
-return None
-'
-       LANGUAGE plpythonu;
-SELECT invalid_type_reraised('rick');
-ERROR:  plpy.Error: type "test" does not exist
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "invalid_type_reraised", line 6, in <module>
-    plpy.error(str(ex))
-PL/Python function "invalid_type_reraised"
-/* no typo no messing about
- */
-CREATE FUNCTION valid_type(a text) RETURNS text
-       AS
-'if "plan" not in SD:
-       SD["plan"] = plpy.prepare("SELECT fname FROM users WHERE lname = $1", [ 
"text" ])
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
-       return rv[0]["fname"]
-return None
-'
-       LANGUAGE plpythonu;
-SELECT valid_type('rick');
- valid_type 
-------------
- 
-(1 row)
-
-/* error in nested functions to get a traceback
-*/
-CREATE FUNCTION nested_error() RETURNS text
-       AS
-'def fun1():
-       plpy.error("boom")
-
-def fun2():
-       fun1()
-
-def fun3():
-       fun2()
-
-fun3()
-return "not reached"
-'
-       LANGUAGE plpythonu;
-SELECT nested_error();
-ERROR:  plpy.Error: boom
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "nested_error", line 10, in <module>
-    fun3()
-  PL/Python function "nested_error", line 8, in fun3
-    fun2()
-  PL/Python function "nested_error", line 5, in fun2
-    fun1()
-  PL/Python function "nested_error", line 2, in fun1
-    plpy.error("boom")
-PL/Python function "nested_error"
-/* raising plpy.Error is just like calling plpy.error
-*/
-CREATE FUNCTION nested_error_raise() RETURNS text
-       AS
-'def fun1():
-       raise plpy.Error("boom")
-
-def fun2():
-       fun1()
-
-def fun3():
-       fun2()
-
-fun3()
-return "not reached"
-'
-       LANGUAGE plpythonu;
-SELECT nested_error_raise();
-ERROR:  plpy.Error: boom
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "nested_error_raise", line 10, in <module>
-    fun3()
-  PL/Python function "nested_error_raise", line 8, in fun3
-    fun2()
-  PL/Python function "nested_error_raise", line 5, in fun2
-    fun1()
-  PL/Python function "nested_error_raise", line 2, in fun1
-    raise plpy.Error("boom")
-PL/Python function "nested_error_raise"
-/* using plpy.warning should not produce a traceback
-*/
-CREATE FUNCTION nested_warning() RETURNS text
-       AS
-'def fun1():
-       plpy.warning("boom")
-
-def fun2():
-       fun1()
-
-def fun3():
-       fun2()
-
-fun3()
-return "you''ve been warned"
-'
-       LANGUAGE plpythonu;
-SELECT nested_warning();
-WARNING:  boom
-   nested_warning   
---------------------
- you've been warned
-(1 row)
-
-/* AttributeError at toplevel used to give segfaults with the traceback
-*/
-CREATE FUNCTION toplevel_attribute_error() RETURNS void AS
-$$
-plpy.nonexistent
-$$ LANGUAGE plpythonu;
-SELECT toplevel_attribute_error();
-ERROR:  AttributeError: 'module' object has no attribute 'nonexistent'
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "toplevel_attribute_error", line 2, in <module>
-    plpy.nonexistent
-PL/Python function "toplevel_attribute_error"
-/* Calling PL/Python functions from SQL and vice versa should not lose context.
- */
-CREATE OR REPLACE FUNCTION python_traceback() RETURNS void AS $$
-def first():
-  second()
-
-def second():
-  third()
-
-def third():
-  plpy.execute("select sql_error()")
-
-first()
-$$ LANGUAGE plpythonu;
-CREATE OR REPLACE FUNCTION sql_error() RETURNS void AS $$
-begin
-  select 1/0;
-end
-$$ LANGUAGE plpgsql;
-CREATE OR REPLACE FUNCTION python_from_sql_error() RETURNS void AS $$
-begin
-  select python_traceback();
-end
-$$ LANGUAGE plpgsql;
-CREATE OR REPLACE FUNCTION sql_from_python_error() RETURNS void AS $$
-plpy.execute("select sql_error()")
-$$ LANGUAGE plpythonu;
-SELECT python_traceback();
-ERROR:  spiexceptions.DivisionByZero: division by zero
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "python_traceback", line 11, in <module>
-    first()
-  PL/Python function "python_traceback", line 3, in first
-    second()
-  PL/Python function "python_traceback", line 6, in second
-    third()
-  PL/Python function "python_traceback", line 9, in third
-    plpy.execute("select sql_error()")
-PL/Python function "python_traceback"
-SELECT sql_error();
-ERROR:  division by zero
-CONTEXT:  SQL statement "select 1/0"
-PL/pgSQL function sql_error() line 3 at SQL statement
-SELECT python_from_sql_error();
-ERROR:  spiexceptions.DivisionByZero: division by zero
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "python_traceback", line 11, in <module>
-    first()
-  PL/Python function "python_traceback", line 3, in first
-    second()
-  PL/Python function "python_traceback", line 6, in second
-    third()
-  PL/Python function "python_traceback", line 9, in third
-    plpy.execute("select sql_error()")
-PL/Python function "python_traceback"
-SQL statement "select python_traceback()"
-PL/pgSQL function python_from_sql_error() line 3 at SQL statement
-SELECT sql_from_python_error();
-ERROR:  spiexceptions.DivisionByZero: division by zero
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "sql_from_python_error", line 2, in <module>
-    plpy.execute("select sql_error()")
-PL/Python function "sql_from_python_error"
-/* check catching specific types of exceptions
- */
-CREATE TABLE specific (
-    i integer PRIMARY KEY
-);
-CREATE FUNCTION specific_exception(i integer) RETURNS void AS
-$$
-from plpy import spiexceptions
-try:
-    plpy.execute("insert into specific values (%s)" % (i or "NULL"));
-except spiexceptions.NotNullViolation, e:
-    plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
-except spiexceptions.UniqueViolation, e:
-    plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
-$$ LANGUAGE plpythonu;
-SELECT specific_exception(2);
- specific_exception 
---------------------
- 
-(1 row)
-
-SELECT specific_exception(NULL);
-NOTICE:  Violated the NOT NULL constraint, sqlstate 23502
- specific_exception 
---------------------
- 
-(1 row)
-
-SELECT specific_exception(2);
-NOTICE:  Violated the UNIQUE constraint, sqlstate 23505
- specific_exception 
---------------------
- 
-(1 row)
-
-/* SPI errors in PL/Python functions should preserve the SQLSTATE value
- */
-CREATE FUNCTION python_unique_violation() RETURNS void AS $$
-plpy.execute("insert into specific values (1)")
-plpy.execute("insert into specific values (1)")
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION catch_python_unique_violation() RETURNS text AS $$
-begin
-    begin
-        perform python_unique_violation();
-    exception when unique_violation then
-        return 'ok';
-    end;
-    return 'not reached';
-end;
-$$ language plpgsql;
-SELECT catch_python_unique_violation();
- catch_python_unique_violation 
--------------------------------
- ok
-(1 row)
-
-/* manually starting subtransactions - a bad idea
- */
-CREATE FUNCTION manual_subxact() RETURNS void AS $$
-plpy.execute("savepoint save")
-plpy.execute("create table foo(x integer)")
-plpy.execute("rollback to save")
-$$ LANGUAGE plpythonu;
-SELECT manual_subxact();
-ERROR:  plpy.SPIError: SPI_execute failed: SPI_ERROR_TRANSACTION
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "manual_subxact", line 2, in <module>
-    plpy.execute("savepoint save")
-PL/Python function "manual_subxact"
-/* same for prepared plans
- */
-CREATE FUNCTION manual_subxact_prepared() RETURNS void AS $$
-save = plpy.prepare("savepoint save")
-rollback = plpy.prepare("rollback to save")
-plpy.execute(save)
-plpy.execute("create table foo(x integer)")
-plpy.execute(rollback)
-$$ LANGUAGE plpythonu;
-SELECT manual_subxact_prepared();
-ERROR:  plpy.SPIError: SPI_execute_plan failed: SPI_ERROR_TRANSACTION
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "manual_subxact_prepared", line 4, in <module>
-    plpy.execute(save)
-PL/Python function "manual_subxact_prepared"
-/* raising plpy.spiexception.* from python code should preserve sqlstate
- */
-CREATE FUNCTION plpy_raise_spiexception() RETURNS void AS $$
-raise plpy.spiexceptions.DivisionByZero()
-$$ LANGUAGE plpythonu;
-DO $$
-BEGIN
-       SELECT plpy_raise_spiexception();
-EXCEPTION WHEN division_by_zero THEN
-       -- NOOP
-END
-$$ LANGUAGE plpgsql;
-/* setting a custom sqlstate should be handled
- */
-CREATE FUNCTION plpy_raise_spiexception_override() RETURNS void AS $$
-exc = plpy.spiexceptions.DivisionByZero()
-exc.sqlstate = 'SILLY'
-raise exc
-$$ LANGUAGE plpythonu;
-DO $$
-BEGIN
-       SELECT plpy_raise_spiexception_override();
-EXCEPTION WHEN SQLSTATE 'SILLY' THEN
-       -- NOOP
-END
-$$ LANGUAGE plpgsql;
-/* test the context stack trace for nested execution levels
- */
-CREATE FUNCTION notice_innerfunc() RETURNS int AS $$
-plpy.execute("DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$")
-return 1
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION notice_outerfunc() RETURNS int AS $$
-plpy.execute("SELECT notice_innerfunc()")
-return 1
-$$ LANGUAGE plpythonu;
-\set SHOW_CONTEXT always
-SELECT notice_outerfunc();
-NOTICE:  inside DO
-CONTEXT:  PL/Python anonymous code block
-SQL statement "DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$"
-PL/Python function "notice_innerfunc"
-SQL statement "SELECT notice_innerfunc()"
-PL/Python function "notice_outerfunc"
- notice_outerfunc 
-------------------
-                1
-(1 row)
-
diff --git a/src/pl/plpython/expected/plpython_subtransaction.out 
b/src/pl/plpython/expected/plpython_subtransaction.out
index 069f0992ab..8df64e7619 100644
--- a/src/pl/plpython/expected/plpython_subtransaction.out
+++ b/src/pl/plpython/expected/plpython_subtransaction.out
@@ -5,71 +5,6 @@
 CREATE TABLE subtransaction_tbl (
     i integer
 );
--- Explicit case for Python <2.6
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
-    try:
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-        if what_error == "SPI":
-            plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-        elif what_error == "Python":
-            raise Exception("Python exception")
-    except:
-        exc = False
-        subxact.__exit__(*sys.exc_info())
-        raise
-finally:
-    if exc:
-        subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_test();
- subtransaction_test 
----------------------
- 
-(1 row)
-
-SELECT * FROM subtransaction_tbl;
- i 
----
- 1
- 2
-(2 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-ERROR:  spiexceptions.InvalidTextRepresentation: invalid input syntax for type 
integer: "oops"
-LINE 1: INSERT INTO subtransaction_tbl VALUES ('oops')
-                                               ^
-QUERY:  INSERT INTO subtransaction_tbl VALUES ('oops')
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_test", line 11, in <module>
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-ERROR:  Exception: Python exception
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_test", line 13, in <module>
-    raise Exception("Python exception")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Context manager case for Python >=2.6
 CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
 AS $$
 with plpy.subtransaction():
diff --git a/src/pl/plpython/expected/plpython_subtransaction_0.out 
b/src/pl/plpython/expected/plpython_subtransaction_0.out
deleted file mode 100644
index 97ee42b5a9..0000000000
--- a/src/pl/plpython/expected/plpython_subtransaction_0.out
+++ /dev/null
@@ -1,448 +0,0 @@
---
--- Test explicit subtransactions
---
--- Test table to see if transactions get properly rolled back
-CREATE TABLE subtransaction_tbl (
-    i integer
-);
--- Explicit case for Python <2.6
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
-    try:
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-        if what_error == "SPI":
-            plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-        elif what_error == "Python":
-            raise Exception("Python exception")
-    except:
-        exc = False
-        subxact.__exit__(*sys.exc_info())
-        raise
-finally:
-    if exc:
-        subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_test();
- subtransaction_test 
----------------------
- 
-(1 row)
-
-SELECT * FROM subtransaction_tbl;
- i 
----
- 1
- 2
-(2 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-ERROR:  spiexceptions.InvalidTextRepresentation: invalid input syntax for type 
integer: "oops"
-LINE 1: INSERT INTO subtransaction_tbl VALUES ('oops')
-                                               ^
-QUERY:  INSERT INTO subtransaction_tbl VALUES ('oops')
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_test", line 11, in <module>
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-ERROR:  Exception: Python exception
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_test", line 13, in <module>
-    raise Exception("Python exception")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Context manager case for Python >=2.6
-CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
-AS $$
-with plpy.subtransaction():
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-    if what_error == "SPI":
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-    elif what_error == "Python":
-        raise Exception("Python exception")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "subtransaction_ctx_test"
-DETAIL:  SyntaxError: invalid syntax (line 3)
-SELECT subtransaction_ctx_test();
-ERROR:  function subtransaction_ctx_test() does not exist
-LINE 1: SELECT subtransaction_ctx_test();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('SPI');
-ERROR:  function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('SPI');
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('Python');
-ERROR:  function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('Python');
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions
-CREATE FUNCTION subtransaction_nested_test(swallow boolean = 'f') RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-    try:
-        with plpy.subtransaction():
-            plpy.execute("INSERT INTO subtransaction_tbl VALUES (3)")
-            plpy.execute("error")
-    except plpy.SPIError, e:
-        if not swallow:
-            raise
-        plpy.notice("Swallowed %s(%r)" % (e.__class__.__name__, e.args[0]))
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "subtransaction_nested_test"
-DETAIL:  SyntaxError: invalid syntax (line 4)
-SELECT subtransaction_nested_test();
-ERROR:  function subtransaction_nested_test() does not exist
-LINE 1: SELECT subtransaction_nested_test();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_nested_test('t');
-ERROR:  function subtransaction_nested_test(unknown) does not exist
-LINE 1: SELECT subtransaction_nested_test('t');
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions that recursively call code dealing with
--- subtransactions
-CREATE FUNCTION subtransaction_deeply_nested_test() RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-    plpy.execute("SELECT subtransaction_nested_test('t')")
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_deeply_nested_test"
-DETAIL:  SyntaxError: invalid syntax (line 4)
-SELECT subtransaction_deeply_nested_test();
-ERROR:  function subtransaction_deeply_nested_test() does not exist
-LINE 1: SELECT subtransaction_deeply_nested_test();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Error conditions from not opening/closing subtransactions
-CREATE FUNCTION subtransaction_exit_without_enter() RETURNS void
-AS $$
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_without_exit() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__exit__(None, None, None)
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__exit__(None, None, None)
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__enter__()
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
--- No warnings here, as the subtransaction gets indeed closed
-CREATE FUNCTION subtransaction_enter_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
-    s.__enter__()
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_enter_subtransaction_in_with"
-DETAIL:  SyntaxError: invalid syntax (line 3)
-CREATE FUNCTION subtransaction_exit_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
-    s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_exit_subtransaction_in_with"
-DETAIL:  SyntaxError: invalid syntax (line 3)
-SELECT subtransaction_exit_without_enter();
-ERROR:  ValueError: this subtransaction has not been entered
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_exit_without_enter", line 2, in <module>
-    plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_without_enter"
-SELECT subtransaction_enter_without_exit();
-WARNING:  forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_without_exit 
------------------------------------
- 
-(1 row)
-
-SELECT subtransaction_exit_twice();
-WARNING:  forcibly aborting a subtransaction that has not been exited
-ERROR:  ValueError: this subtransaction has not been entered
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_exit_twice", line 3, in <module>
-    plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_twice"
-SELECT subtransaction_enter_twice();
-WARNING:  forcibly aborting a subtransaction that has not been exited
-WARNING:  forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_twice 
-----------------------------
- 
-(1 row)
-
-SELECT subtransaction_exit_same_subtransaction_twice();
-ERROR:  ValueError: this subtransaction has already been exited
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_exit_same_subtransaction_twice", line 5, 
in <module>
-    s.__exit__(None, None, None)
-PL/Python function "subtransaction_exit_same_subtransaction_twice"
-SELECT subtransaction_enter_same_subtransaction_twice();
-WARNING:  forcibly aborting a subtransaction that has not been exited
-ERROR:  ValueError: this subtransaction has already been entered
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_enter_same_subtransaction_twice", line 4, 
in <module>
-    s.__enter__()
-PL/Python function "subtransaction_enter_same_subtransaction_twice"
-SELECT subtransaction_enter_subtransaction_in_with();
-ERROR:  function subtransaction_enter_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_enter_subtransaction_in_with();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT subtransaction_exit_subtransaction_in_with();
-ERROR:  function subtransaction_exit_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_exit_subtransaction_in_with();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
--- Make sure we don't get a "current transaction is aborted" error
-SELECT 1 as test;
- test 
-------
-    1
-(1 row)
-
--- Mix explicit subtransactions and normal SPI calls
-CREATE FUNCTION subtransaction_mix_explicit_and_implicit() RETURNS void
-AS $$
-p = plpy.prepare("INSERT INTO subtransaction_tbl VALUES ($1)", ["integer"])
-try:
-    with plpy.subtransaction():
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-        plpy.execute(p, [2])
-        plpy.execute(p, ["wrong"])
-except plpy.SPIError:
-    plpy.warning("Caught a SPI error from an explicit subtransaction")
-
-try:
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-    plpy.execute(p, [2])
-    plpy.execute(p, ["wrong"])
-except plpy.SPIError:
-    plpy.warning("Caught a SPI error")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_mix_explicit_and_implicit"
-DETAIL:  SyntaxError: invalid syntax (line 5)
-SELECT subtransaction_mix_explicit_and_implicit();
-ERROR:  function subtransaction_mix_explicit_and_implicit() does not exist
-LINE 1: SELECT subtransaction_mix_explicit_and_implicit();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Alternative method names for Python <2.6
-CREATE FUNCTION subtransaction_alternative_names() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.enter()
-s.exit(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_alternative_names();
- subtransaction_alternative_names 
-----------------------------------
- 
-(1 row)
-
--- try/catch inside a subtransaction block
-CREATE FUNCTION try_catch_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
-     plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-     try:
-         plpy.execute("INSERT INTO subtransaction_tbl VALUES ('a')")
-     except plpy.SPIError:
-         plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "try_catch_inside_subtransaction"
-DETAIL:  SyntaxError: invalid syntax (line 3)
-SELECT try_catch_inside_subtransaction();
-ERROR:  function try_catch_inside_subtransaction() does not exist
-LINE 1: SELECT try_catch_inside_subtransaction();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-ALTER TABLE subtransaction_tbl ADD PRIMARY KEY (i);
-CREATE FUNCTION pk_violation_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
-     plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-     try:
-         plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-     except plpy.SPIError:
-         plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"pk_violation_inside_subtransaction"
-DETAIL:  SyntaxError: invalid syntax (line 3)
-SELECT pk_violation_inside_subtransaction();
-ERROR:  function pk_violation_inside_subtransaction() does not exist
-LINE 1: SELECT pk_violation_inside_subtransaction();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-DROP TABLE subtransaction_tbl;
--- cursor/subtransactions interactions
-CREATE FUNCTION cursor_in_subxact() RETURNS int AS $$
-with plpy.subtransaction():
-    cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
-    cur.fetch(10)
-fetched = cur.fetch(10);
-return int(fetched[5]["i"])
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_in_subxact"
-DETAIL:  SyntaxError: invalid syntax (line 3)
-CREATE FUNCTION cursor_aborted_subxact() RETURNS int AS $$
-try:
-    with plpy.subtransaction():
-        cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
-        cur.fetch(10);
-        plpy.execute("select no_such_function()")
-except plpy.SPIError:
-    fetched = cur.fetch(10)
-    return int(fetched[5]["i"])
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_aborted_subxact"
-DETAIL:  SyntaxError: invalid syntax (line 4)
-CREATE FUNCTION cursor_plan_aborted_subxact() RETURNS int AS $$
-try:
-    with plpy.subtransaction():
-        plpy.execute('create temporary table tmp(i) '
-                     'as select generate_series(1, 10)')
-        plan = plpy.prepare("select i from tmp")
-        cur = plpy.cursor(plan)
-        plpy.execute("select no_such_function()")
-except plpy.SPIError:
-    fetched = cur.fetch(5)
-    return fetched[2]["i"]
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_plan_aborted_subxact"
-DETAIL:  SyntaxError: invalid syntax (line 4)
-CREATE FUNCTION cursor_close_aborted_subxact() RETURNS boolean AS $$
-try:
-    with plpy.subtransaction():
-        cur = plpy.cursor('select 1')
-        plpy.execute("select no_such_function()")
-except plpy.SPIError:
-    cur.close()
-    return True
-return False # not reached
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_close_aborted_subxact"
-DETAIL:  SyntaxError: invalid syntax (line 4)
-SELECT cursor_in_subxact();
-ERROR:  function cursor_in_subxact() does not exist
-LINE 1: SELECT cursor_in_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT cursor_aborted_subxact();
-ERROR:  function cursor_aborted_subxact() does not exist
-LINE 1: SELECT cursor_aborted_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT cursor_plan_aborted_subxact();
-ERROR:  function cursor_plan_aborted_subxact() does not exist
-LINE 1: SELECT cursor_plan_aborted_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT cursor_close_aborted_subxact();
-ERROR:  function cursor_close_aborted_subxact() does not exist
-LINE 1: SELECT cursor_close_aborted_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
diff --git a/src/pl/plpython/expected/plpython_subtransaction_5.out 
b/src/pl/plpython/expected/plpython_subtransaction_5.out
deleted file mode 100644
index e172e98f86..0000000000
--- a/src/pl/plpython/expected/plpython_subtransaction_5.out
+++ /dev/null
@@ -1,448 +0,0 @@
---
--- Test explicit subtransactions
---
--- Test table to see if transactions get properly rolled back
-CREATE TABLE subtransaction_tbl (
-    i integer
-);
--- Explicit case for Python <2.6
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
-    try:
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-        if what_error == "SPI":
-            plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-        elif what_error == "Python":
-            raise Exception("Python exception")
-    except:
-        exc = False
-        subxact.__exit__(*sys.exc_info())
-        raise
-finally:
-    if exc:
-        subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_test();
- subtransaction_test 
----------------------
- 
-(1 row)
-
-SELECT * FROM subtransaction_tbl;
- i 
----
- 1
- 2
-(2 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-ERROR:  spiexceptions.InvalidTextRepresentation: invalid input syntax for type 
integer: "oops"
-LINE 1: INSERT INTO subtransaction_tbl VALUES ('oops')
-                                               ^
-QUERY:  INSERT INTO subtransaction_tbl VALUES ('oops')
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_test", line 11, in <module>
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-ERROR:  Exception: Python exception
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_test", line 13, in <module>
-    raise Exception("Python exception")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Context manager case for Python >=2.6
-CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
-AS $$
-with plpy.subtransaction():
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-    if what_error == "SPI":
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-    elif what_error == "Python":
-        raise Exception("Python exception")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "subtransaction_ctx_test"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 3)
-SELECT subtransaction_ctx_test();
-ERROR:  function subtransaction_ctx_test() does not exist
-LINE 1: SELECT subtransaction_ctx_test();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('SPI');
-ERROR:  function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('SPI');
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('Python');
-ERROR:  function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('Python');
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions
-CREATE FUNCTION subtransaction_nested_test(swallow boolean = 'f') RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-    try:
-        with plpy.subtransaction():
-            plpy.execute("INSERT INTO subtransaction_tbl VALUES (3)")
-            plpy.execute("error")
-    except plpy.SPIError, e:
-        if not swallow:
-            raise
-        plpy.notice("Swallowed %s(%r)" % (e.__class__.__name__, e.args[0]))
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "subtransaction_nested_test"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 4)
-SELECT subtransaction_nested_test();
-ERROR:  function subtransaction_nested_test() does not exist
-LINE 1: SELECT subtransaction_nested_test();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_nested_test('t');
-ERROR:  function subtransaction_nested_test(unknown) does not exist
-LINE 1: SELECT subtransaction_nested_test('t');
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions that recursively call code dealing with
--- subtransactions
-CREATE FUNCTION subtransaction_deeply_nested_test() RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-    plpy.execute("SELECT subtransaction_nested_test('t')")
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_deeply_nested_test"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 4)
-SELECT subtransaction_deeply_nested_test();
-ERROR:  function subtransaction_deeply_nested_test() does not exist
-LINE 1: SELECT subtransaction_deeply_nested_test();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Error conditions from not opening/closing subtransactions
-CREATE FUNCTION subtransaction_exit_without_enter() RETURNS void
-AS $$
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_without_exit() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__exit__(None, None, None)
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__exit__(None, None, None)
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__enter__()
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
--- No warnings here, as the subtransaction gets indeed closed
-CREATE FUNCTION subtransaction_enter_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
-    s.__enter__()
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_enter_subtransaction_in_with"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 3)
-CREATE FUNCTION subtransaction_exit_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
-    s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_exit_subtransaction_in_with"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 3)
-SELECT subtransaction_exit_without_enter();
-ERROR:  ValueError: this subtransaction has not been entered
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_exit_without_enter", line 2, in <module>
-    plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_without_enter"
-SELECT subtransaction_enter_without_exit();
-WARNING:  forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_without_exit 
------------------------------------
- 
-(1 row)
-
-SELECT subtransaction_exit_twice();
-WARNING:  forcibly aborting a subtransaction that has not been exited
-ERROR:  ValueError: this subtransaction has not been entered
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_exit_twice", line 3, in <module>
-    plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_twice"
-SELECT subtransaction_enter_twice();
-WARNING:  forcibly aborting a subtransaction that has not been exited
-WARNING:  forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_twice 
-----------------------------
- 
-(1 row)
-
-SELECT subtransaction_exit_same_subtransaction_twice();
-ERROR:  ValueError: this subtransaction has already been exited
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_exit_same_subtransaction_twice", line 5, 
in <module>
-    s.__exit__(None, None, None)
-PL/Python function "subtransaction_exit_same_subtransaction_twice"
-SELECT subtransaction_enter_same_subtransaction_twice();
-WARNING:  forcibly aborting a subtransaction that has not been exited
-ERROR:  ValueError: this subtransaction has already been entered
-CONTEXT:  Traceback (most recent call last):
-  PL/Python function "subtransaction_enter_same_subtransaction_twice", line 4, 
in <module>
-    s.__enter__()
-PL/Python function "subtransaction_enter_same_subtransaction_twice"
-SELECT subtransaction_enter_subtransaction_in_with();
-ERROR:  function subtransaction_enter_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_enter_subtransaction_in_with();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT subtransaction_exit_subtransaction_in_with();
-ERROR:  function subtransaction_exit_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_exit_subtransaction_in_with();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
--- Make sure we don't get a "current transaction is aborted" error
-SELECT 1 as test;
- test 
-------
-    1
-(1 row)
-
--- Mix explicit subtransactions and normal SPI calls
-CREATE FUNCTION subtransaction_mix_explicit_and_implicit() RETURNS void
-AS $$
-p = plpy.prepare("INSERT INTO subtransaction_tbl VALUES ($1)", ["integer"])
-try:
-    with plpy.subtransaction():
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-        plpy.execute(p, [2])
-        plpy.execute(p, ["wrong"])
-except plpy.SPIError:
-    plpy.warning("Caught a SPI error from an explicit subtransaction")
-
-try:
-    plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-    plpy.execute(p, [2])
-    plpy.execute(p, ["wrong"])
-except plpy.SPIError:
-    plpy.warning("Caught a SPI error")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"subtransaction_mix_explicit_and_implicit"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 5)
-SELECT subtransaction_mix_explicit_and_implicit();
-ERROR:  function subtransaction_mix_explicit_and_implicit() does not exist
-LINE 1: SELECT subtransaction_mix_explicit_and_implicit();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Alternative method names for Python <2.6
-CREATE FUNCTION subtransaction_alternative_names() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.enter()
-s.exit(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_alternative_names();
- subtransaction_alternative_names 
-----------------------------------
- 
-(1 row)
-
--- try/catch inside a subtransaction block
-CREATE FUNCTION try_catch_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
-     plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-     try:
-         plpy.execute("INSERT INTO subtransaction_tbl VALUES ('a')")
-     except plpy.SPIError:
-         plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "try_catch_inside_subtransaction"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 3)
-SELECT try_catch_inside_subtransaction();
-ERROR:  function try_catch_inside_subtransaction() does not exist
-LINE 1: SELECT try_catch_inside_subtransaction();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-ALTER TABLE subtransaction_tbl ADD PRIMARY KEY (i);
-CREATE FUNCTION pk_violation_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
-     plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-     try:
-         plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-     except plpy.SPIError:
-         plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function 
"pk_violation_inside_subtransaction"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 3)
-SELECT pk_violation_inside_subtransaction();
-ERROR:  function pk_violation_inside_subtransaction() does not exist
-LINE 1: SELECT pk_violation_inside_subtransaction();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i 
----
-(0 rows)
-
-DROP TABLE subtransaction_tbl;
--- cursor/subtransactions interactions
-CREATE FUNCTION cursor_in_subxact() RETURNS int AS $$
-with plpy.subtransaction():
-    cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
-    cur.fetch(10)
-fetched = cur.fetch(10);
-return int(fetched[5]["i"])
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_in_subxact"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 3)
-CREATE FUNCTION cursor_aborted_subxact() RETURNS int AS $$
-try:
-    with plpy.subtransaction():
-        cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
-        cur.fetch(10);
-        plpy.execute("select no_such_function()")
-except plpy.SPIError:
-    fetched = cur.fetch(10)
-    return int(fetched[5]["i"])
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_aborted_subxact"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 4)
-CREATE FUNCTION cursor_plan_aborted_subxact() RETURNS int AS $$
-try:
-    with plpy.subtransaction():
-        plpy.execute('create temporary table tmp(i) '
-                     'as select generate_series(1, 10)')
-        plan = plpy.prepare("select i from tmp")
-        cur = plpy.cursor(plan)
-        plpy.execute("select no_such_function()")
-except plpy.SPIError:
-    fetched = cur.fetch(5)
-    return fetched[2]["i"]
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_plan_aborted_subxact"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 4)
-CREATE FUNCTION cursor_close_aborted_subxact() RETURNS boolean AS $$
-try:
-    with plpy.subtransaction():
-        cur = plpy.cursor('select 1')
-        plpy.execute("select no_such_function()")
-except plpy.SPIError:
-    cur.close()
-    return True
-return False # not reached
-$$ LANGUAGE plpythonu;
-ERROR:  could not compile PL/Python function "cursor_close_aborted_subxact"
-DETAIL:  SyntaxError: invalid syntax (<string>, line 4)
-SELECT cursor_in_subxact();
-ERROR:  function cursor_in_subxact() does not exist
-LINE 1: SELECT cursor_in_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT cursor_aborted_subxact();
-ERROR:  function cursor_aborted_subxact() does not exist
-LINE 1: SELECT cursor_aborted_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT cursor_plan_aborted_subxact();
-ERROR:  function cursor_plan_aborted_subxact() does not exist
-LINE 1: SELECT cursor_plan_aborted_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
-SELECT cursor_close_aborted_subxact();
-ERROR:  function cursor_close_aborted_subxact() does not exist
-LINE 1: SELECT cursor_close_aborted_subxact();
-               ^
-HINT:  No function matches the given name and argument types. You might need 
to add explicit type casts.
diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c
index eb562821a2..71b433ef26 100644
--- a/src/pl/plpython/plpy_elog.c
+++ b/src/pl/plpython/plpy_elog.c
@@ -242,12 +242,6 @@ PLy_traceback(PyObject *e, PyObject *v, PyObject *tb,
 
                PG_TRY();
                {
-                       /*
-                        * Ancient versions of Python (circa 2.3) contain a bug 
whereby
-                        * the fetches below can fail if the error indicator is 
set.
-                        */
-                       PyErr_Clear();
-
                        lineno = PyObject_GetAttrString(tb, "tb_lineno");
                        if (lineno == NULL)
                                elog(ERROR, "could not get line number from 
Python traceback");
diff --git a/src/pl/plpython/plpython.h b/src/pl/plpython/plpython.h
index dc8fcee001..d685d12d84 100644
--- a/src/pl/plpython/plpython.h
+++ b/src/pl/plpython/plpython.h
@@ -59,16 +59,6 @@
 #include <Python.h>
 #endif
 
-/*
- * Py_ssize_t compat for Python <= 2.4
- */
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-typedef int Py_ssize_t;
-
-#define PY_SSIZE_T_MAX INT_MAX
-#define PY_SSIZE_T_MIN INT_MIN
-#endif
-
 /*
  * Python 2/3 strings/unicode/bytes handling.  Python 2 has strings
  * and unicode, Python 3 has strings, which are unicode on the C
@@ -80,15 +70,6 @@ typedef int Py_ssize_t;
  * string to a Python string it converts the C string from the
  * PostgreSQL server encoding to a Python Unicode object.
  */
-
-#if PY_VERSION_HEX < 0x02060000
-/* This is exactly the compatibility layer that Python 2.6 uses. */
-#define PyBytes_AsString PyString_AsString
-#define PyBytes_FromStringAndSize PyString_FromStringAndSize
-#define PyBytes_Size PyString_Size
-#define PyObject_Bytes PyObject_Str
-#endif
-
 #if PY_MAJOR_VERSION >= 3
 #define PyString_Check(x) 0
 #define PyString_AsString(x) PLyUnicode_AsString(x)
@@ -104,16 +85,6 @@ typedef int Py_ssize_t;
 #define PyInt_AsLong(x) PyLong_AsLong(x)
 #endif
 
-/*
- * PyVarObject_HEAD_INIT was added in Python 2.6.  Its use is
- * necessary to handle both Python 2 and 3.  This replacement
- * definition is for Python <=2.5
- */
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size)              \
-               PyObject_HEAD_INIT(type) size,
-#endif
-
 /* Python 3 removed the Py_TPFLAGS_HAVE_ITER flag */
 #if PY_MAJOR_VERSION >= 3
 #define Py_TPFLAGS_HAVE_ITER 0
diff --git a/src/pl/plpython/sql/plpython_subtransaction.sql 
b/src/pl/plpython/sql/plpython_subtransaction.sql
index 398c65720c..38c8617828 100644
--- a/src/pl/plpython/sql/plpython_subtransaction.sql
+++ b/src/pl/plpython/sql/plpython_subtransaction.sql
@@ -8,43 +8,6 @@ CREATE TABLE subtransaction_tbl (
     i integer
 );
 
--- Explicit case for Python <2.6
-
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
-    try:
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-        plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
-        if what_error == "SPI":
-            plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-        elif what_error == "Python":
-            raise Exception("Python exception")
-    except:
-        exc = False
-        subxact.__exit__(*sys.exc_info())
-        raise
-finally:
-    if exc:
-        subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-
-SELECT subtransaction_test();
-SELECT * FROM subtransaction_tbl;
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-SELECT * FROM subtransaction_tbl;
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-SELECT * FROM subtransaction_tbl;
-TRUNCATE subtransaction_tbl;
-
--- Context manager case for Python >=2.6
-
 CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
 AS $$
 with plpy.subtransaction():
-- 
2.24.0

From 5cba1aba65f3a74c1e87fe5da56c561f9db6d9d4 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 9 Dec 2019 11:14:02 +0100
Subject: [PATCH 2/2] Modernize Python exception syntax

Change the exception syntax used in test and documentation to use the
more current

    except Exception as ex:

rather than the old

    except Exception, ex:

Since support for Python <2.6 has been removed, all supported versions
now support the new style, and we can save one step in the Python 3
compatibility conversion.
---
 doc/src/sgml/plpython.sgml                           | 8 ++++----
 src/pl/plpython/expected/plpython_ereport.out        | 4 ++--
 src/pl/plpython/expected/plpython_error.out          | 8 ++++----
 src/pl/plpython/expected/plpython_import.out         | 2 +-
 src/pl/plpython/expected/plpython_params.out         | 2 +-
 src/pl/plpython/expected/plpython_spi.out            | 6 +++---
 src/pl/plpython/expected/plpython_subtransaction.out | 2 +-
 src/pl/plpython/expected/plpython_types.out          | 2 +-
 src/pl/plpython/regress-python3-mangle.mk            | 2 +-
 src/pl/plpython/sql/plpython_ereport.sql             | 4 ++--
 src/pl/plpython/sql/plpython_error.sql               | 8 ++++----
 src/pl/plpython/sql/plpython_import.sql              | 2 +-
 src/pl/plpython/sql/plpython_params.sql              | 2 +-
 src/pl/plpython/sql/plpython_spi.sql                 | 6 +++---
 src/pl/plpython/sql/plpython_subtransaction.sql      | 2 +-
 src/pl/plpython/sql/plpython_types.sql               | 2 +-
 src/tools/msvc/vcregress.pl                          | 1 -
 17 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index 31a0dd3e40..7bdaf76bba 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -1227,7 +1227,7 @@ <title>Trapping Errors</title>
     return "denominator cannot equal zero"
 except spiexceptions.UniqueViolation:
     return "already have that fraction"
-except plpy.SPIError, e:
+except plpy.SPIError as e:
     return "other error, SQLSTATE %s" % e.sqlstate
 else:
     return "fraction inserted"
@@ -1274,7 +1274,7 @@ <title>Subtransaction Context Managers</title>
 try:
     plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE 
account_name = 'joe'")
     plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE 
account_name = 'mary'")
-except plpy.SPIError, e:
+except plpy.SPIError as e:
     result = "error transferring funds: %s" % e.args
 else:
     result = "funds transferred correctly"
@@ -1306,7 +1306,7 @@ <title>Subtransaction Context Managers</title>
     with plpy.subtransaction():
         plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE 
account_name = 'joe'")
         plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE 
account_name = 'mary'")
-except plpy.SPIError, e:
+except plpy.SPIError as e:
     result = "error transferring funds: %s" % e.args
 else:
     result = "funds transferred correctly"
@@ -1356,7 +1356,7 @@ <title>Older Python Versions</title>
         raise
     else:
         subxact.exit(None, None, None)
-except plpy.SPIError, e:
+except plpy.SPIError as e:
     result = "error transferring funds: %s" % e.args
 else:
     result = "funds transferred correctly"
diff --git a/src/pl/plpython/expected/plpython_ereport.out 
b/src/pl/plpython/expected/plpython_ereport.out
index e11999ce8c..b73bfff511 100644
--- a/src/pl/plpython/expected/plpython_ereport.out
+++ b/src/pl/plpython/expected/plpython_ereport.out
@@ -186,7 +186,7 @@ DETAIL:  message:(plpy.Error: message text), detail:(detail 
text), hint: (hint t
 DO $$
 try:
     plpy.execute("select raise_exception(_message => 'my message', _sqlstate 
=> 'XX987', _hint => 'some hint', _table_name => 'users_tab', _datatype_name => 
'user_type')")
-except Exception, e:
+except Exception as e:
     plpy.info(e.spidata)
     raise e
 $$ LANGUAGE plpythonu;
@@ -196,7 +196,7 @@ HINT:  some hint
 DO $$
 try:
     plpy.error(message  = 'my message', sqlstate = 'XX987', hint = 'some 
hint', table_name = 'users_tab', datatype_name = 'user_type')
-except Exception, e:
+except Exception as e:
     plpy.info('sqlstate: %s, hint: %s, table_name: %s, datatype_name: %s' % 
(e.sqlstate, e.hint, e.table_name, e.datatype_name))
     raise e
 $$ LANGUAGE plpythonu;
diff --git a/src/pl/plpython/expected/plpython_error.out 
b/src/pl/plpython/expected/plpython_error.out
index 4d615b41cc..b2f8fe83eb 100644
--- a/src/pl/plpython/expected/plpython_error.out
+++ b/src/pl/plpython/expected/plpython_error.out
@@ -97,7 +97,7 @@ CREATE FUNCTION invalid_type_caught(a text) RETURNS text
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
-       except plpy.SPIError, ex:
+       except plpy.SPIError as ex:
                plpy.notice(str(ex))
                return None
 rv = plpy.execute(SD["plan"], [ a ])
@@ -122,7 +122,7 @@ CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
-       except plpy.SPIError, ex:
+       except plpy.SPIError as ex:
                plpy.error(str(ex))
 rv = plpy.execute(SD["plan"], [ a ])
 if len(rv):
@@ -321,9 +321,9 @@ $$
 from plpy import spiexceptions
 try:
     plpy.execute("insert into specific values (%s)" % (i or "NULL"));
-except spiexceptions.NotNullViolation, e:
+except spiexceptions.NotNullViolation as e:
     plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
-except spiexceptions.UniqueViolation, e:
+except spiexceptions.UniqueViolation as e:
     plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
 $$ LANGUAGE plpythonu;
 SELECT specific_exception(2);
diff --git a/src/pl/plpython/expected/plpython_import.out 
b/src/pl/plpython/expected/plpython_import.out
index 1d981eacf1..b59e1821a7 100644
--- a/src/pl/plpython/expected/plpython_import.out
+++ b/src/pl/plpython/expected/plpython_import.out
@@ -21,7 +21,7 @@ CREATE FUNCTION import_succeed() returns text
   import re
   import string
   import time
-except Exception, ex:
+except Exception as ex:
        plpy.notice("import failed -- %s" % str(ex))
        return "failed, that wasn''t supposed to happen"
 return "succeeded, as expected"'
diff --git a/src/pl/plpython/expected/plpython_params.out 
b/src/pl/plpython/expected/plpython_params.out
index 8dc3802513..46ea7dfb90 100644
--- a/src/pl/plpython/expected/plpython_params.out
+++ b/src/pl/plpython/expected/plpython_params.out
@@ -25,7 +25,7 @@ CREATE FUNCTION test_param_names3(a0 integer) RETURNS boolean 
AS $$
 try:
        assert a1 == args[0]
        return False
-except NameError, e:
+except NameError as e:
        assert e.args[0].find("a1") > -1
        return True
 $$ LANGUAGE plpythonu;
diff --git a/src/pl/plpython/expected/plpython_spi.out 
b/src/pl/plpython/expected/plpython_spi.out
index e54dca9e2e..a09df68c7d 100644
--- a/src/pl/plpython/expected/plpython_spi.out
+++ b/src/pl/plpython/expected/plpython_spi.out
@@ -26,7 +26,7 @@ CREATE FUNCTION spi_prepared_plan_test_one(a text) RETURNS 
text
 try:
        rv = plpy.execute(SD["myplan"], [a])
        return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
-except Exception, ex:
+except Exception as ex:
        plpy.error(str(ex))
 return None
 '
@@ -39,7 +39,7 @@ CREATE FUNCTION spi_prepared_plan_test_two(a text) RETURNS 
text
 try:
        rv = SD["myplan"].execute([a])
        return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
-except Exception, ex:
+except Exception as ex:
        plpy.error(str(ex))
 return None
 '
@@ -53,7 +53,7 @@ try:
        rv = plpy.execute(SD["myplan"])
        if len(rv):
                return rv[0]["count"]
-except Exception, ex:
+except Exception as ex:
        plpy.error(str(ex))
 return None
 '
diff --git a/src/pl/plpython/expected/plpython_subtransaction.out 
b/src/pl/plpython/expected/plpython_subtransaction.out
index 8df64e7619..0d0ff2e36d 100644
--- a/src/pl/plpython/expected/plpython_subtransaction.out
+++ b/src/pl/plpython/expected/plpython_subtransaction.out
@@ -66,7 +66,7 @@ with plpy.subtransaction():
         with plpy.subtransaction():
             plpy.execute("INSERT INTO subtransaction_tbl VALUES (3)")
             plpy.execute("error")
-    except plpy.SPIError, e:
+    except plpy.SPIError as e:
         if not swallow:
             raise
         plpy.notice("Swallowed %s(%r)" % (e.__class__.__name__, e.args[0]))
diff --git a/src/pl/plpython/expected/plpython_types.out 
b/src/pl/plpython/expected/plpython_types.out
index 98b89b7d5c..0a2659fe29 100644
--- a/src/pl/plpython/expected/plpython_types.out
+++ b/src/pl/plpython/expected/plpython_types.out
@@ -400,7 +400,7 @@ CREATE FUNCTION test_type_unmarshal(x bytea) RETURNS text 
AS $$
 import marshal
 try:
     return marshal.loads(x)
-except ValueError, e:
+except ValueError as e:
     return 'FAILED: ' + str(e)
 $$ LANGUAGE plpythonu;
 SELECT test_type_unmarshal(x) FROM test_type_marshal() x;
diff --git a/src/pl/plpython/regress-python3-mangle.mk 
b/src/pl/plpython/regress-python3-mangle.mk
index 63948159bb..e18cb82154 100644
--- a/src/pl/plpython/regress-python3-mangle.mk
+++ b/src/pl/plpython/regress-python3-mangle.mk
@@ -14,7 +14,7 @@ REGRESS := $(foreach test,$(REGRESS),$(if $(filter 
$(test),$(REGRESS_PLPYTHON3_M
 pgregress-python3-mangle:
        $(MKDIR_P) sql/python3 expected/python3 results/python3
        for file in $(patsubst 
%,$(srcdir)/sql/%.sql,$(REGRESS_PLPYTHON3_MANGLE)) $(patsubst 
%,$(srcdir)/expected/%*.out,$(REGRESS_PLPYTHON3_MANGLE)); do \
-         sed -e 's/except \([[:alpha:]][[:alpha:].]*\), 
*\([[:alpha:]][[:alpha:]]*\):/except \1 as \2:/g' \
+         sed \
              -e "s/<type 'exceptions\.\([[:alpha:]]*\)'>/<class '\1'>/g" \
              -e "s/<type 'long'>/<class 'int'>/g" \
              -e "s/\([0-9][0-9]*\)L/\1/g" \
diff --git a/src/pl/plpython/sql/plpython_ereport.sql 
b/src/pl/plpython/sql/plpython_ereport.sql
index 889293d33c..58df2057ef 100644
--- a/src/pl/plpython/sql/plpython_ereport.sql
+++ b/src/pl/plpython/sql/plpython_ereport.sql
@@ -125,7 +125,7 @@ CREATE OR REPLACE FUNCTION raise_exception(_message text, 
_detail text DEFAULT N
 DO $$
 try:
     plpy.execute("select raise_exception(_message => 'my message', _sqlstate 
=> 'XX987', _hint => 'some hint', _table_name => 'users_tab', _datatype_name => 
'user_type')")
-except Exception, e:
+except Exception as e:
     plpy.info(e.spidata)
     raise e
 $$ LANGUAGE plpythonu;
@@ -133,7 +133,7 @@ CREATE OR REPLACE FUNCTION raise_exception(_message text, 
_detail text DEFAULT N
 DO $$
 try:
     plpy.error(message  = 'my message', sqlstate = 'XX987', hint = 'some 
hint', table_name = 'users_tab', datatype_name = 'user_type')
-except Exception, e:
+except Exception as e:
     plpy.info('sqlstate: %s, hint: %s, table_name: %s, datatype_name: %s' % 
(e.sqlstate, e.hint, e.table_name, e.datatype_name))
     raise e
 $$ LANGUAGE plpythonu;
diff --git a/src/pl/plpython/sql/plpython_error.sql 
b/src/pl/plpython/sql/plpython_error.sql
index d712eb1078..88d6936fd0 100644
--- a/src/pl/plpython/sql/plpython_error.sql
+++ b/src/pl/plpython/sql/plpython_error.sql
@@ -82,7 +82,7 @@ CREATE FUNCTION invalid_type_caught(a text) RETURNS text
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
-       except plpy.SPIError, ex:
+       except plpy.SPIError as ex:
                plpy.notice(str(ex))
                return None
 rv = plpy.execute(SD["plan"], [ a ])
@@ -104,7 +104,7 @@ CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
-       except plpy.SPIError, ex:
+       except plpy.SPIError as ex:
                plpy.error(str(ex))
 rv = plpy.execute(SD["plan"], [ a ])
 if len(rv):
@@ -247,9 +247,9 @@ CREATE FUNCTION specific_exception(i integer) RETURNS void 
AS
 from plpy import spiexceptions
 try:
     plpy.execute("insert into specific values (%s)" % (i or "NULL"));
-except spiexceptions.NotNullViolation, e:
+except spiexceptions.NotNullViolation as e:
     plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
-except spiexceptions.UniqueViolation, e:
+except spiexceptions.UniqueViolation as e:
     plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
 $$ LANGUAGE plpythonu;
 
diff --git a/src/pl/plpython/sql/plpython_import.sql 
b/src/pl/plpython/sql/plpython_import.sql
index d4a4a24af4..ec887677e1 100644
--- a/src/pl/plpython/sql/plpython_import.sql
+++ b/src/pl/plpython/sql/plpython_import.sql
@@ -24,7 +24,7 @@ CREATE FUNCTION import_succeed() returns text
   import re
   import string
   import time
-except Exception, ex:
+except Exception as ex:
        plpy.notice("import failed -- %s" % str(ex))
        return "failed, that wasn''t supposed to happen"
 return "succeeded, as expected"'
diff --git a/src/pl/plpython/sql/plpython_params.sql 
b/src/pl/plpython/sql/plpython_params.sql
index f580abe53d..ee75c4dc41 100644
--- a/src/pl/plpython/sql/plpython_params.sql
+++ b/src/pl/plpython/sql/plpython_params.sql
@@ -29,7 +29,7 @@ CREATE FUNCTION test_param_names3(a0 integer) RETURNS boolean 
AS $$
 try:
        assert a1 == args[0]
        return False
-except NameError, e:
+except NameError as e:
        assert e.args[0].find("a1") > -1
        return True
 $$ LANGUAGE plpythonu;
diff --git a/src/pl/plpython/sql/plpython_spi.sql 
b/src/pl/plpython/sql/plpython_spi.sql
index fcf049cb66..dd77833ed5 100644
--- a/src/pl/plpython/sql/plpython_spi.sql
+++ b/src/pl/plpython/sql/plpython_spi.sql
@@ -31,7 +31,7 @@ CREATE FUNCTION spi_prepared_plan_test_one(a text) RETURNS 
text
 try:
        rv = plpy.execute(SD["myplan"], [a])
        return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
-except Exception, ex:
+except Exception as ex:
        plpy.error(str(ex))
 return None
 '
@@ -45,7 +45,7 @@ CREATE FUNCTION spi_prepared_plan_test_two(a text) RETURNS 
text
 try:
        rv = SD["myplan"].execute([a])
        return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
-except Exception, ex:
+except Exception as ex:
        plpy.error(str(ex))
 return None
 '
@@ -60,7 +60,7 @@ CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS 
text
        rv = plpy.execute(SD["myplan"])
        if len(rv):
                return rv[0]["count"]
-except Exception, ex:
+except Exception as ex:
        plpy.error(str(ex))
 return None
 '
diff --git a/src/pl/plpython/sql/plpython_subtransaction.sql 
b/src/pl/plpython/sql/plpython_subtransaction.sql
index 38c8617828..47bb11f157 100644
--- a/src/pl/plpython/sql/plpython_subtransaction.sql
+++ b/src/pl/plpython/sql/plpython_subtransaction.sql
@@ -40,7 +40,7 @@ CREATE FUNCTION subtransaction_nested_test(swallow boolean = 
'f') RETURNS text
         with plpy.subtransaction():
             plpy.execute("INSERT INTO subtransaction_tbl VALUES (3)")
             plpy.execute("error")
-    except plpy.SPIError, e:
+    except plpy.SPIError as e:
         if not swallow:
             raise
         plpy.notice("Swallowed %s(%r)" % (e.__class__.__name__, e.args[0]))
diff --git a/src/pl/plpython/sql/plpython_types.sql 
b/src/pl/plpython/sql/plpython_types.sql
index cc0524ee80..0d207d9c01 100644
--- a/src/pl/plpython/sql/plpython_types.sql
+++ b/src/pl/plpython/sql/plpython_types.sql
@@ -163,7 +163,7 @@ CREATE FUNCTION test_type_unmarshal(x bytea) RETURNS text 
AS $$
 import marshal
 try:
     return marshal.loads(x)
-except ValueError, e:
+except ValueError as e:
     return 'FAILED: ' + str(e)
 $$ LANGUAGE plpythonu;
 
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index 8a0f132199..7915ee7925 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -290,7 +290,6 @@ sub mangle_plpython3
                                close($handle);
                                do
                                {
-                                       s/except ([[:alpha:]][[:alpha:].]*), 
*([[:alpha:]][[:alpha:]]*):/except $1 as $2:/g;
                                        s/<type 
'exceptions\.([[:alpha:]]*)'>/<class '$1'>/g;
                                        s/<type 'long'>/<class 'int'>/g;
                                        s/([0-9][0-9]*)L/$1/g;
-- 
2.24.0

Reply via email to