*/
 CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'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 ])
  */
 CREATE FUNCTION invalid_type_caught(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'if "plan" not in SD:
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
  */
 CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'if "plan" not in SD:
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
  */
 CREATE FUNCTION valid_type(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'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):
 
  */
 CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'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 ])
  */
 CREATE FUNCTION invalid_type_caught(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'if "plan" not in SD:
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
  */
 CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'if "plan" not in SD:
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
  */
 CREATE FUNCTION valid_type(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'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):
 
 --
 CREATE FUNCTION global_test_one() returns text
     AS
-'if not SD.has_key("global_test"):
+'if "global_test" not in SD:
        SD["global_test"] = "set by global_test_one"
-if not GD.has_key("global_test"):
+if "global_test" not in GD:
        GD["global_test"] = "set by global_test_one"
 return "SD: " + SD["global_test"] + ", GD: " + GD["global_test"]'
     LANGUAGE plpythonu;
 CREATE FUNCTION global_test_two() returns text
     AS
-'if not SD.has_key("global_test"):
+'if "global_test" not in SD:
        SD["global_test"] = "set by global_test_two"
-if not GD.has_key("global_test"):
+if "global_test" not in GD:
        GD["global_test"] = "set by global_test_two"
 return "SD: " + SD["global_test"] + ", GD: " + GD["global_test"]'
     LANGUAGE plpythonu;
 CREATE FUNCTION static_test() returns int4
     AS
-'if SD.has_key("call"):
+'if "call" in SD:
        SD["call"] = SD["call"] + 1
 else:
        SD["call"] = 1
 
   import cmath
   import errno
   import math
-  import md5
   import operator
   import random
   import re
-  import sha
   import string
   import time
 except Exception, ex:
     LANGUAGE plpythonu;
 CREATE FUNCTION import_test_one(p text) RETURNS text
        AS
-'import sha
-digest = sha.new(p)
+'try:
+    import hashlib
+    digest = hashlib.sha1(p.encode("ascii"))
+except ImportError:
+    import sha
+    digest = sha.new(p)
 return digest.hexdigest()'
        LANGUAGE plpythonu;
 CREATE FUNCTION import_test_two(u users) RETURNS text
        AS
-'import sha
-plain = u["fname"] + u["lname"]
-digest = sha.new(plain);
+'plain = u["fname"] + u["lname"]
+try:
+    import hashlib
+    digest = hashlib.sha1(plain.encode("ascii"))
+except ImportError:
+    import sha
+    digest = sha.new(plain);
 return "sha hash of " + plain + " is " + digest.hexdigest()'
        LANGUAGE plpythonu;
 -- import python modules
 
 $$ LANGUAGE plpythonu;
 CREATE FUNCTION test_setof_as_tuple(count integer, content text) RETURNS SETOF text AS $$
 t = ()
-for i in xrange(count):
+for i in range(count):
        t += ( content, )
 return t
 $$ LANGUAGE plpythonu;
 
 -- some spi stuff
 CREATE FUNCTION spi_prepared_plan_test_one(a text) RETURNS text
        AS
-'if not SD.has_key("myplan"):
+'if "myplan" not in SD:
        q = "SELECT count(*) FROM users WHERE lname = $1"
        SD["myplan"] = plpy.prepare(q, [ "text" ])
 try:
        LANGUAGE plpythonu;
 CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS text
        AS
-'if not SD.has_key("myplan"):
+'if "myplan" not in SD:
        q = "SELECT spi_prepared_plan_test_one(''%s'') as count" % a
        SD["myplan"] = plpy.prepare(q)
 try:
 
 -- test multiple arguments
 CREATE FUNCTION argument_test_one(u users, a1 text, a2 text) RETURNS text
        AS
-'keys = u.keys()
+'keys = list(u.keys())
 keys.sort()
 out = []
 for key in keys:
 
        (i int, v text );
 CREATE FUNCTION trigger_data() returns trigger language plpythonu as $$
 
-if TD.has_key('relid'):
+if 'relid' in TD:
        TD['relid'] = "bogus:12345"
 
-skeys = TD.keys()
+skeys = list(TD.keys())
 skeys.sort()
 for key in skeys:
        val = TD[key]
 
  */
 CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'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 ])
  */
 CREATE FUNCTION invalid_type_caught(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'if "plan" not in SD:
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
  */
 CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'if "plan" not in SD:
        q = "SELECT fname FROM users WHERE lname = $1"
        try:
                SD["plan"] = plpy.prepare(q, [ "test" ])
  */
 CREATE FUNCTION valid_type(a text) RETURNS text
        AS
-'if not SD.has_key("plan"):
+'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):
 
 
 CREATE FUNCTION global_test_one() returns text
     AS
-'if not SD.has_key("global_test"):
+'if "global_test" not in SD:
        SD["global_test"] = "set by global_test_one"
-if not GD.has_key("global_test"):
+if "global_test" not in GD:
        GD["global_test"] = "set by global_test_one"
 return "SD: " + SD["global_test"] + ", GD: " + GD["global_test"]'
     LANGUAGE plpythonu;
 
 CREATE FUNCTION global_test_two() returns text
     AS
-'if not SD.has_key("global_test"):
+'if "global_test" not in SD:
        SD["global_test"] = "set by global_test_two"
-if not GD.has_key("global_test"):
+if "global_test" not in GD:
        GD["global_test"] = "set by global_test_two"
 return "SD: " + SD["global_test"] + ", GD: " + GD["global_test"]'
     LANGUAGE plpythonu;
 
 CREATE FUNCTION static_test() returns int4
     AS
-'if SD.has_key("call"):
+'if "call" in SD:
        SD["call"] = SD["call"] + 1
 else:
        SD["call"] = 1
 
   import cmath
   import errno
   import math
-  import md5
   import operator
   import random
   import re
-  import sha
   import string
   import time
 except Exception, ex:
 
 CREATE FUNCTION import_test_one(p text) RETURNS text
        AS
-'import sha
-digest = sha.new(p)
+'try:
+    import hashlib
+    digest = hashlib.sha1(p.encode("ascii"))
+except ImportError:
+    import sha
+    digest = sha.new(p)
 return digest.hexdigest()'
        LANGUAGE plpythonu;
 
 CREATE FUNCTION import_test_two(u users) RETURNS text
        AS
-'import sha
-plain = u["fname"] + u["lname"]
-digest = sha.new(plain);
+'plain = u["fname"] + u["lname"]
+try:
+    import hashlib
+    digest = hashlib.sha1(plain.encode("ascii"))
+except ImportError:
+    import sha
+    digest = sha.new(plain);
 return "sha hash of " + plain + " is " + digest.hexdigest()'
        LANGUAGE plpythonu;
 
 
 
 CREATE FUNCTION test_setof_as_tuple(count integer, content text) RETURNS SETOF text AS $$
 t = ()
-for i in xrange(count):
+for i in range(count):
        t += ( content, )
 return t
 $$ LANGUAGE plpythonu;
 
 
 CREATE FUNCTION spi_prepared_plan_test_one(a text) RETURNS text
        AS
-'if not SD.has_key("myplan"):
+'if "myplan" not in SD:
        q = "SELECT count(*) FROM users WHERE lname = $1"
        SD["myplan"] = plpy.prepare(q, [ "text" ])
 try:
 
 CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS text
        AS
-'if not SD.has_key("myplan"):
+'if "myplan" not in SD:
        q = "SELECT spi_prepared_plan_test_one(''%s'') as count" % a
        SD["myplan"] = plpy.prepare(q)
 try:
 
 -- test multiple arguments
 CREATE FUNCTION argument_test_one(u users, a1 text, a2 text) RETURNS text
        AS
-'keys = u.keys()
+'keys = list(u.keys())
 keys.sort()
 out = []
 for key in keys:
 
 
 CREATE FUNCTION trigger_data() returns trigger language plpythonu as $$
 
-if TD.has_key('relid'):
+if 'relid' in TD:
        TD['relid'] = "bogus:12345"
 
-skeys = TD.keys()
+skeys = list(TD.keys())
 skeys.sort()
 for key in skeys:
        val = TD[key]