From 781079a3f755b33e36505bd98cdff209427614c1 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sun, 6 Mar 2022 16:57:28 -0800
Subject: [PATCH v6 4/4] plpython: Adjust docs after removal of Python 2
 support.

Discussion: https://postgr.es/m/20211031184548.g4sxfe47n2kyi55r@alap3.anarazel.de
---
 doc/src/sgml/hstore.sgml               |   8 +-
 doc/src/sgml/json.sgml                 |   9 +-
 doc/src/sgml/ltree.sgml                |   8 +-
 doc/src/sgml/plpython.sgml             | 275 +++++--------------------
 doc/src/sgml/ref/comment.sgml          |   2 +-
 doc/src/sgml/ref/create_transform.sgml |   6 +-
 doc/src/sgml/ref/drop_transform.sgml   |   4 +-
 7 files changed, 63 insertions(+), 249 deletions(-)

diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml
index 870063c288b..679878b3afc 100644
--- a/doc/src/sgml/hstore.sgml
+++ b/doc/src/sgml/hstore.sgml
@@ -943,12 +943,8 @@ ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || '';
    and <literal>hstore_plperlu</literal>, for trusted and untrusted PL/Perl.
    If you install these transforms and specify them when creating a
    function, <type>hstore</type> values are mapped to Perl hashes.  The
-   extensions for PL/Python are
-   called <literal>hstore_plpythonu</literal>, <literal>hstore_plpython2u</literal>,
-   and <literal>hstore_plpython3u</literal>
-   (see <xref linkend="plpython-python23"/> for the PL/Python naming
-   convention).  If you use them, <type>hstore</type> values are mapped to
-   Python dictionaries.
+   extension for PL/Python is called <literal>hstore_plpython3u</literal>.
+   If you use it, <type>hstore</type> values are mapped to Python dictionaries.
   </para>
 
   <caution>
diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml
index 673c70c3bb8..b3b16b8a77e 100644
--- a/doc/src/sgml/json.sgml
+++ b/doc/src/sgml/json.sgml
@@ -716,12 +716,9 @@ UPDATE table_name SET jsonb_field[1]['a'] = '1';
   </para>
 
   <para>
-   The extensions for PL/Python are called <literal>jsonb_plpythonu</literal>,
-   <literal>jsonb_plpython2u</literal>, and
-   <literal>jsonb_plpython3u</literal> (see <xref
-   linkend="plpython-python23"/> for the PL/Python naming convention).  If you
-   use them, <type>jsonb</type> values are mapped to Python dictionaries,
-   lists, and scalars, as appropriate.
+   The extensions for PL/Python is called <literal>jsonb_plpython3u</literal>.
+   If you use it, <type>jsonb</type> values are mapped to Python
+   dictionaries, lists, and scalars, as appropriate.
   </para>
 
   <para>
diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml
index 436be76bfaa..4ff384c7ee7 100644
--- a/doc/src/sgml/ltree.sgml
+++ b/doc/src/sgml/ltree.sgml
@@ -826,12 +826,8 @@ ltreetest=&gt; SELECT ins_label(path,2,'Space') FROM test WHERE path &lt;@ 'Top.
   <title>Transforms</title>
 
   <para>
-   Additional extensions are available that implement transforms for
-   the <type>ltree</type> type for PL/Python.  The extensions are
-   called <literal>ltree_plpythonu</literal>, <literal>ltree_plpython2u</literal>,
-   and <literal>ltree_plpython3u</literal>
-   (see <xref linkend="plpython-python23"/> for the PL/Python naming
-   convention).  If you install these transforms and specify them when
+   The <literal>ltree_plpython3u</literal> implement transforms for the
+   <type>ltree</type> type for PL/Python. If installed and specified when
    creating a function, <type>ltree</type> values are mapped to Python lists.
    (The reverse is currently not supported, however.)
   </para>
diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index b67f8f4aaed..fab4330cd1d 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -14,8 +14,7 @@
 
  <para>
   To install PL/Python in a particular database, use
-  <literal>CREATE EXTENSION plpythonu</literal> (but
-  see also <xref linkend="plpython-python23"/>).
+  <literal>CREATE EXTENSION plpython3u</literal>.
  </para>
 
   <tip>
@@ -28,14 +27,14 @@
  <para>
   PL/Python is only available as an <quote>untrusted</quote> language, meaning
   it does not offer any way of restricting what users can do in it and
-  is therefore named <literal>plpythonu</literal>.  A trusted
+  is therefore named <literal>plpython3u</literal>.  A trusted
   variant <literal>plpython</literal> might become available in the future
   if a secure execution mechanism is developed in Python.  The
   writer of a function in untrusted PL/Python must take care that the
   function cannot be used to do anything unwanted, since it will be
   able to do anything that could be done by a user logged in as the
   database administrator.  Only superusers can create functions in
-  untrusted languages such as <literal>plpythonu</literal>.
+  untrusted languages such as <literal>plpython3u</literal>.
  </para>
 
  <note>
@@ -51,133 +50,10 @@
   <title>Python 2 vs. Python 3</title>
 
   <para>
-   PL/Python supports both the Python 2 and Python 3 language
-   variants.  (The PostgreSQL installation instructions might contain
-   more precise information about the exact supported minor versions
-   of Python.)  Because the Python 2 and Python 3 language variants
-   are incompatible in some important aspects, the following naming
-   and transitioning scheme is used by PL/Python to avoid mixing them:
-
-   <itemizedlist>
-    <listitem>
-     <para>
-      The PostgreSQL language named <literal>plpython2u</literal>
-      implements PL/Python based on the Python 2 language variant.
-     </para>
-    </listitem>
-
-    <listitem>
-     <para>
-      The PostgreSQL language named <literal>plpython3u</literal>
-      implements PL/Python based on the Python 3 language variant.
-     </para>
-    </listitem>
-
-    <listitem>
-     <para>
-      The language named <literal>plpythonu</literal> implements
-      PL/Python based on the default Python language variant, which is
-      currently Python 2.  (This default is independent of what any
-      local Python installations might consider to be
-      their <quote>default</quote>, for example,
-      what <filename>/usr/bin/python</filename> might be.)  The
-      default will probably be changed to Python 3 in a distant future
-      release of PostgreSQL, depending on the progress of the
-      migration to Python 3 in the Python community.
-     </para>
-    </listitem>
-   </itemizedlist>
-
-   This scheme is analogous to the recommendations in <ulink
-   url="https://www.python.org/dev/peps/pep-0394/">PEP 394</ulink> regarding the
-   naming and transitioning of the <command>python</command> command.
-  </para>
-
-  <para>
-   It depends on the build configuration or the installed packages
-   whether PL/Python for Python 2 or Python 3 or both are available.
-  </para>
-
-  <tip>
-   <para>
-    The built variant depends on which Python version was found during
-    the installation or which version was explicitly set using
-    the <envar>PYTHON</envar> environment variable;
-    see <xref linkend="install-procedure"/>.  To make both variants of
-    PL/Python available in one installation, the source tree has to be
-    configured and built twice.
-   </para>
-  </tip>
-
-  <para>
-   This results in the following usage and migration strategy:
-
-   <itemizedlist>
-    <listitem>
-     <para>
-      Existing users and users who are currently not interested in
-      Python 3 use the language name <literal>plpythonu</literal> and
-      don't have to change anything for the foreseeable future.  It is
-      recommended to gradually <quote>future-proof</quote> the code
-      via migration to Python 2.6/2.7 to simplify the eventual
-      migration to Python 3.
-     </para>
-
-     <para>
-      In practice, many PL/Python functions will migrate to Python 3
-      with few or no changes.
-     </para>
-    </listitem>
-
-    <listitem>
-     <para>
-      Users who know that they have heavily Python 2 dependent code
-      and don't plan to ever change it can make use of
-      the <literal>plpython2u</literal> language name.  This will
-      continue to work into the very distant future, until Python 2
-      support might be completely dropped by PostgreSQL.
-     </para>
-    </listitem>
-
-    <listitem>
-     <para>
-      Users who want to dive into Python 3 can use
-      the <literal>plpython3u</literal> language name, which will keep
-      working forever by today's standards.  In the distant future,
-      when Python 3 might become the default, they might like to
-      remove the <quote>3</quote> for aesthetic reasons.
-     </para>
-    </listitem>
-
-    <listitem>
-     <para>
-      Daredevils, who want to build a Python-3-only operating system
-      environment, can change the contents of
-      <literal>plpythonu</literal>'s extension control and script files
-      to make <literal>plpythonu</literal> be equivalent
-      to <literal>plpython3u</literal>, keeping in mind that this
-      would make their installation incompatible with most of the rest
-      of the world.
-     </para>
-    </listitem>
-   </itemizedlist>
-  </para>
-
-  <para>
-   See also the
-   document <ulink url="https://docs.python.org/3/whatsnew/3.0.html">What's
-   New In Python 3.0</ulink> for more information about porting to
-   Python 3.
-  </para>
-
-  <para>
-   It is not allowed to use PL/Python based on Python 2 and PL/Python
-   based on Python 3 in the same session, because the symbols in the
-   dynamic modules would clash, which could result in crashes of the
-   PostgreSQL server process.  There is a check that prevents mixing
-   Python major versions in a session, which will abort the session if
-   a mismatch is detected.  It is possible, however, to use both
-   PL/Python variants in the same database, from separate sessions.
+   PL/Python supports only Python 3. Past versions of
+   <productname>PostgreSQL</productname> supported Python 2, using the
+   <literal>plpyhonu</literal> and <literal>plpython2u</literal> language
+   names.
   </para>
  </sect1>
 
@@ -193,7 +69,7 @@ CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-list<
   RETURNS <replaceable>return-type</replaceable>
 AS $$
   # PL/Python function body
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
   </para>
 
@@ -225,7 +101,7 @@ AS $$
   if a &gt; b:
     return a
   return b
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
 
    The Python code that is given as the body of the function definition
@@ -255,7 +131,7 @@ CREATE FUNCTION pystrip(x text)
 AS $$
   x = x.strip()  # error
   return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
    because assigning to <varname>x</varname>
    makes <varname>x</varname> a local variable for the entire block,
@@ -271,7 +147,7 @@ AS $$
   global x
   x = x.strip()  # ok now
   return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
    But it is advisable not to rely on this implementation detail of
    PL/Python.  It is better to treat the function parameters as
@@ -303,11 +179,8 @@ $$ LANGUAGE plpythonu;
 
      <listitem>
       <para>
-       PostgreSQL <type>smallint</type> and <type>int</type> are
-       converted to Python <type>int</type>.
-       PostgreSQL <type>bigint</type> and <type>oid</type> are converted
-       to <type>long</type> in Python 2 and to <type>int</type> in
-       Python 3.
+       PostgreSQL <type>smallint</type>, <type>int</type>, <type>bigint</type>
+       and <type>oid</type> are converted to Python <type>int</type>.
       </para>
      </listitem>
 
@@ -335,19 +208,15 @@ $$ LANGUAGE plpythonu;
 
      <listitem>
       <para>
-       PostgreSQL <type>bytea</type> is converted to
-       Python <type>str</type> in Python 2 and to <type>bytes</type>
-       in Python 3.  In Python 2, the string should be treated as a
-       byte sequence without any character encoding.
+       PostgreSQL <type>bytea</type> is converted to Python <type>bytes</type>.
       </para>
      </listitem>
 
      <listitem>
       <para>
-       All other data types, including the PostgreSQL character string
-       types, are converted to a Python <type>str</type>.  In Python
-       2, this string will be in the PostgreSQL server encoding; in
-       Python 3, it will be a Unicode string like all strings.
+       All other data types, including the PostgreSQL character string types,
+       are converted to a Python <type>str</type> (in Unicode like all Python
+       strings).
       </para>
      </listitem>
 
@@ -375,10 +244,10 @@ $$ LANGUAGE plpythonu;
 
      <listitem>
       <para>
-       When the PostgreSQL return type is <type>bytea</type>, the
-       return value will be converted to a string (Python 2) or bytes
-       (Python 3) using the respective Python built-ins, with the
-       result being converted to <type>bytea</type>.
+       When the PostgreSQL return type is <type>bytea</type>, the return value
+       will be converted to Python <type>bytes</type> using the respective
+       Python built-ins, with the result being converted to
+       <type>bytea</type>.
       </para>
      </listitem>
 
@@ -393,14 +262,8 @@ $$ LANGUAGE plpythonu;
       </para>
 
       <para>
-       Strings in Python 2 are required to be in the PostgreSQL server
-       encoding when they are passed to PostgreSQL.  Strings that are
-       not valid in the current server encoding will raise an error,
-       but not all encoding mismatches can be detected, so garbage
-       data can still result when this is not done correctly.  Unicode
-       strings are converted to the correct encoding automatically, so
-       it can be safer and more convenient to use those.  In Python 3,
-       all strings are Unicode strings.
+       Strings are automatically converted to the PostgreSQL server encoding
+       when they are passed to PostgreSQL.
       </para>
      </listitem>
 
@@ -440,7 +303,7 @@ AS $$
   if a &gt; b:
     return a
   return b
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
 
    As shown above, to return an SQL null value from a PL/Python
@@ -461,10 +324,10 @@ CREATE FUNCTION return_arr()
   RETURNS int[]
 AS $$
 return [1, 2, 3, 4, 5]
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 SELECT return_arr();
- return_arr  
+ return_arr
 -------------
  {1,2,3,4,5}
 (1 row)
@@ -479,11 +342,11 @@ SELECT return_arr();
 CREATE FUNCTION test_type_conversion_array_int4(x int4[]) RETURNS int4[] AS $$
 plpy.info(x, type(x))
 return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 SELECT * FROM test_type_conversion_array_int4(ARRAY[[1,2,3],[4,5,6]]);
 INFO:  ([[1, 2, 3], [4, 5, 6]], &lt;type 'list'&gt;)
- test_type_conversion_array_int4 
+ test_type_conversion_array_int4
 ---------------------------------
  {{1,2,3},{4,5,6}}
 (1 row)
@@ -506,7 +369,7 @@ CREATE FUNCTION return_str_arr()
   RETURNS varchar[]
 AS $$
 return "hello"
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 SELECT return_str_arr();
  return_str_arr
@@ -540,7 +403,7 @@ AS $$
   if (e["age"] &lt; 30) and (e["salary"] &gt; 100000):
     return True
   return False
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
   </para>
 
@@ -574,7 +437,7 @@ CREATE FUNCTION make_pair (name text, value integer)
 AS $$
   return ( name, value )
   # or alternatively, as list: return [ name, value ]
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
 
        To return an SQL null for any column, insert <symbol>None</symbol> at
@@ -600,7 +463,7 @@ CREATE FUNCTION make_pair (name text, value integer)
   RETURNS named_value
 AS $$
   return { "name": name, "value": value }
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
 
        Any extra dictionary key/value pairs are ignored. Missing keys are
@@ -633,7 +496,7 @@ AS $$
   nv.name = name
   nv.value = value
   return nv
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
       </para>
      </listitem>
@@ -646,7 +509,7 @@ $$ LANGUAGE plpythonu;
 <programlisting>
 CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$
 return (1, 2)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 SELECT * FROM multiout_simple();
 </programlisting>
@@ -657,7 +520,7 @@ SELECT * FROM multiout_simple();
 <programlisting>
 CREATE PROCEDURE python_triple(INOUT a integer, INOUT b integer) AS $$
 return (a * 3, b * 3)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 CALL python_triple(5, 10);
 </programlisting>
@@ -693,7 +556,7 @@ AS $$
   # return tuple containing lists as composite types
   # all other combinations work also
   return ( [ how, "World" ], [ how, "PostgreSQL" ], [ how, "PL/Python" ] )
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
       </para>
      </listitem>
@@ -724,7 +587,7 @@ AS $$
       return ( self.how, self.who[self.ndx] )
 
   return producer(how, [ "World", "PostgreSQL", "PL/Python" ])
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
       </para>
      </listitem>
@@ -740,7 +603,7 @@ CREATE FUNCTION greet (how text)
 AS $$
   for who in [ "World", "PostgreSQL", "PL/Python" ]:
     yield ( how, who )
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
 
       </para>
@@ -756,7 +619,7 @@ $$ LANGUAGE plpythonu;
 <programlisting>
 CREATE FUNCTION multiout_simple_setof(n integer, OUT integer, OUT integer) RETURNS SETOF record AS $$
 return [(1, 2)] * n
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 SELECT * FROM multiout_simple_setof(3);
 </programlisting>
@@ -794,7 +657,7 @@ SELECT * FROM multiout_simple_setof(3);
 <programlisting>
 DO $$
     # PL/Python code
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
 
    An anonymous code block receives no arguments, and whatever value it
@@ -1089,7 +952,7 @@ CREATE FUNCTION usesavedplan() RETURNS trigger AS $$
         plan = plpy.prepare("SELECT 1")
         SD["plan"] = plan
     # rest of function
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
      </para>
     </listitem>
@@ -1132,7 +995,7 @@ for row in plpy.cursor("select num from largetable"):
     if row['num'] % 2:
          odd += 1
 return odd
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$
 odd = 0
@@ -1145,7 +1008,7 @@ while True:
         if row['num'] % 2:
             odd += 1
 return odd
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$
 odd = 0
@@ -1153,7 +1016,7 @@ plan = plpy.prepare("select num from largetable where num % $1 &lt;&gt; 0", ["in
 rows = list(plpy.cursor(plan, [2]))  # or: = list(plan.cursor([2]))
 
 return len(rows)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
      </para>
 
@@ -1198,7 +1061,7 @@ CREATE FUNCTION try_adding_joe() RETURNS text AS $$
         return "something went wrong"
     else:
         return "Joe added"
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
    </para>
 
@@ -1231,7 +1094,7 @@ except plpy.SPIError as e:
     return "other error, SQLSTATE %s" % e.sqlstate
 else:
     return "fraction inserted"
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
     Note that because all exceptions from
     the <literal>plpy.spiexceptions</literal> module inherit
@@ -1280,7 +1143,7 @@ else:
     result = "funds transferred correctly"
 plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
 plpy.execute(plan, [result])
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
     If the second <literal>UPDATE</literal> statement results in an
     exception being raised, this function will report the error, but
@@ -1312,7 +1175,7 @@ else:
     result = "funds transferred correctly"
 plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
 plpy.execute(plan, [result])
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 </programlisting>
     Note that the use of <literal>try/catch</literal> is still
     required.  Otherwise the exception would propagate to the top of
@@ -1329,44 +1192,6 @@ $$ LANGUAGE plpythonu;
     to be rolled back.
    </para>
   </sect2>
-
-  <sect2>
-   <title>Older Python Versions</title>
-
-   <para>
-    Context managers syntax using the <literal>with</literal> keyword
-    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
-    aliases.  The example function that transfers funds could be
-    written as:
-<programlisting>
-CREATE FUNCTION transfer_funds_old() RETURNS void AS $$
-try:
-    subxact = plpy.subtransaction()
-    subxact.enter()
-    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:
-        import sys
-        subxact.exit(*sys.exc_info())
-        raise
-    else:
-        subxact.exit(None, None, None)
-except plpy.SPIError as e:
-    result = "error transferring funds: %s" % e.args
-else:
-    result = "funds transferred correctly"
-
-plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
-plpy.execute(plan, [result])
-$$ LANGUAGE plpythonu;
-</programlisting>
-   </para>
-  </sect2>
  </sect1>
 
  <sect1 id="plpython-transactions">
@@ -1389,7 +1214,7 @@ $$ LANGUAGE plpythonu;
    Here is an example:
 <programlisting>
 CREATE PROCEDURE transaction_test1()
-LANGUAGE plpythonu
+LANGUAGE plpython3u
 AS $$
 for i in range(0, 10):
     plpy.execute("INSERT INTO test1 (a) VALUES (%d)" % i)
@@ -1465,7 +1290,7 @@ CREATE FUNCTION raise_custom_exception() RETURNS void AS $$
 plpy.error("custom exception message",
            detail="some info about exception",
            hint="hint for users")
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
 
 =# SELECT raise_custom_exception();
 ERROR:  plpy.Error: custom exception message
diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml
index b12796095fb..23d9029af9c 100644
--- a/doc/src/sgml/ref/comment.sgml
+++ b/doc/src/sgml/ref/comment.sgml
@@ -349,7 +349,7 @@ COMMENT ON TEXT SEARCH CONFIGURATION my_config IS 'Special word filtering';
 COMMENT ON TEXT SEARCH DICTIONARY swedish IS 'Snowball stemmer for Swedish language';
 COMMENT ON TEXT SEARCH PARSER my_parser IS 'Splits text into words';
 COMMENT ON TEXT SEARCH TEMPLATE snowball IS 'Snowball stemmer';
-COMMENT ON TRANSFORM FOR hstore LANGUAGE plpythonu IS 'Transform between hstore and Python dict';
+COMMENT ON TRANSFORM FOR hstore LANGUAGE plpython3u IS 'Transform between hstore and Python dict';
 COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for RI';
 COMMENT ON TYPE complex IS 'Complex number data type';
 COMMENT ON VIEW my_view IS 'View of departmental costs';
diff --git a/doc/src/sgml/ref/create_transform.sgml b/doc/src/sgml/ref/create_transform.sgml
index 3f81dc6bba2..34bdc60e130 100644
--- a/doc/src/sgml/ref/create_transform.sgml
+++ b/doc/src/sgml/ref/create_transform.sgml
@@ -156,11 +156,11 @@ CREATE [ OR REPLACE ] TRANSFORM FOR <replaceable>type_name</replaceable> LANGUAG
 
   <para>
    To create a transform for type <type>hstore</type> and language
-   <literal>plpythonu</literal>, first set up the type and the language:
+   <literal>plpython3u</literal>, first set up the type and the language:
 <programlisting>
 CREATE TYPE hstore ...;
 
-CREATE EXTENSION plpythonu;
+CREATE EXTENSION plpython3u;
 </programlisting>
    Then create the necessary functions:
 <programlisting>
@@ -174,7 +174,7 @@ AS ...;
 </programlisting>
    And finally create the transform to connect them all together:
 <programlisting>
-CREATE TRANSFORM FOR hstore LANGUAGE plpythonu (
+CREATE TRANSFORM FOR hstore LANGUAGE plpython3u (
     FROM SQL WITH FUNCTION hstore_to_plpython(internal),
     TO SQL WITH FUNCTION plpython_to_hstore(internal)
 );
diff --git a/doc/src/sgml/ref/drop_transform.sgml b/doc/src/sgml/ref/drop_transform.sgml
index d25cb51604d..544a9663d77 100644
--- a/doc/src/sgml/ref/drop_transform.sgml
+++ b/doc/src/sgml/ref/drop_transform.sgml
@@ -101,9 +101,9 @@ DROP TRANSFORM [ IF EXISTS ] FOR <replaceable>type_name</replaceable> LANGUAGE <
 
   <para>
    To drop the transform for type <type>hstore</type> and language
-   <literal>plpythonu</literal>:
+   <literal>plpython3u</literal>:
 <programlisting>
-DROP TRANSFORM FOR hstore LANGUAGE plpythonu;
+DROP TRANSFORM FOR hstore LANGUAGE plpython3u;
 </programlisting></para>
  </refsect1>
 
-- 
2.35.1.354.g715d08a9e5

