Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
       [not found] <cover.1607675470.git.sergeyb@tarantool.org>
@ 2020-12-11  8:42 ` sergeyb
  2020-12-13 17:58   ` Vladislav Shpilevoy
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x sergeyb
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 27+ messages in thread
From: sergeyb @ 2020-12-11  8:42 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

From: Sergey Bronnikov <sergeyb@tarantool.org>

- convert print statement to function. In a Python 3 'print' becomes a
function, see [1]. Patch makes 'print' in a regression tests compatible with
Python 3.
- according to PEP8, mixing using double quotes and quotes in a project looks
inconsistent. Patch makes using quotes with strings consistent.
- print multiline strings with multiple print()
- use "format()" instead of "%" everywhere

1. https://docs.python.org/3/whatsnew/3.0.html#print-is-a-function

Part of #5538
---
 test/app-tap/httpd.py                    |  42 ++---
 test/box-py/args.test.py                 |  14 +-
 test/box-py/bad_trigger.result           |   2 -
 test/box-py/bad_trigger.test.py          |  20 +--
 test/box-py/bootstrap.result             |   2 +-
 test/box-py/bootstrap.test.py            |  16 +-
 test/box-py/call.result                  |  12 +-
 test/box-py/call.test.py                 |  92 +++++-----
 test/box-py/iproto.result                |  10 +-
 test/box-py/iproto.test.py               | 218 +++++++++++------------
 test/box-py/print.result                 |   6 +-
 test/box-py/print.test.py                |  24 +--
 test/box-py/snapshot.result              |   4 +-
 test/box-py/snapshot.test.py             |  33 ++--
 test/long_run-py/finalizers.result       |   2 +-
 test/long_run-py/finalizers.test.py      |   8 +-
 test/replication-py/cluster.result       |   6 +-
 test/replication-py/cluster.test.py      | 217 +++++++++++-----------
 test/replication-py/conflict.test.py     |  54 +++---
 test/replication-py/init_storage.test.py |  52 +++---
 test/replication-py/multi.test.py        |  78 ++++----
 test/replication-py/swap.test.py         |  46 ++---
 test/xlog-py/big_lsn.test.py             |   4 +-
 test/xlog-py/dup_key.test.py             |  17 +-
 test/xlog-py/empty.test.py               |   4 +-
 test/xlog-py/lsn_gap.test.py             |  10 +-
 test/xlog-py/misc.test.py                |  33 ++--
 test/xlog-py/missing.test.py             |  10 +-
 28 files changed, 523 insertions(+), 513 deletions(-)

diff --git a/test/app-tap/httpd.py b/test/app-tap/httpd.py
index b4662bc1f..b57ef1e39 100755
--- a/test/app-tap/httpd.py
+++ b/test/app-tap/httpd.py
@@ -6,35 +6,35 @@ from gevent import spawn, sleep, socket
 
 def absent():
     code = "500 Server Error"
-    headers = [('Content-Type', 'application/json')]
+    headers = [("Content-Type", "application/json")]
     body = ["No such method"]
     return code, body, headers
 
 def hello():
     code = "200 OK"
     body = ["hello world"]
-    headers = [('Content-Type', 'application/json')]
+    headers = [("Content-Type", "application/json")]
     return code, body, headers
 
 def hello1():
     code = "200 OK"
     body = [b"abc"]
-    headers = [('Content-Type', 'application/json')]
+    headers = [("Content-Type", "application/json")]
     return code, body, headers
 
 def headers():
     code = "200 OK"
     body = [b"cookies"]
-    headers = [('Content-Type', 'application/json'),
-               ('Content-Type', 'application/yaml'),
-               ('Set-Cookie', 'likes=cheese; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly'),
-               ('Set-Cookie', 'bad@name=no;'),
-               ('Set-Cookie', 'badcookie'),
-               ('Set-Cookie', 'good_name=yes;'),
-               ('Set-Cookie', 'age = 17; NOSuchOption; EmptyOption=Value;Secure'),
-               ('my_header', 'value1'),
-               ('my_header', 'value2'),
-               ('very_very_very_long_headers_name1', 'true'),
+    headers = [("Content-Type", "application/json"),
+               ("Content-Type", "application/yaml"),
+               ("Set-Cookie", "likes=cheese; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly"),
+               ("Set-Cookie", "bad@name=no;"),
+               ("Set-Cookie", "badcookie"),
+               ("Set-Cookie", "good_name=yes;"),
+               ("Set-Cookie", "age = 17; NOSuchOption; EmptyOption=Value;Secure"),
+               ("my_header", "value1"),
+               ("my_header", "value2"),
+               ("very_very_very_long_headers_name1", "true"),
                ]
     return code, body, headers
 
@@ -42,13 +42,13 @@ def long_query():
     sleep(0.005)
     code = "200 OK"
     body = [b"abc"]
-    headers = [('Content-Type', 'application/json')]
+    headers = [("Content-Type", "application/json")]
     return code, body, headers
 
 def redirect():
     code = "302 Found"
     body = ["redirecting"]
-    headers = [('Location', '/')]
+    headers = [("Location", "/")]
     return code, body, headers
 
 paths = {
@@ -63,7 +63,7 @@ paths = {
 def read_handle(env, response):
     code = "404 Not Found"
     headers = []
-    body = ['Not Found']
+    body = ["Not Found"]
     if env["PATH_INFO"] in paths:
         code, body, headers = paths[env["PATH_INFO"]]()
     for key,value in env.iteritems():
@@ -74,7 +74,7 @@ def read_handle(env, response):
 
 def post_handle(env, response):
     code = "200 OK"
-    body = [env['wsgi.input'].read()]
+    body = [env["wsgi.input"].read()]
     headers = []
     for key,value in env.iteritems():
         if "HTTP_" in key:
@@ -83,7 +83,7 @@ def post_handle(env, response):
     return body
 
 def other_handle(env, response, method, code):
-    headers = [('Content-Type', 'text/plain'), ("method", method)]
+    headers = [("Content-Type", "text/plain"), ("method", method)]
     body = [method]
     for key,value in env.iteritems():
         if "HTTP_" in key:
@@ -119,15 +119,15 @@ def heartbeat():
         sys.exit(1)
 
 def usage():
-    sys.stderr.write("Usage: %s { --inet HOST:PORT | --unix PATH }\n" %
-                     sys.argv[0])
+    message = "Usage: {} {{ --inet HOST:PORT | --unix PATH }}\n".format(sys.argv[0])
+    sys.stderr.write(message)
     sys.exit(1)
 
 if len(sys.argv) != 3:
     usage()
 
 if sys.argv[1] == "--inet":
-    host, port = sys.argv[2].split(':')
+    host, port = sys.argv[2].split(":")
     sock_family = socket.AF_INET
     sock_addr = (host, int(port))
 elif sys.argv[1] == "--unix":
diff --git a/test/box-py/args.test.py b/test/box-py/args.test.py
index c0fac9038..f1b840a85 100644
--- a/test/box-py/args.test.py
+++ b/test/box-py/args.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import sys
 import os
 import re
@@ -5,7 +7,7 @@ import re
 # Disabled on OpenBSD due to fail #XXXX.
 import platform
 
-if platform.system() == 'OpenBSD':
+if platform.system() == "OpenBSD":
     self.skip = 1
 
 # mask BFD warnings: https://bugs.launchpad.net/tarantool/+bug/1018356
@@ -13,9 +15,9 @@ sys.stdout.push_filter("unable to read unknown load command 0x2\d+", "")
 server.test_option("--help")
 server.test_option("-h")
 # Replace with the same value for case when builddir inside source dir
-sys.stdout.push_filter(re.escape(os.getenv("BUILDDIR")+'/src/tarantool'), "tarantool")
+sys.stdout.push_filter(re.escape(os.getenv("BUILDDIR")+"/src/tarantool"), "tarantool")
 sys.stdout.push_filter(re.escape(os.getenv("BUILDDIR")), "${SOURCEDIR}")
-sys.stdout.push_filter(re.escape(os.getenv("SOURCEDIR")+'/src/tarantool'), "tarantool")
+sys.stdout.push_filter(re.escape(os.getenv("SOURCEDIR")+"/src/tarantool"), "tarantool")
 sys.stdout.push_filter(re.escape(os.getenv("SOURCEDIR")), "${SOURCEDIR}")
 sys.stdout.push_filter("invalid option.*", "invalid option")
 sys.stdout.push_filter("unrecognized option.*", "unrecognized option")
@@ -44,11 +46,11 @@ server.test_option(script + " --help 1 2 3")
 server.test_option("-V " + script + " 1 2 3")
 
 # gh-3966: os.exit() hangs if called by a command from the argument list.
-server.test_option("-e \"print(1) os.exit() print(2)\"")
-server.test_option("-e \"print(1)\" -e \"os.exit()\" -e \"print(1)\" -e \"os.exit()\" -e \"print(1)\"")
+server.test_option("-e 'print(1) os.exit() print(2)'")
+server.test_option("-e 'print(1)' -e 'os.exit()' -e 'print(1)' -e 'os.exit()' -e 'print(1)'")
 
 server.test_option("-e \"print('Hello')\" " + script + " 1 2 3")
-server.test_option("-e \"a = 10\" " + \
+server.test_option("-e 'a = 10' " + \
                    "-e print(a) " + \
                    script + \
                    " 1 2 3 --help")
diff --git a/test/box-py/bad_trigger.result b/test/box-py/bad_trigger.result
index 5d064b764..42cd9a7e8 100644
--- a/test/box-py/bad_trigger.result
+++ b/test/box-py/bad_trigger.result
@@ -1,8 +1,6 @@
-
  #
  # if on_connect() trigger raises an exception, the connection is dropped
  #
- 
 nosuchfunction = nil
 ---
 ...
diff --git a/test/box-py/bad_trigger.test.py b/test/box-py/bad_trigger.test.py
index 7d200b921..789fe8045 100644
--- a/test/box-py/bad_trigger.test.py
+++ b/test/box-py/bad_trigger.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 from lib.box_connection import BoxConnection
 from lib.tarantool_connection import TarantoolConnection
 from tarantool import NetworkError
@@ -6,11 +8,9 @@ from tarantool.const import IPROTO_GREETING_SIZE, IPROTO_CODE, IPROTO_ERROR, \
 import socket
 import msgpack
 
-print """
- #
- # if on_connect() trigger raises an exception, the connection is dropped
- #
- """
+print(" #")
+print(" # if on_connect() trigger raises an exception, the connection is dropped")
+print(" #")
 
 # silence possible error of strict mode
 server.admin("nosuchfunction = nil")
@@ -24,12 +24,12 @@ conn.connect()
 s = conn.socket
 
 # Read greeting
-print 'greeting: ', len(s.recv(IPROTO_GREETING_SIZE)) == IPROTO_GREETING_SIZE
+print("greeting:  {}".format(len(s.recv(IPROTO_GREETING_SIZE)) == IPROTO_GREETING_SIZE))
 
 # Read error packet
 IPROTO_FIXHEADER_SIZE = 5
 fixheader = s.recv(IPROTO_FIXHEADER_SIZE)
-print 'fixheader: ', len(fixheader) == IPROTO_FIXHEADER_SIZE
+print("fixheader:  {}".format(len(fixheader) == IPROTO_FIXHEADER_SIZE))
 unpacker.feed(fixheader)
 packet_len = unpacker.unpack()
 packet = s.recv(packet_len)
@@ -38,9 +38,9 @@ unpacker.feed(packet)
 # Parse packet
 header = unpacker.unpack()
 body = unpacker.unpack()
-print 'error code', (header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))
-print 'error message: ', body[IPROTO_ERROR]
-print 'eof:', len(s.recv(1024)) == 0
+print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
+print("error message:  {}".format(body[IPROTO_ERROR]))
+print("eof: {}".format(len(s.recv(1024)) == 0))
 s.close()
 
 server.admin("box.session.on_connect(nil, f1)")
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index 0876e77a6..865302698 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -165,7 +165,7 @@ box.space._user:select{}
   - [3, 1, 'replication', 'role', {}]
   - [31, 1, 'super', 'role', {}]
 ...
-for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end
+for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end
 ---
 - - [1, 1, 'box.schema.user.info', 1, 'LUA', '', 'function', [], 'any', 'none', 'none',
     false, false, true, ['LUA'], {}, '', '', '']
diff --git a/test/box-py/bootstrap.test.py b/test/box-py/bootstrap.test.py
index 63c13e8a4..f7c846bf1 100644
--- a/test/box-py/bootstrap.test.py
+++ b/test/box-py/bootstrap.test.py
@@ -1,11 +1,11 @@
-server.admin('box.internal.bootstrap()')
-server.admin('box.space._schema:select{}')
-server.admin('box.space._cluster:select{}')
-server.admin('box.space._space:select{}')
-server.admin('box.space._index:select{}')
-server.admin('box.space._user:select{}')
-server.admin('for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end')
-server.admin('box.space._priv:select{}')
+server.admin("box.internal.bootstrap()")
+server.admin("box.space._schema:select{}")
+server.admin("box.space._cluster:select{}")
+server.admin("box.space._space:select{}")
+server.admin("box.space._index:select{}")
+server.admin("box.space._user:select{}")
+server.admin("for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end")
+server.admin("box.space._priv:select{}")
 
 # Cleanup
 server.stop()
diff --git a/test/box-py/call.result b/test/box-py/call.result
index d340ed6fa..e6b7b8dc9 100644
--- a/test/box-py/call.result
+++ b/test/box-py/call.result
@@ -536,10 +536,10 @@ function f(...) return ... end
 call f({'k2': 'v2', 'k1': 'v1'})
 ---
 - {'k2': 'v2', 'k1': 'v1'}
-eval (return space:auto_increment({"transaction"}))()
+eval (return space:auto_increment({'transaction'}))()
 ---
 - [1, 'transaction']
-function f(...) return space:auto_increment({"transaction"}) end
+function f(...) return space:auto_increment({'transaction'}) end
 ---
 ...
 call f()
@@ -554,11 +554,11 @@ function f(...) return space:select{} end
 call f()
 ---
 - [[1, 'transaction'], [2, 'transaction']]
-eval (return box.begin(), space:auto_increment({"failed"}), box.rollback())()
+eval (return box.begin(), space:auto_increment({'failed'}), box.rollback())()
 ---
 - None
 - [3, 'failed']
-function f(...) return box.begin(), space:auto_increment({"failed"}), box.rollback() end
+function f(...) return box.begin(), space:auto_increment({'failed'}), box.rollback() end
 ---
 ...
 call f()
@@ -574,10 +574,10 @@ function f(...) return space:select{} end
 call f()
 ---
 - [[1, 'transaction'], [2, 'transaction']]
-eval (return require("fiber").sleep(0))()
+eval (return require('fiber').sleep(0))()
 ---
 
-function f(...) return require("fiber").sleep(0) end
+function f(...) return require('fiber').sleep(0) end
 ---
 ...
 call f()
diff --git a/test/box-py/call.test.py b/test/box-py/call.test.py
index 974ba0cac..75ced1dff 100644
--- a/test/box-py/call.test.py
+++ b/test/box-py/call.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import sys
 
@@ -6,9 +8,9 @@ def call(name, *args):
 
 admin("box.schema.user.create('test', { password = 'test' })")
 admin("box.schema.user.grant('test', 'execute,read,write', 'universe')")
-iproto.authenticate('test', 'test')
+iproto.authenticate("test", "test")
 # workaround for gh-770 centos 6 float representation
-admin('exp_notation = 1e123')
+admin("exp_notation = 1e123")
 admin("function f1() return 'testing', 1, false, -1, 1.123, math.abs(exp_notation - 1e123) < 0.1, nil end")
 admin("f1()")
 call("f1")
@@ -19,13 +21,13 @@ call("f1")
 
 # A test case for https://github.com/tarantool/tarantool/issues/44
 # IPROTO required!
-call("box.error", 33333, 'Hey!')
+call("box.error", 33333, "Hey!")
 
-print """
-# A test case for Bug#103491
-# server CALL processing bug with name path longer than two
-# https://bugs.launchpad.net/tarantool/+bug/1034912
-"""
+print("")
+print("# A test case for Bug#103491")
+print("# server CALL processing bug with name path longer than two")
+print("# https://bugs.launchpad.net/tarantool/+bug/1034912")
+print("")
 admin("f = function() return 'OK' end")
 admin("test = {}")
 admin("test.f = f")
@@ -35,11 +37,11 @@ call("f")
 call("test.f")
 call("test.test.f")
 
-print """
-# Test for Bug #955226
-# Lua Numbers are passed back wrongly as strings
-#
-"""
+print("")
+print("# Test for Bug #955226")
+print("# Lua Numbers are passed back wrongly as strings")
+print("#")
+print("")
 admin("function foo() return 1, 2, '1', '2' end")
 call("foo")
 
@@ -48,8 +50,8 @@ call("foo")
 #
 admin("function f1(...) return {...} end")
 admin("function f2(...) return f1({...}) end")
-call("f1", 'test_', 'test_')
-call("f2", 'test_', 'test_')
+call("f1", "test_", "test_")
+call("f2", "test_", "test_")
 call("f1")
 call("f2")
 #
@@ -72,8 +74,8 @@ call("f3")
 admin("function f3() return { { test={1,2,3} }, { test2={1,2,3} } } end")
 call("f3")
 
-call("f1", 'jason')
-call("f1", 'jason', 1, 'test', 2, 'stewart')
+call("f1", "jason")
+call("f1", "jason", 1, "test", 2, "stewart")
 
 admin("space = box.schema.space.create('tweedledum')")
 admin("index = space:create_index('primary', { type = 'hash' })")
@@ -81,30 +83,30 @@ admin("index = space:create_index('primary', { type = 'hash' })")
 admin("function myreplace(...) return space:replace{...} end")
 admin("function myinsert(...) return space:insert{...} end")
 
-call("myinsert", 1, 'test box delete')
+call("myinsert", 1, "test box delete")
 call("space:delete", 1)
-call("myinsert", 1, 'test box delete')
+call("myinsert", 1, "test box delete")
 call("space:delete", 1)
 call("space:delete", 1)
-call("myinsert", 2, 'test box delete')
+call("myinsert", 2, "test box delete")
 call("space:delete", 1)
 call("space:delete", 2)
 call("space:delete", 2)
 admin("space:delete{2}")
 
-call("myinsert", 2, 'test box delete')
+call("myinsert", 2, "test box delete")
 call("space:get", 2)
 admin("space:delete{2}")
 call("space:get", 2)
-call("myinsert", 2, 'test box.select()')
+call("myinsert", 2, "test box.select()")
 call("space:get", 2)
 call("space:select", 2)
 admin("space:get{2}")
 admin("space:select{2}")
 admin("space:get{1}")
 admin("space:select{1}")
-call("myreplace", 2, 'hello', 'world')
-call("myreplace", 2, 'goodbye', 'universe')
+call("myreplace", 2, "hello", "world")
+call("myreplace", 2, "goodbye", "universe")
 call("space:get", 2)
 call("space:select", 2)
 admin("space:get{2}")
@@ -114,9 +116,9 @@ call("space:get", 2)
 call("space:select", 2)
 call("space:delete", 2)
 call("space:delete", 2)
-call("myinsert", 3, 'old', 2)
+call("myinsert", 3, "old", 2)
 # test that insert produces a duplicate key error
-call("myinsert", 3, 'old', 2)
+call("myinsert", 3, "old", 2)
 admin("space:update({3}, {{'=', 1, 4}, {'=', 2, 'new'}})")
 admin("space:insert(space:get{3}:update{{'=', 1, 4}, {'=', 2, 'new'}}) space:delete{3}")
 call("space:get", 4)
@@ -136,19 +138,19 @@ admin("index = space:create_index('primary', { type = 'tree' })")
 
 
 def lua_eval(name, *args):
-    print 'eval (%s)(%s)' % (name, ','.join([ str(arg) for arg in args]))
-    print '---'
-    print iproto.py_con.eval(name, args)
+    print("eval ({})({})".format(name, ",".join([ str(arg) for arg in args])))
+    print("---")
+    print(iproto.py_con.eval(name, args))
 
 def lua_call(name, *args):
-    print 'call %s(%s)' % (name, ','.join([ str(arg) for arg in args]))
-    print '---'
-    print iproto.py_con.call(name, args)
+    print("call {}({})".format(name, ",".join([ str(arg) for arg in args])))
+    print("---")
+    print(iproto.py_con.call(name, args))
 
 def test(expr, *args):
-    lua_eval('return ' + expr, *args)
-    admin('function f(...) return ' + expr + ' end')
-    lua_call('f', *args)
+    lua_eval("return " + expr, *args)
+    admin("function f(...) return " + expr + " end")
+    lua_call("f", *args)
 
 # Return values
 test("1")
@@ -172,18 +174,18 @@ test("{t}")
 test("{t, t, t}")
 test("error('exception')")
 test("box.error(0)")
-test('...')
-test('...', 1, 2, 3)
-test('...',  None, None, None)
-test('...', { 'k1': 'v1', 'k2': 'v2'})
+test("...")
+test("...", 1, 2, 3)
+test("...",  None, None, None)
+test("...", { "k1": "v1", "k2": "v2"})
 # Transactions
-test('space:auto_increment({"transaction"})')
-test('space:select{}')
-test('box.begin(), space:auto_increment({"failed"}), box.rollback()')
-test('space:select{}')
-test('require("fiber").sleep(0)')
+test("space:auto_increment({'transaction'})")
+test("space:select{}")
+test("box.begin(), space:auto_increment({'failed'}), box.rollback()")
+test("space:select{}")
+test("require('fiber').sleep(0)")
 # Other
-lua_eval('!invalid expression')
+lua_eval("!invalid expression")
 
 admin("space:drop()")
 admin("box.schema.user.drop('test')")
diff --git a/test/box-py/iproto.result b/test/box-py/iproto.result
index 04e2e220c..0f2766871 100644
--- a/test/box-py/iproto.result
+++ b/test/box-py/iproto.result
@@ -1,21 +1,15 @@
 box.schema.user.grant('guest', 'read,write,execute', 'universe')
 ---
 ...
-
 #
 # iproto packages test
 #
-
-
 # Test bug #899343 (server assertion failure on incorrect packet)
-
 # send the package with invalid length
 12
 # check that is server alive
 True
-
-#  Test gh-206 "Segfault if sending IPROTO package without `KEY` field"
-
+#  Test gh-206 'Segfault if sending IPROTO package without `KEY` field'
 IPROTO_SELECT
 query {'IPROTO_CODE': 1} {'IPROTO_SPACE_ID': 280}
 True
@@ -165,10 +159,8 @@ space:drop()
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
 ...
-
 # Test bugs gh-272, gh-1654 if the packet was incorrect, respond with
 # an error code and do not close connection
-
 sync=0, Invalid MsgPack - packet header
 sync=1234, Missing mandatory field 'space id' in request
 sync=5678, Read access to space '_user' is denied for user 'guest'
diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
index cdd1a71c5..5eccd40d3 100644
--- a/test/box-py/iproto.test.py
+++ b/test/box-py/iproto.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import sys
 import struct
@@ -11,46 +13,42 @@ from lib.tarantool_connection import TarantoolConnection
 
 admin("box.schema.user.grant('guest', 'read,write,execute', 'universe')")
 
-print """
-#
-# iproto packages test
-#
-"""
+print("#")
+print("# iproto packages test")
+print("#")
 
-# opeing new connection to tarantool/box
+# opening new connection to tarantool/box
 conn = TarantoolConnection(server.iproto.host, server.iproto.port)
 conn.connect()
 s = conn.socket
 
-print """
-# Test bug #899343 (server assertion failure on incorrect packet)
-"""
-print "# send the package with invalid length"
-invalid_request = struct.pack('<LLL', 1, 4294967290, 1)
-print s.send(invalid_request)
-print "# check that is server alive"
-print iproto.py_con.ping() > 0
+print("# Test bug #899343 (server assertion failure on incorrect packet)")
+print("# send the package with invalid length")
+invalid_request = struct.pack("<LLL", 1, 4294967290, 1)
+print(s.send(invalid_request))
+print("# check that is server alive")
+print(iproto.py_con.ping() > 0)
 
 # closing connection
 s.close()
 
 key_names = {}
-for (k,v) in globals().items():
-    if type(k) == str and k.startswith('IPROTO_') and type(v) == int:
+for (k,v) in list(globals().items()):
+    if type(k) == str and k.startswith("IPROTO_") and type(v) == int:
         key_names[v] = k
 
 def repr_dict(todump):
     d = {}
-    for (k, v) in todump.items():
+    for (k, v) in list(todump.items()):
         k_name = key_names.get(k, k)
         d[k_name] = v
     return repr(d)
 
 def test(header, body):
     # Connect and authenticate
-    c = Connection('localhost', server.iproto.port)
+    c = Connection("localhost", server.iproto.port)
     c.connect()
-    print 'query', repr_dict(header), repr_dict(body)
+    print("query", repr_dict(header), repr_dict(body))
     header = msgpack.dumps(header)
     body = msgpack.dumps(body)
     query = msgpack.dumps(len(header) + len(body)) + header + body
@@ -59,36 +57,34 @@ def test(header, body):
     try:
         s.send(query)
     except OSError as e:
-        print '   => ', 'Failed to send request'
+        print("   => ", "Failed to send request")
     c.close()
-    print iproto.py_con.ping() > 0
+    print(iproto.py_con.ping() > 0)
 
-print """
-#  Test gh-206 "Segfault if sending IPROTO package without `KEY` field"
-"""
+print("#  Test gh-206 'Segfault if sending IPROTO package without `KEY` field'")
 
-print "IPROTO_SELECT"
+print("IPROTO_SELECT")
 test({ IPROTO_CODE : REQUEST_TYPE_SELECT }, { IPROTO_SPACE_ID: 280 })
-print "\n"
+print("\n")
 
-print "IPROTO_DELETE"
+print("IPROTO_DELETE")
 test({ IPROTO_CODE : REQUEST_TYPE_DELETE }, { IPROTO_SPACE_ID: 280 })
-print "\n"
+print("\n")
 
-print "IPROTO_UPDATE"
+print("IPROTO_UPDATE")
 test({ IPROTO_CODE : REQUEST_TYPE_UPDATE }, { IPROTO_SPACE_ID: 280 })
 test({ IPROTO_CODE : REQUEST_TYPE_UPDATE },
      { IPROTO_SPACE_ID: 280, IPROTO_KEY: (1, )})
-print "\n"
+print("\n")
 
-print "IPROTO_REPLACE"
+print("IPROTO_REPLACE")
 test({ IPROTO_CODE : REQUEST_TYPE_REPLACE }, { IPROTO_SPACE_ID: 280 })
-print "\n"
+print("\n")
 
-print "IPROTO_CALL"
+print("IPROTO_CALL")
 test({ IPROTO_CODE : REQUEST_TYPE_CALL }, {})
-test({ IPROTO_CODE : REQUEST_TYPE_CALL }, { IPROTO_KEY: ('procname', )})
-print "\n"
+test({ IPROTO_CODE : REQUEST_TYPE_CALL }, { IPROTO_KEY: ("procname", )})
+print("\n")
 
 # gh-434 Tarantool crashes on multiple iproto requests with WAL enabled
 admin("box.cfg.wal_mode")
@@ -96,7 +92,7 @@ admin("space = box.schema.space.create('test', { id = 567 })")
 admin("index = space:create_index('primary', { type = 'hash' })")
 admin("box.schema.user.grant('guest', 'read,write,execute', 'space', 'test')")
 
-c = Connection('localhost', server.iproto.port)
+c = Connection("localhost", server.iproto.port)
 c.connect()
 request1 = RequestInsert(c, 567, [1, "baobab"])
 request2 = RequestInsert(c, 567, [2, "obbaba"])
@@ -104,11 +100,11 @@ s = c._socket
 try:
     s.send(bytes(request1) + bytes(request2))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response1 = Response(c, c._read_response())
 response2 = Response(c, c._read_response())
-print response1.__str__()
-print response2.__str__()
+print(response1.__str__())
+print(response2.__str__())
 
 request1 = RequestInsert(c, 567, [3, "occama"])
 request2 = RequestSelect(c, 567, 0, [1], 0, 1, 0)
@@ -116,11 +112,11 @@ s = c._socket
 try:
     s.send(bytes(request1) + bytes(request2))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response1 = Response(c, c._read_response())
 response2 = Response(c, c._read_response())
-print response1.__str__()
-print response2.__str__()
+print(response1.__str__())
+print(response2.__str__())
 
 request1 = RequestSelect(c, 567, 0, [2], 0, 1, 0)
 request2 = RequestInsert(c, 567, [4, "ockham"])
@@ -128,11 +124,11 @@ s = c._socket
 try:
     s.send(bytes(request1) + bytes(request2))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response1 = Response(c, c._read_response())
 response2 = Response(c, c._read_response())
-print response1.__str__()
-print response2.__str__()
+print(response1.__str__())
+print(response2.__str__())
 
 request1 = RequestSelect(c, 567, 0, [1], 0, 1, 0)
 request2 = RequestSelect(c, 567, 0, [2], 0, 1, 0)
@@ -140,11 +136,11 @@ s = c._socket
 try:
     s.send(bytes(request1) + bytes(request2))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response1 = Response(c, c._read_response())
 response2 = Response(c, c._read_response())
-print response1.__str__()
-print response2.__str__()
+print(response1.__str__())
+print(response2.__str__())
 
 c.close()
 
@@ -176,7 +172,7 @@ class RawSelect(Request):
         self._body = request_body
 
 c = iproto.py_con
-space = c.space('test')
+space = c.space("test")
 space_id = space.space_no
 
 TESTS = [
@@ -192,34 +188,34 @@ TESTS = [
 for test in TESTS:
     it = iter(test)
     size = next(it)
-    print 'STR', size
-    print '--'
+    print("STR", size)
+    print("--")
     for fmt in it:
-        print '0x' + fmt.encode('hex'), '=>',
-        field = '*' * size
+        print("0x" + fmt.encode("hex"), "=>", end=" ")
+        field = "*" * size
         c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
         tuple = space.select(field)[0]
-        print len(tuple[0])== size and 'ok' or 'fail',
+        print(len(tuple[0])== size and "ok" or "fail", end=" ")
         it2 = iter(test)
         next(it2)
         for fmt2 in it2:
             tuple = c._send_request(RawSelect(c, space_id,
                 "\x91" + fmt2 + field))[0]
-            print len(tuple[0]) == size and 'ok' or 'fail',
+            print(len(tuple[0]) == size and "ok" or "fail", end=" ")
         tuple = space.delete(field)[0]
-        print len(tuple[0]) == size and 'ok' or 'fail',
-        print
-    print
+        print(len(tuple[0]) == size and "ok" or "fail", end="")
+        print()
+    print()
 
 
-print 'Test of schema_id in iproto.'
-c = Connection('localhost', server.iproto.port)
+print("Test of schema_id in iproto.")
+c = Connection("localhost", server.iproto.port)
 c.connect()
 s = c._socket
 
 def receive_response():
-    resp_len = ''
-    resp_headerbody = ''
+    resp_len = ""
+    resp_headerbody = ""
     resp_header = {}
     resp_body = {}
     try:
@@ -235,10 +231,10 @@ def receive_response():
         resp_header = unpacker.unpack()
         resp_body = unpacker.unpack()
     except OSError as e:
-        print '   => ', 'Failed to recv response'
+        print("   => ", "Failed to recv response")
     res = {}
-    res['header'] = resp_header
-    res['body'] = resp_body
+    res["header"] = resp_header
+    res["body"] = resp_body
     return res
 
 def test_request(req_header, req_body):
@@ -249,7 +245,7 @@ def test_request(req_header, req_body):
     try:
         s.send(query)
     except OSError as e:
-        print '   => ', 'Failed to send request'
+        print("   => ", "Failed to send request")
     return receive_response()
 
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT}
@@ -260,62 +256,62 @@ body = { IPROTO_SPACE_ID: space_id,
     IPROTO_OFFSET: 0,
     IPROTO_LIMIT: 1 }
 resp = test_request(header, body)
-print 'Normal connect done w/o errors:', resp['header'][0] == 0
-print 'Got schema_id:', resp['header'][5] > 0
-schema_id = resp['header'][5]
+print("Normal connect done w/o errors:", resp["header"][0] == 0)
+print("Got schema_id:", resp["header"][5] > 0)
+schema_id = resp["header"][5]
 
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT, 5 : 0 }
 resp = test_request(header, body)
-print 'Zero-schema_id connect done w/o errors:', resp['header'][0] == 0
-print 'Same schema_id:', resp['header'][5] == schema_id
+print("Zero-schema_id connect done w/o errors:", resp["header"][0] == 0)
+print("Same schema_id:", resp["header"][5] == schema_id)
 
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT, 5 : schema_id }
 resp = test_request(header, body)
-print 'Normal connect done w/o errors:', resp['header'][0] == 0
-print 'Same schema_id:', resp['header'][5] == schema_id
+print("Normal connect done w/o errors:", resp["header"][0] == 0)
+print("Same schema_id:", resp["header"][5] == schema_id)
 
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT, 5 : schema_id + 1 }
 resp = test_request(header, body)
-print 'Wrong schema_id leads to error:', resp['header'][0] != 0
-print 'Same schema_id:', resp['header'][5] == schema_id
+print("Wrong schema_id leads to error:", resp["header"][0] != 0)
+print("Same schema_id:", resp["header"][5] == schema_id)
 
 admin("space2 = box.schema.create_space('test2')")
 
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT, 5 : schema_id }
 resp = test_request(header, body)
-print 'Schema changed -> error:', resp['header'][0] != 0
-print 'Got another schema_id:', resp['header'][5] != schema_id
+print("Schema changed -> error:", resp["header"][0] != 0)
+print("Got another schema_id:", resp["header"][5] != schema_id)
 
 #
 # gh-2334 Lost SYNC in JOIN response.
 #
-uuid = '0d5bd431-7f3e-4695-a5c2-82de0a9cbc95'
+uuid = "0d5bd431-7f3e-4695-a5c2-82de0a9cbc95"
 header = { IPROTO_CODE: REQUEST_TYPE_JOIN, IPROTO_SYNC: 2334 }
 body = { IPROTO_SERVER_UUID: uuid }
 resp = test_request(header, body)
-if resp['header'][IPROTO_SYNC] == 2334:
+if resp["header"][IPROTO_SYNC] == 2334:
     i = 1
     while i < 3:
         resp = receive_response()
-        if resp['header'][IPROTO_SYNC] != 2334:
-            print 'Bad sync on response with number ', i
+        if resp["header"][IPROTO_SYNC] != 2334:
+            print("Bad sync on response with number ", i)
             break
-        if resp['header'][IPROTO_CODE] == REQUEST_TYPE_OK:
+        if resp["header"][IPROTO_CODE] == REQUEST_TYPE_OK:
             i += 1
     else:
-        print 'Sync ok'
+        print("Sync ok")
 else:
-    print 'Bad first sync'
+    print("Bad first sync")
 
 #
 # Try incorrect JOIN. SYNC must be also returned.
 #
-body[IPROTO_SERVER_UUID] = 'unknown'
+body[IPROTO_SERVER_UUID] = "unknown"
 resp = test_request(header, body)
-if resp['header'][IPROTO_SYNC] == 2334:
-    print('Sync on error is ok')
+if resp["header"][IPROTO_SYNC] == 2334:
+    print("Sync on error is ok")
 else:
-    print('Sync on error is not ok')
+    print("Sync on error is not ok")
 
 c.close()
 
@@ -332,8 +328,8 @@ admin("space:insert({1})")
 admin("space:insert({2, 'Music'})")
 admin("space:insert({3, 'Length', 93})")
 
-iproto.py_con.space('gh1280').select([])
-iproto.py_con.space('gh1280').select(list())
+iproto.py_con.space("gh1280").select([])
+iproto.py_con.space("gh1280").select(list())
 
 
 admin("space:drop()")
@@ -344,26 +340,24 @@ admin("box.schema.user.revoke('guest', 'read,write,execute', 'universe')")
 # gh-272 if the packet was incorrect, respond with an error code
 # gh-1654 do not close connnection on invalid request
 #
-print """
-# Test bugs gh-272, gh-1654 if the packet was incorrect, respond with
-# an error code and do not close connection
-"""
+print("# Test bugs gh-272, gh-1654 if the packet was incorrect, respond with")
+print("# an error code and do not close connection")
 
-c = Connection('localhost', server.iproto.port)
+c = Connection("localhost", server.iproto.port)
 c.connect()
 s = c._socket
 header = { "hello": "world"}
 body = { "bug": 272 }
 resp = test_request(header, body)
-print 'sync=%d, %s' % (resp['header'][IPROTO_SYNC], resp['body'].get(IPROTO_ERROR))
+print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT }
 header[IPROTO_SYNC] = 1234
 resp = test_request(header, body)
-print 'sync=%d, %s' % (resp['header'][IPROTO_SYNC], resp['body'].get(IPROTO_ERROR))
+print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
 header[IPROTO_SYNC] = 5678
 body = { IPROTO_SPACE_ID: 304, IPROTO_KEY: [], IPROTO_LIMIT: 1 }
 resp = test_request(header, body)
-print 'sync=%d, %s' % (resp['header'][IPROTO_SYNC], resp['body'].get(IPROTO_ERROR))
+print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
 c.close()
 
 
@@ -371,7 +365,7 @@ admin("space = box.schema.space.create('test_index_base', { id = 568 })")
 admin("index = space:create_index('primary', { type = 'hash' })")
 admin("box.schema.user.grant('guest', 'read,write,execute', 'space', 'test_index_base')")
 
-c = Connection('localhost', server.iproto.port)
+c = Connection("localhost", server.iproto.port)
 c.connect()
 s = c._socket
 
@@ -379,32 +373,32 @@ request = RequestInsert(c, 568, [1, 0, 0, 0])
 try:
     s.send(bytes(request))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response = Response(c, c._read_response())
-print response.__str__()
+print(response.__str__())
 
-request = RequestUpdate(c, 568, 0, [1], [['+', 2, 1], ['-', 3, 1]])
+request = RequestUpdate(c, 568, 0, [1], [["+", 2, 1], ["-", 3, 1]])
 try:
     s.send(bytes(request))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response = Response(c, c._read_response())
-print response.__str__()
+print(response.__str__())
 
-request = RequestUpsert(c, 568, 0, [1, 0, 0, 0], [['+', 2, 1], ['-', 3, 1]])
+request = RequestUpsert(c, 568, 0, [1, 0, 0, 0], [["+", 2, 1], ["-", 3, 1]])
 try:
     s.send(bytes(request))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response = Response(c, c._read_response())
 
 request = RequestSelect(c, 568, 0, [1], 0, 1, 0)
 try:
     s.send(bytes(request))
 except OSError as e:
-    print '   => ', 'Failed to send request'
+    print("   => ", "Failed to send request")
 response = Response(c, c._read_response())
-print response.__str__()
+print(response.__str__())
 
 c.close()
 
@@ -414,15 +408,15 @@ c.close()
 admin("function kek() return 'kek' end")
 admin("box.schema.user.grant('guest', 'read,write,execute', 'universe')")
 
-c = Connection('localhost', server.iproto.port)
+c = Connection("localhost", server.iproto.port)
 c.connect()
 s = c._socket
 
 header = { IPROTO_CODE: REQUEST_TYPE_CALL, IPROTO_SYNC: 100 }
-body = { IPROTO_FUNCTION_NAME: 'kek' }
+body = { IPROTO_FUNCTION_NAME: "kek" }
 resp = test_request(header, body)
-print "Sync: ", resp['header'][IPROTO_SYNC]
-print "Retcode: ", resp['body'][IPROTO_DATA]
+print("Sync: ", resp["header"][IPROTO_SYNC])
+print("Retcode: ", resp["body"][IPROTO_DATA])
 
 c.close()
 
diff --git a/test/box-py/print.result b/test/box-py/print.result
index b2d58d7de..7a3282d79 100644
--- a/test/box-py/print.result
+++ b/test/box-py/print.result
@@ -1,4 +1,4 @@
-print("Hello, world")
+print('Hello, world')
 ---
 ...
 io = require('io')
@@ -17,9 +17,9 @@ require('fiber').sleep(0.01)
 ...
 Check log line (Hello):
 ---
-- "logfile contains "Hello""
+- 'logfile contains 'Hello''
 ...
 Check log line (Ehllo):
 ---
-- "logfile contains "Ehllo""
+- 'logfile contains 'Ehllo''
 ...
diff --git a/test/box-py/print.test.py b/test/box-py/print.test.py
index 5083bdf42..015ce633a 100644
--- a/test/box-py/print.test.py
+++ b/test/box-py/print.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import tarantool
 
 import sys
@@ -6,7 +8,7 @@ import re
 
 log = server.get_log()
 
-admin('print("Hello, world")')
+admin("print('Hello, world')")
 admin("io = require('io')")
 
 admin("""local f = require('fiber').create(
@@ -18,17 +20,17 @@ admin("""local f = require('fiber').create(
 admin("require('fiber').sleep(0.01)")
 
 print("Check log line (Hello):")
-print('---')
-if log.seek_once('Hello') >= 0:
-    print('- "logfile contains "Hello""')
+print("---")
+if log.seek_once("Hello") >= 0:
+    print("- 'logfile contains 'Hello''")
 else:
-    print('- "logfile does not contain "Hello""')
-print('...')
+    print("- 'logfile does not contain 'Hello''")
+print("...")
 
 print("Check log line (Ehllo):")
-print('---')
-if log.seek_once('Ehllo') >= 0:
-    print('- "logfile contains "Ehllo""')
+print("---")
+if log.seek_once("Ehllo") >= 0:
+    print("- 'logfile contains 'Ehllo''")
 else:
-    print('- "logfile does not contain "Ehllo""')
-print('...')
+    print("- 'logfile does not contain 'Ehllo''")
+print("...")
diff --git a/test/box-py/snapshot.result b/test/box-py/snapshot.result
index fbaab912f..dfd1a00a2 100644
--- a/test/box-py/snapshot.result
+++ b/test/box-py/snapshot.result
@@ -10,7 +10,6 @@ index = space:create_index('primary', { type = 'hash' })
 # file that already exists. Verify also that any other
 # error that happens when saving snapshot is propagated
 # to the caller.
-
 space:insert{1, 'first tuple'}
 ---
 - [1, 'first tuple']
@@ -44,9 +43,8 @@ space:delete{2}
 ...
 #
 # A test case for http://bugs.launchpad.net/bugs/727174
-# "tarantool_box crashes when saving snapshot on SIGUSR1"
+# 'tarantool_box crashes when saving snapshot on SIGUSR1'
 #
-
 # Increment the lsn number, to make sure there is no such snapshot yet
 #
 space:insert{1, 'Test tuple'}
diff --git a/test/box-py/snapshot.test.py b/test/box-py/snapshot.test.py
index 2bfb8f621..91ff0c5dd 100644
--- a/test/box-py/snapshot.test.py
+++ b/test/box-py/snapshot.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import sys
 import yaml
@@ -9,13 +11,13 @@ sys.stdout.push_filter(server.vardir, "<dir>")
 admin("space = box.schema.space.create('tweedledum')")
 admin("index = space:create_index('primary', { type = 'hash' })")
 
-print """#
-# A test case for: http://bugs.launchpad.net/bugs/686411
-# Check that 'box.snapshot()' does not overwrite a snapshot
-# file that already exists. Verify also that any other
-# error that happens when saving snapshot is propagated
-# to the caller.
-"""
+print("#")
+print("# A test case for: http://bugs.launchpad.net/bugs/686411")
+print("# Check that 'box.snapshot()' does not overwrite a snapshot")
+print("# file that already exists. Verify also that any other")
+print("# error that happens when saving snapshot is propagated")
+print("# to the caller.")
+
 admin("space:insert{1, 'first tuple'}")
 admin("box.snapshot()")
 #
@@ -38,14 +40,13 @@ os.rmdir(snapshot)
 admin("space:delete{1}")
 admin("space:delete{2}")
 
-print """#
-# A test case for http://bugs.launchpad.net/bugs/727174
-# "tarantool_box crashes when saving snapshot on SIGUSR1"
-#"""
+print("#")
+print("# A test case for http://bugs.launchpad.net/bugs/727174")
+print("# 'tarantool_box crashes when saving snapshot on SIGUSR1'")
+print("#")
 
-print """
-# Increment the lsn number, to make sure there is no such snapshot yet
-#"""
+print("# Increment the lsn number, to make sure there is no such snapshot yet")
+print("#")
 
 admin("space:insert{1, 'Test tuple'}")
 
@@ -65,9 +66,9 @@ while not os.access(snapshot, os.F_OK) and iteration < MAX_ITERATIONS:
   iteration = iteration + 1
 
 if iteration == 0 or iteration >= MAX_ITERATIONS:
-  print "Snapshot is missing."
+  print("Snapshot is missing.")
 else:
-  print "Snapshot exists."
+  print("Snapshot exists.")
 
 admin("space:drop()")
 
diff --git a/test/long_run-py/finalizers.result b/test/long_run-py/finalizers.result
index 29313694c..2d2866b35 100644
--- a/test/long_run-py/finalizers.result
+++ b/test/long_run-py/finalizers.result
@@ -1 +1 @@
-Expected error: <class 'lib.tarantool_server.TarantoolStartError'>
+('Expected error:', <class 'lib.tarantool_server.TarantoolStartError'>)
diff --git a/test/long_run-py/finalizers.test.py b/test/long_run-py/finalizers.test.py
index 96118e607..07bceb6b9 100644
--- a/test/long_run-py/finalizers.test.py
+++ b/test/long_run-py/finalizers.test.py
@@ -5,12 +5,12 @@ import yaml
 from lib.tarantool_server import TarantoolServer
 
 server = TarantoolServer(server.ini)
-server.script = 'long_run-py/lua/finalizers.lua'
-server.vardir = os.path.join(server.vardir, 'finalizers')
+server.script = "long_run-py/lua/finalizers.lua"
+server.vardir = os.path.join(server.vardir, "finalizers")
 server.crash_expected = True
 try:
     server.deploy()
 except:
-    print "Expected error:", sys.exc_info()[0]
+    print("Expected error:", sys.exc_info()[0])
 else:
-    print "Error! exception did not occur"
+    print("Error! exception did not occur")
diff --git a/test/replication-py/cluster.result b/test/replication-py/cluster.result
index f68a6af7c..9bc8a7393 100644
--- a/test/replication-py/cluster.result
+++ b/test/replication-py/cluster.result
@@ -93,7 +93,7 @@ box.info.vclock[2] == nil
 -------------------------------------------------------------
 Modify data to bump LSN and check box.info
 -------------------------------------------------------------
-box.space._schema:insert{"test", 48}
+box.space._schema:insert{'test', 48}
 ---
 - ['test', 48]
 ...
@@ -114,7 +114,7 @@ box.cfg{ replication_source = '<replication_source>' }
 -------------------------------------------------------------
 Disconnect replica from master
 -------------------------------------------------------------
-box.cfg { replication_source = "" }
+box.cfg { replication_source = '' }
 ---
 ...
 -------------------------------------------------------------
@@ -131,7 +131,7 @@ box.info.vclock[2] == 1
 -------------------------------------------------------------
 Modify data to bump LSN on replica
 -------------------------------------------------------------
-box.space._schema:insert{"tost", 49}
+box.space._schema:insert{'tost', 49}
 ---
 - ['tost', 49]
 ...
diff --git a/test/replication-py/cluster.test.py b/test/replication-py/cluster.test.py
index 088ca9c34..c770a9bc9 100644
--- a/test/replication-py/cluster.test.py
+++ b/test/replication-py/cluster.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import sys
 import re
@@ -7,19 +9,19 @@ import glob
 from lib.tarantool_server import TarantoolServer
 
 ## Get cluster uuid
-cluster_uuid = ''
+cluster_uuid = ""
 try:
     cluster_uuid = yaml.safe_load(server.admin("box.space._schema:get('cluster')",
         silent = True))[0][1]
-    uuid.UUID('{' + cluster_uuid + '}')
-    print 'ok - cluster uuid'
+    uuid.UUID("{" + cluster_uuid + "}")
+    print("ok - cluster uuid")
 except Exception as e:
-    print 'not ok - invalid cluster uuid', e
+    print("not ok - invalid cluster uuid", e)
 
 server.iproto.reconnect() # re-connect with new permissions
-print '-------------------------------------------------------------'
-print ' gh-696: Check global READ permissions for replication'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print(" gh-696: Check global READ permissions for replication")
+print("-------------------------------------------------------------")
 
 
 # Generate replica cluster UUID
@@ -27,56 +29,59 @@ replica_uuid = str(uuid.uuid4())
 
 ## Universal read permission is required to perform JOIN/SUBSCRIBE
 rows = list(server.iproto.py_con.join(replica_uuid))
-print len(rows) == 1 and rows[0].return_message.find('Read access') >= 0 and \
-    'ok' or 'not ok', '-', 'join without read permissions on universe'
+status = len(rows) == 1 and rows[0].return_message.find("Read access") >= 0 and \
+        "ok" or "not ok"
+print("{} - join without read permissions on universe".format(status))
 rows = list(server.iproto.py_con.subscribe(cluster_uuid, replica_uuid))
-print len(rows) == 1 and rows[0].return_message.find('Read access') >= 0 and \
-    'ok' or 'not ok', '-', 'subscribe without read permissions on universe'
+status = len(rows) == 1 and rows[0].return_message.find("Read access") >= 0 and \
+        "ok" or "not ok"
+print("{} - subscribe without read permissions on universe".format(status))
 ## Write permission to space `_cluster` is required to perform JOIN
 server.admin("box.schema.user.grant('guest', 'read', 'universe')")
 server.iproto.reconnect() # re-connect with new permissions
 rows = list(server.iproto.py_con.join(replica_uuid))
-print len(rows) == 1 and rows[0].return_message.find('Write access') >= 0 and \
-    'ok' or 'not ok', '-', 'join without write permissions to _cluster'
+status = len(rows) == 1 and rows[0].return_message.find("Write access") >= 0 and \
+        "ok" or "not ok"
+print("{} - join without write permissions to _cluster".format(status))
 
 def check_join(msg):
     ok = True
     for resp in server.iproto.py_con.join(replica_uuid):
         if resp._return_code != 0:
-            print 'not ok', '-', msg, resp.return_message
+            print("not ok - {} {}".format(msg, resp.return_message))
             ok = False
 
     server.iproto.reconnect() # the only way to stop JOIN
     if not ok:
         return
-    tuples = server.iproto.py_con.space('_cluster').select(replica_uuid, index = 1)
+    tuples = server.iproto.py_con.space("_cluster").select(replica_uuid, index = 1)
     if len(tuples) == 0:
-        print 'not ok', '-', msg, 'missing entry in _cluster'
+        print("not ok - {} missing entry in _cluster".format(msg))
         return
     server_id = tuples[0][0]
-    print 'ok', '-', msg
+    print("ok - {}".format(msg))
     return server_id
 
 ## JOIN with permissions
 server.admin("box.schema.user.grant('guest', 'write', 'space', '_cluster')")
 server.iproto.reconnect() # re-connect with new permissions
-server_id = check_join('join with granted permissions')
-server.iproto.py_con.space('_cluster').delete(server_id)
+server_id = check_join("join with granted permissions")
+server.iproto.py_con.space("_cluster").delete(server_id)
 
 # JOIN with granted role
 server.admin("box.schema.user.revoke('guest', 'read', 'universe')")
 server.admin("box.schema.user.revoke('guest', 'write', 'space', '_cluster')")
 server.admin("box.schema.user.grant('guest', 'replication')")
 server.iproto.reconnect() # re-connect with new permissions
-server_id = check_join('join with granted role')
-server.iproto.py_con.space('_cluster').delete(server_id)
+server_id = check_join("join with granted role")
+server.iproto.py_con.space("_cluster").delete(server_id)
 
-print '-------------------------------------------------------------'
-print 'gh-434: Assertion if replace _cluster tuple for local server'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("gh-434: Assertion if replace _cluster tuple for local server")
+print("-------------------------------------------------------------")
 
-master_uuid = server.get_param('uuid')
-sys.stdout.push_filter(master_uuid, '<master uuid>')
+master_uuid = server.get_param("uuid")
+sys.stdout.push_filter(master_uuid, "<master uuid>")
 
 # Invalid UUID
 server.admin("box.space._cluster:replace{1, require('uuid').NULL:str()}")
@@ -87,19 +92,19 @@ server.admin("box.space._cluster:replace{1, require('uuid').str()}")
 # Update of tail is OK
 server.admin("box.space._cluster:update(1, {{'=', 3, 'test'}})")
 
-print '-------------------------------------------------------------'
-print 'gh-1140: Assertion if replace _cluster tuple for remote server'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("gh-1140: Assertion if replace _cluster tuple for remote server")
+print("-------------------------------------------------------------")
 
 # Test that insert is OK
-new_uuid = '0d5bd431-7f3e-4695-a5c2-82de0a9cbc95'
+new_uuid = "0d5bd431-7f3e-4695-a5c2-82de0a9cbc95"
 server.admin("box.space._cluster:insert{{5, '{0}'}}".format(new_uuid))
 server.admin("box.info.vclock[5] == nil")
 
 # Replace with the same UUID is OK
 server.admin("box.space._cluster:replace{{5, '{0}'}}".format(new_uuid))
 # Replace with a new UUID is not OK
-new_uuid = 'a48a19a3-26c0-4f8c-a5b5-77377bab389b'
+new_uuid = "a48a19a3-26c0-4f8c-a5b5-77377bab389b"
 server.admin("box.space._cluster:replace{{5, '{0}'}}".format(new_uuid))
 # Update of tail is OK
 server.admin("box.space._cluster:update(5, {{'=', 3, 'test'}})")
@@ -112,83 +117,83 @@ server.admin("box.info.vclock[5] == nil")
 server.stop()
 server.deploy()
 
-print '-------------------------------------------------------------'
-print 'Start a new replica and check box.info on the start'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("Start a new replica and check box.info on the start")
+print("-------------------------------------------------------------")
 # master server
 master = server
-master_id = master.get_param('id')
+master_id = master.get_param("id")
 
 master.admin("box.schema.user.grant('guest', 'replication')")
 
 replica = TarantoolServer(server.ini)
-replica.script = 'replication-py/replica.lua'
+replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir
 replica.rpl_master = master
 replica.deploy()
-replica_id = replica.get_param('id')
-replica_uuid = replica.get_param('uuid')
-sys.stdout.push_filter(replica_uuid, '<replica uuid>')
-
-replica.admin('box.info.id == %d' % replica_id)
-replica.admin('not box.info.ro')
-replica.admin('box.info.lsn == 0')
-replica.admin('box.info.vclock[%d] == nil' % replica_id)
-
-print '-------------------------------------------------------------'
-print 'Modify data to bump LSN and check box.info'
-print '-------------------------------------------------------------'
-replica.admin('box.space._schema:insert{"test", 48}')
-replica.admin('box.info.lsn == 1')
-replica.admin('box.info.vclock[%d] == 1' % replica_id)
-
-print '-------------------------------------------------------------'
-print 'Connect master to replica'
-print '-------------------------------------------------------------'
-replication_source = yaml.safe_load(replica.admin('box.cfg.listen', silent = True))[0]
-sys.stdout.push_filter(replication_source, '<replication_source>')
-master.admin("box.cfg{ replication_source = '%s' }" % replication_source)
+replica_id = replica.get_param("id")
+replica_uuid = replica.get_param("uuid")
+sys.stdout.push_filter(replica_uuid, "<replica uuid>")
+
+replica.admin("box.info.id == {}".format(replica_id))
+replica.admin("not box.info.ro")
+replica.admin("box.info.lsn == 0")
+replica.admin("box.info.vclock[{}] == nil".format(replica_id))
+
+print("-------------------------------------------------------------")
+print("Modify data to bump LSN and check box.info")
+print("-------------------------------------------------------------")
+replica.admin("box.space._schema:insert{'test', 48}")
+replica.admin("box.info.lsn == 1")
+replica.admin("box.info.vclock[{}] == 1".format(replica_id))
+
+print("-------------------------------------------------------------")
+print("Connect master to replica")
+print("-------------------------------------------------------------")
+replication_source = yaml.safe_load(replica.admin("box.cfg.listen", silent = True))[0]
+sys.stdout.push_filter(replication_source, "<replication_source>")
+master.admin("box.cfg{{ replication_source = '{}' }}".format(replication_source))
 master.wait_lsn(replica_id, replica.get_lsn(replica_id))
 
-print '-------------------------------------------------------------'
-print 'Disconnect replica from master'
-print '-------------------------------------------------------------'
-replica.admin('box.cfg { replication_source = "" }')
+print("-------------------------------------------------------------")
+print("Disconnect replica from master")
+print("-------------------------------------------------------------")
+replica.admin("box.cfg { replication_source = '' }")
 
-print '-------------------------------------------------------------'
-print 'Unregister replica'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("Unregister replica")
+print("-------------------------------------------------------------")
 
-master.admin('box.space._cluster:delete{%d} ~= nil' % replica_id)
+master.admin("box.space._cluster:delete{{{}}} ~= nil".format(replica_id))
 
 # gh-1219: LSN must not be removed from vclock on unregister
-master.admin('box.info.vclock[%d] == 1' % replica_id)
+master.admin("box.info.vclock[{}] == 1".format(replica_id))
 
-print '-------------------------------------------------------------'
-print 'Modify data to bump LSN on replica'
-print '-------------------------------------------------------------'
-replica.admin('box.space._schema:insert{"tost", 49}')
-replica.admin('box.info.lsn == 2')
-replica.admin('box.info.vclock[%d] == 2' % replica_id)
+print("-------------------------------------------------------------")
+print("Modify data to bump LSN on replica")
+print("-------------------------------------------------------------")
+replica.admin("box.space._schema:insert{'tost', 49}")
+replica.admin("box.info.lsn == 2")
+replica.admin("box.info.vclock[{}] == 2".format(replica_id))
 
-print '-------------------------------------------------------------'
-print 'Master must not crash then receives orphan rows from replica'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("Master must not crash then receives orphan rows from replica")
+print("-------------------------------------------------------------")
 
-replication_source = yaml.safe_load(replica.admin('box.cfg.listen', silent = True))[0]
-sys.stdout.push_filter(replication_source, '<replication>')
-master.admin("box.cfg{ replication = '%s' }" % replication_source)
+replication_source = yaml.safe_load(replica.admin("box.cfg.listen", silent = True))[0]
+sys.stdout.push_filter(replication_source, "<replication>")
+master.admin("box.cfg{{ replication = '{}' }}".format(replication_source))
 
 master.wait_lsn(replica_id, replica.get_lsn(replica_id))
-master.admin('box.info.vclock[%d] == 2' % replica_id)
+master.admin("box.info.vclock[{}] == 2".format(replica_id))
 
 master.admin("box.cfg{ replication = '' }")
 replica.stop()
 replica.cleanup()
 
-print '-------------------------------------------------------------'
-print 'Start a new replica and check that server_id, LSN is re-used'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("Start a new replica and check that server_id, LSN is re-used")
+print("-------------------------------------------------------------")
 
 #
 # gh-1219: Proper removal of servers with non-zero LSN from _cluster
@@ -196,36 +201,36 @@ print '-------------------------------------------------------------'
 # Snapshot is required. Otherwise a relay will skip records made by previous
 # replica with the re-used id.
 master.admin("box.snapshot()")
-master.admin('box.info.vclock[%d] == 2' % replica_id)
+master.admin("box.info.vclock[{}] == 2".format(replica_id))
 
 replica = TarantoolServer(server.ini)
-replica.script = 'replication-py/replica.lua'
+replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir
 replica.rpl_master = master
 replica.deploy()
 replica.wait_lsn(master_id, master.get_lsn(master_id))
 # Check that replica_id was re-used
-replica.admin('box.info.id == %d' % replica_id)
-replica.admin('not box.info.ro')
+replica.admin("box.info.id == {}".format(replica_id))
+replica.admin("not box.info.ro")
 # All records were succesfully recovered.
 # Replica should have the same vclock as master.
-master.admin('box.info.vclock[%d] == 2' % replica_id)
-replica.admin('box.info.vclock[%d] == 2' % replica_id)
+master.admin("box.info.vclock[{}] == 2".format(replica_id))
+replica.admin("box.info.vclock[{}] == 2".format(replica_id))
 
 replica.stop()
 replica.cleanup()
-master.admin('box.space._cluster:delete{%d} ~= nil' % replica_id)
+master.admin("box.space._cluster:delete{{{}}} ~= nil".format(replica_id))
 
-print '-------------------------------------------------------------'
-print 'JOIN replica to read-only master'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("JOIN replica to read-only master")
+print("-------------------------------------------------------------")
 
 # master server
 master = server
-master.admin('box.cfg { read_only = true }')
+master.admin("box.cfg { read_only = true }")
 #gh-1230 Assertion vclock_has on attempt to JOIN read-only master
 failed = TarantoolServer(server.ini)
-failed.script = 'replication-py/failed.lua'
+failed.script = "replication-py/failed.lua"
 failed.vardir = server.vardir
 failed.rpl_master = master
 failed.name = "failed"
@@ -235,16 +240,16 @@ try:
 except Exception as e:
     line = "ER_READONLY"
     if failed.logfile_pos.seek_once(line) >= 0:
-        print "'%s' exists in server log" % line
+        print("\'{}\' exists in server log".format(line))
 
-master.admin('box.cfg { read_only = false }')
+master.admin("box.cfg { read_only = false }")
 
-print '-------------------------------------------------------------'
-print 'JOIN replica with different replica set UUID'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("JOIN replica with different replica set UUID")
+print("-------------------------------------------------------------")
 
 failed = TarantoolServer(server.ini)
-failed.script = 'replication-py/uuid_mismatch.lua'
+failed.script = "replication-py/uuid_mismatch.lua"
 failed.vardir = server.vardir
 failed.rpl_master = master
 failed.name = "uuid_mismatch"
@@ -254,15 +259,15 @@ try:
 except Exception as e:
     line = "ER_REPLICASET_UUID_MISMATCH"
     if failed.logfile_pos.seek_once(line) >= 0:
-        print "'%s' exists in server log" % line
+        print("\'{}\' exists in server log".format(line))
 
 failed.cleanup()
 
-print '-------------------------------------------------------------'
-print 'Cleanup'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("Cleanup")
+print("-------------------------------------------------------------")
 
 # Cleanup
 sys.stdout.pop_filter()
 master.admin("box.schema.user.revoke('guest', 'replication')")
-master.admin('box.space._cluster:delete{2} ~= nil')
+master.admin("box.space._cluster:delete{2} ~= nil")
diff --git a/test/replication-py/conflict.test.py b/test/replication-py/conflict.test.py
index 1dcd66765..5e19d0c40 100644
--- a/test/replication-py/conflict.test.py
+++ b/test/replication-py/conflict.test.py
@@ -1,35 +1,37 @@
+from __future__ import print_function
+
 from lib.tarantool_server import TarantoolServer
 from time import sleep
 import yaml
 
-def check_replication(nodes, select_args=''):
+def check_replication(nodes, select_args=""):
     for node in nodes:
-        node.admin('box.space.test:select{%s}' % select_args)
+        node.admin("box.space.test:select{{{}}}".format(select_args))
 
 master = server
 master.admin("box.schema.user.grant('guest', 'replication')")
 
 replica = TarantoolServer(server.ini)
-replica.script = 'replication-py/replica.lua'
+replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir
 replica.rpl_master = master
 replica.deploy()
 
 def parallel_run(cmd1, cmd2, compare):
-    print 'parallel send: %s' % cmd1
-    print 'parallel send: %s' % cmd2
-    master.admin.socket.sendall('%s\n' % cmd1)
-    replica.admin.socket.sendall('%s\n' % cmd2)
+    print("parallel send: {}".format(cmd1))
+    print("parallel send: {}".format(cmd2))
+    master.admin.socket.sendall("{}\n".format(cmd1))
+    replica.admin.socket.sendall("{}\n".format(cmd2))
 
     master.admin.socket.recv(2048)
     replica.admin.socket.recv(2048)
 
     # wait for status changing in tarantool
     master_status = yaml.safe_load(master.admin(
-        'box.info().replication[2].upstream.status', silent=True
+        "box.info().replication[2].upstream.status", silent=True
     ))[0]
     replica_status = yaml.safe_load(replica.admin(
-        'box.info().replication[1].upstream.status', silent=True
+        "box.info().replication[1].upstream.status", silent=True
     ))[0]
 
     # wait for status
@@ -37,11 +39,11 @@ def parallel_run(cmd1, cmd2, compare):
     while True:
         sleep(0.01)
         if any(results):
-            print 'replication state is correct'
+            print("replication state is correct")
             break
 
 def prepare_cluster():
-    print 'reset master-master replication'
+    print("reset master-master replication")
     master.stop()
     master.cleanup()
     master.start()
@@ -51,13 +53,13 @@ def prepare_cluster():
     replica.cleanup()
     replica.start()
 
-    master.admin("box.cfg{replication='%s'}" % replica.iproto.uri, silent=True)
-    r1_id = replica.get_param('id')
-    r2_id = master.get_param('id')
+    master.admin("box.cfg{{replication='{}'}}".format(replica.iproto.uri), silent=True)
+    r1_id = replica.get_param("id")
+    r2_id = master.get_param("id")
 
     master.admin("space = box.schema.space.create('test')", silent=True)
     master.admin("index = space:create_index('primary', { type = 'tree'})", silent=True)
-    master.admin('for k = 1, 9 do space:insert{k, k*k} end', silent=True)
+    master.admin("for k = 1, 9 do space:insert{k, k*k} end", silent=True)
 
     # wait lsn
     replica.wait_lsn(r2_id, master.get_lsn(r2_id))
@@ -69,20 +71,20 @@ parallel_run(
     "box.space.test:update(1, {{'#', 2, 1}})",
     "box.space.test:update(1, {{'#', 2, 1}})",
     [
-        lambda x,y: x == 'stopped' or y == 'stopped',
-        lambda x,y: x == 'follow' and y == 'follow',
+        lambda x,y: x == "stopped" or y == "stopped",
+        lambda x,y: x == "follow" and y == "follow",
     ]
 )
-check_replication([master, replica], '1')
+check_replication([master, replica], "1")
 
 # test2: insert different values with single id
 prepare_cluster()
 parallel_run(
-    'box.space.test:insert{20, 1}',
-    'box.space.test:insert{20, 2}',
+    "box.space.test:insert{20, 1}",
+    "box.space.test:insert{20, 2}",
     [
-        lambda x,y: x == 'stopped' or y == 'stopped',
-        lambda x,y: x == 'follow' and y == 'follow',
+        lambda x,y: x == "stopped" or y == "stopped",
+        lambda x,y: x == "follow" and y == "follow",
     ]
 )
 
@@ -91,7 +93,7 @@ prepare_cluster()
 parallel_run(
     "box.space.test:update(2, {{'=', 2, 1}})",
     "box.space.test:update(2, {{'=', 2, 2}})",
-    [lambda x,y: x == 'follow' and y == 'follow',]
+    [lambda x,y: x == "follow" and y == "follow",]
 )
 
 # test4: CRDT increment with update
@@ -99,16 +101,16 @@ prepare_cluster()
 parallel_run(
     "box.space.test:update(1, {{'+', 2, 1}})",
     "box.space.test:update(1, {{'+', 2, 2}})",
-    [lambda x,y: x == 'follow' and y == 'follow',]
+    [lambda x,y: x == "follow" and y == "follow",]
 )
-check_replication([master, replica], '1')
+check_replication([master, replica], "1")
 
 # test5: delete not existing key
 prepare_cluster()
 parallel_run(
     "box.space.test:delete(999)",
     "box.space.test:delete(999)",
-    [lambda x,y: x == 'follow' and y == 'follow',]
+    [lambda x,y: x == "follow" and y == "follow",]
 )
 check_replication([master, replica])
 
diff --git a/test/replication-py/init_storage.test.py b/test/replication-py/init_storage.test.py
index f8641bf65..43ebc8afb 100644
--- a/test/replication-py/init_storage.test.py
+++ b/test/replication-py/init_storage.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import glob
 from lib.tarantool_server import TarantoolStartError
@@ -5,65 +7,65 @@ from lib.tarantool_server import TarantoolServer
 
 # master server
 master = server
-master_id = master.get_param('id')
+master_id = master.get_param("id")
 master.admin("box.schema.user.grant('guest', 'replication')")
 
-print '-------------------------------------------------------------'
-print 'gh-484: JOIN doesn\'t save data to snapshot with TREE index'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("gh-484: JOIN doesn't save data to snapshot with TREE index")
+print("-------------------------------------------------------------")
 
 master.admin("space = box.schema.space.create('test', {id =  42})")
 master.admin("index = space:create_index('primary', { type = 'tree'})")
 
-master.admin('for k = 1, 9 do space:insert{k, k*k} end')
+master.admin("for k = 1, 9 do space:insert{k, k*k} end")
 
 replica = TarantoolServer(server.ini)
-replica.script = 'replication-py/replica.lua'
+replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
 replica.rpl_master = master
 replica.deploy()
-replica.admin('box.space.test:select()')
+replica.admin("box.space.test:select()")
 
 replica.restart()
-replica.admin('box.space.test:select()')
+replica.admin("box.space.test:select()")
 replica.stop()
 replica.cleanup()
 
-print '-------------------------------------------------------------'
-print 'replica test 2 (must be ok)'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("replica test 2 (must be ok)")
+print("-------------------------------------------------------------")
 
 master.restart()
-master.admin('for k = 10, 19 do box.space[42]:insert{k, k*k*k} end')
+master.admin("for k = 10, 19 do box.space[42]:insert{k, k*k*k} end")
 master.admin("for k = 20, 29 do box.space[42]:upsert({k}, {}) end")
 lsn = master.get_lsn(master_id)
 
 replica = TarantoolServer(server.ini)
-replica.script = 'replication-py/replica.lua'
+replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
 replica.rpl_master = master
 replica.deploy()
 
-replica.admin('space = box.space.test');
+replica.admin("space = box.space.test");
 replica.wait_lsn(master_id, lsn)
 for i in range(1, 20):
-    replica.admin('space:get{%d}' % i)
+    replica.admin("space:get{{{}}}".format(i))
 
 replica.stop()
 replica.cleanup()
 
-print '-------------------------------------------------------------'
-print 'reconnect on JOIN/SUBSCRIBE'
-print '-------------------------------------------------------------'
+print("-------------------------------------------------------------")
+print("reconnect on JOIN/SUBSCRIBE")
+print("-------------------------------------------------------------")
 
 server.stop()
 replica = TarantoolServer(server.ini)
-replica.script = 'replication-py/replica.lua'
+replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
 replica.rpl_master = master
 replica.deploy(wait=False)
 
-print 'waiting reconnect on JOIN...'
+print("waiting reconnect on JOIN...")
 server.start()
 try:
     # Replica may fail to start due connection issues may occur, check
@@ -73,14 +75,14 @@ try:
     replica.crash_expected = True
     replica.wait_until_started()
 except TarantoolStartError:
-    print 'not ok - server failed to start'
+    print("not ok - server failed to start")
 else:
-    print 'ok'
+    print("ok")
 
 replica.stop()
 server.stop()
 
-print 'waiting reconnect on SUBSCRIBE...'
+print("waiting reconnect on SUBSCRIBE...")
 replica.start(wait=False)
 server.start()
 try:
@@ -91,9 +93,9 @@ try:
     replica.crash_expected = True
     replica.wait_until_started()
 except TarantoolStartError:
-    print 'not ok - server failed to start'
+    print("not ok - server failed to start")
 else:
-    print 'ok'
+    print("ok")
 
 replica.stop()
 replica.cleanup()
diff --git a/test/replication-py/multi.test.py b/test/replication-py/multi.test.py
index 233802458..a346fd560 100644
--- a/test/replication-py/multi.test.py
+++ b/test/replication-py/multi.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import sys
 import os
 from lib.tarantool_server import TarantoolServer
@@ -14,17 +16,17 @@ master.admin("fiber = require('fiber')")
 master.admin("box.schema.user.grant('guest', 'replication')")
 master.admin("box.schema.user.grant('guest', 'execute', 'universe')")
 
-print '----------------------------------------------------------------------'
-print 'Bootstrap replicas'
-print '----------------------------------------------------------------------'
+print("----------------------------------------------------------------------")
+print("Bootstrap replicas")
+print("----------------------------------------------------------------------")
 
 # Start replicas
-master.id = master.get_param('id')
+master.id = master.get_param("id")
 cluster = [ master ]
 for i in range(REPLICA_N - 1):
     server = TarantoolServer(server.ini)
-    server.script = 'replication-py/replica.lua'
-    server.vardir = os.path.join(server.vardir, 'replica', str(master.id + i))
+    server.script = "replication-py/replica.lua"
+    server.vardir = os.path.join(server.vardir, "replica", str(master.id + i))
     server.rpl_master = master
     server.deploy()
     # Wait replica to fully bootstrap.
@@ -34,14 +36,14 @@ for i in range(REPLICA_N - 1):
 # Make a list of servers
 sources = []
 for server in cluster:
-    sources.append(yaml.safe_load(server.admin('box.cfg.listen', silent = True))[0])
-    server.id = server.get_param('id')
+    sources.append(yaml.safe_load(server.admin("box.cfg.listen", silent = True))[0])
+    server.id = server.get_param("id")
 
-print 'done'
+print("done")
 
-print '----------------------------------------------------------------------'
-print 'Make a full mesh'
-print '----------------------------------------------------------------------'
+print("----------------------------------------------------------------------")
+print("Make a full mesh")
+print("----------------------------------------------------------------------")
 
 # Connect each server to each other to make full mesh
 for server in cluster:
@@ -54,55 +56,55 @@ for server in cluster:
             while #box.info.vclock[...] ~= nil do
                 fiber.sleep(0.01)
             end;""", server2.id)
-        print 'server', server.id, "connected"
+        print("server {} connected".format(server.id))
 
-print 'done'
+print("done")
 
-print '----------------------------------------------------------------------'
-print 'Test inserts'
-print '----------------------------------------------------------------------'
+print("----------------------------------------------------------------------")
+print("Test inserts")
+print("----------------------------------------------------------------------")
 
-print 'Create a test space'
+print("Create a test space")
 master.admin("_ = box.schema.space.create('test')")
 master.admin("_ = box.space.test:create_index('primary')")
 master_lsn = master.get_lsn(master.id)
 # Wait changes to propagate to replicas
 for server in cluster:
     server.wait_lsn(master.id, master_lsn)
-    print 'server', server.id, 'is ok'
-print
+    print("server {} is ok".format(server.id))
+print("")
 
-print 'Insert records'
+print("Insert records")
 for i in range(ROW_N):
     server = cluster[i % REPLICA_N]
-    server.admin("box.space.test:insert{%d, %s}" % (i, server.id), silent = True)
-print 'inserted %d records' % ROW_N
-print
+    server.admin("box.space.test:insert{{{}, {}}}".format(i, server.id), silent = True)
+print("inserted {} records".format(ROW_N))
+print("")
 
-print 'Synchronize'
+print("Synchronize")
 for server1 in cluster:
     for server2 in cluster:
         server1.wait_lsn(server2.id, server2.get_lsn(server2.id))
-    print 'server', server1.id, 'done'
-print 'done'
-print
+    print("server {} done".format(server1.id))
+print("done")
+print("")
 
-print 'Check data'
+print("Check data")
 for server in cluster:
     cnt = yaml.safe_load(server.admin("box.space.test:len()", silent = True))[0]
-    print 'server', server.id, 'is', cnt == ROW_N and 'ok' or 'not ok'
-print 'Done'
-print
+    print("server {} is {}".format(server.id, cnt == ROW_N and "ok" or "not ok"))
+print("Done")
+print("")
 
-print
-print '----------------------------------------------------------------------'
-print 'Cleanup'
-print '----------------------------------------------------------------------'
+print("")
+print("----------------------------------------------------------------------")
+print("Cleanup")
+print("----------------------------------------------------------------------")
 
 for server in cluster:
     server.stop()
-    print 'server', server.id, 'done'
-print
+    print("server {} done".format(server.id))
+print("")
 
 master.cleanup()
 master.deploy()
diff --git a/test/replication-py/swap.test.py b/test/replication-py/swap.test.py
index 98eeeea6d..b162ae241 100644
--- a/test/replication-py/swap.test.py
+++ b/test/replication-py/swap.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import tarantool
 from lib.tarantool_server import TarantoolServer
@@ -7,26 +9,26 @@ import yaml
 REPEAT = 20
 ID_BEGIN = 0
 ID_STEP = 5
-LOGIN = 'test'
-PASSWORD = 'pass123456'
+LOGIN = "test"
+PASSWORD = "pass123456"
 
-engines = ['memtx', 'vinyl']
+engines = ["memtx", "vinyl"]
 
 def insert_tuples(_server, begin, end, msg = "tuple"):
     for engine in engines:
         for i in range(begin, end):
-            print 'box.space.%s:insert{%d, "%s %d"}' % (engine, i, msg, i)
-            print '-'
+            print('box.space.{}:insert{{{}, "{} {}"}}'.format(engine, i, msg, i))
+            print("-")
             space = _server.iproto.py_con.space(engine)
-            print space.insert((i, '%s %d' % (msg, i)))
+            print(space.insert((i, "{} {}".format(msg, i))))
 
 def select_tuples(_server, begin, end):
     for engine in engines:
         for i in range(begin, end):
-            print 'box.space.%s:select{%d}' % (engine, i)
-            print '-'
+            print("box.space.{}:select{{{}}}".format(engine, i))
+            print("-")
             space = _server.iproto.py_con.space(engine)
-            print space.select(i)
+            print(space.select(i))
 
 # master server
 master = server
@@ -34,11 +36,11 @@ master = server
 master.stop()
 master.cleanup()
 master.deploy()
-master.admin("box.schema.user.create('%s', { password = '%s'})" % (LOGIN, PASSWORD))
-master.admin("box.schema.user.grant('%s', 'read,write,execute', 'universe')" % LOGIN)
+master.admin("box.schema.user.create('{}', {{ password = '{}'}})".format(LOGIN, PASSWORD))
+master.admin("box.schema.user.grant('{}', 'read,write,execute', 'universe')".format(LOGIN))
 master.iproto.py_con.authenticate(LOGIN, PASSWORD)
-master.uri = '%s:%s@%s' % (LOGIN, PASSWORD, master.iproto.uri)
-os.putenv('MASTER', master.uri)
+master.uri = "{}:{}@{}".format(LOGIN, PASSWORD, master.iproto.uri)
+os.putenv("MASTER", master.uri)
 
 # replica server
 replica = TarantoolServer()
@@ -46,12 +48,12 @@ replica.script = "replication-py/replica.lua"
 replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
 replica.deploy()
 replica.admin("while box.info.id == 0 do require('fiber').sleep(0.01) end")
-replica.uri = '%s:%s@%s' % (LOGIN, PASSWORD, replica.iproto.uri)
+replica.uri = "{}:{}@{}".format(LOGIN, PASSWORD, replica.iproto.uri)
 replica.admin("while box.space['_priv']:len() < 1 do require('fiber').sleep(0.01) end")
 replica.iproto.py_con.authenticate(LOGIN, PASSWORD)
 
 for engine in engines:
-    master.admin("s = box.schema.space.create('%s', { engine = '%s'})" % (engine, engine))
+    master.admin("s = box.schema.space.create('{}', {{ engine = '{}'}})".format(engine, engine))
     master.admin("index = s:create_index('primary', {type = 'tree'})")
 
 ### gh-343: replica.cc must not add login and password to proc title
@@ -61,12 +63,12 @@ for engine in engines:
 #if not m or m.group(1) != host_port:
 #    print 'invalid box.info.status', status, 'expected host:port', host_port
 
-master_id = master.get_param('id')
-replica_id = replica.get_param('id')
+master_id = master.get_param("id")
+replica_id = replica.get_param("id")
 
 id = ID_BEGIN
 for i in range(REPEAT):
-    print "test %d iteration" % i
+    print("test {} iteration".format(i))
 
     # insert to master
     insert_tuples(master, id, id + ID_STEP)
@@ -82,7 +84,7 @@ for i in range(REPEAT):
     select_tuples(replica, id, id + ID_STEP)
     id += ID_STEP
 
-    print "swap servers"
+    print("swap servers")
     # reconfigure replica to master
     replica.rpl_master = None
     print("switch replica to master")
@@ -90,7 +92,7 @@ for i in range(REPEAT):
     # reconfigure master to replica
     master.rpl_master = replica
     print("switch master to replica")
-    master.admin("box.cfg{replication='%s'}" % replica.uri, silent=True)
+    master.admin("box.cfg{{replication='{}'}}".format(replica.uri), silent=True)
 
     # insert to replica
     insert_tuples(replica, id, id + ID_STEP)
@@ -106,7 +108,7 @@ for i in range(REPEAT):
     select_tuples(master, id, id + ID_STEP)
     id += ID_STEP
 
-    print "rollback servers configuration"
+    print("rollback servers configuration")
     # reconfigure replica to master
     master.rpl_master = None
     print("switch master to master")
@@ -114,7 +116,7 @@ for i in range(REPEAT):
     # reconfigure master to replica
     replica.rpl_master = master
     print("switch replica to replica")
-    replica.admin("box.cfg{replication='%s'}" % master.uri, silent=True)
+    replica.admin("box.cfg{{replication='{}'}}".format(master.uri), silent=True)
 
 
 # Cleanup.
diff --git a/test/xlog-py/big_lsn.test.py b/test/xlog-py/big_lsn.test.py
index c6a31d971..edc1e5620 100644
--- a/test/xlog-py/big_lsn.test.py
+++ b/test/xlog-py/big_lsn.test.py
@@ -19,8 +19,8 @@ old_wal = os.path.join(wal_dir, "%020d.xlog" % old_lsn)
 new_wal = os.path.join(wal_dir, "%020d.xlog" % new_lsn)
 with open(old_wal, "r+") as f:
     s = f.read()
-    s = s.replace("VClock: {1: %d}" % old_lsn,
-                  "VClock: {1: %d}" % new_lsn)
+    s = s.replace("VClock: {{1: {}}}".format(old_lsn),
+                  "VClock: {{1: {}}}".format(new_lsn))
     f.seek(0)
     f.write(s)
 os.rename(old_wal, new_wal)
diff --git a/test/xlog-py/dup_key.test.py b/test/xlog-py/dup_key.test.py
index 7609c9555..b1442c520 100644
--- a/test/xlog-py/dup_key.test.py
+++ b/test/xlog-py/dup_key.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import yaml
 
@@ -26,7 +28,7 @@ server.stop()
 
 # Save wal#1
 if os.access(wal, os.F_OK):
-    print ".xlog exists"
+    print(".xlog exists")
     os.rename(wal, wal_old)
 
 # Write wal#2
@@ -37,18 +39,17 @@ server.stop()
 
 # Restore wal#1
 if not os.access(wal, os.F_OK):
-    print ".xlog does not exist"
+    print(".xlog does not exist")
     os.rename(wal_old, wal)
 
 server.start()
-line = 'Duplicate key'
-print "check log line for '%s'" % line
-print
+line = "Duplicate key"
+print("check log line for '{}'".format(line))
+print("")
 if server.logfile_pos.seek_once(line) >= 0:
-    print "'%s' exists in server log" % line
-print
+    print("'{}' exists in server log".format(line))
+print("")
 
 server.admin("box.space.test:get{1}")
 server.admin("box.space.test:get{2}")
 server.admin("box.space.test:len()")
-
diff --git a/test/xlog-py/empty.test.py b/test/xlog-py/empty.test.py
index d6f89e0fb..8b19bc3d7 100644
--- a/test/xlog-py/empty.test.py
+++ b/test/xlog-py/empty.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import yaml
 from os.path import abspath
@@ -20,7 +22,7 @@ f.close()
 server.start()
 server.stop()
 if os.access(filename, os.F_OK):
-    print ".xlog exists"
+    print(".xlog exists")
 # the server has started but is crippled since it
 # can't override an existing file
 server.start()
diff --git a/test/xlog-py/lsn_gap.test.py b/test/xlog-py/lsn_gap.test.py
index 7a503ff07..8da6166a2 100644
--- a/test/xlog-py/lsn_gap.test.py
+++ b/test/xlog-py/lsn_gap.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import yaml
 #
@@ -28,11 +30,11 @@ os.unlink(wal)
 
 server.start()
 line="ignoring a gap in LSN"
-print "check log line for '%s'" % line
-print
+print("check log line for '{}'".format(line))
+print("")
 if server.logfile_pos.seek_once(line) >= 0:
-    print "'%s' exists in server log" % line
-print
+    print("'{}' exists in server log".format(line))
+print("")
 
 # missing tuple from removed xlog
 server.admin("box.space.test:select{}")
diff --git a/test/xlog-py/misc.test.py b/test/xlog-py/misc.test.py
index e39ae1495..3fcda9504 100644
--- a/test/xlog-py/misc.test.py
+++ b/test/xlog-py/misc.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 import yaml
 
@@ -11,9 +13,9 @@ server.stop()
 
 data_path = os.path.join(server.vardir, server.name)
 
-print """
-# xlog file must exist after inserts.
-"""
+print("")
+print("# xlog file must exist after inserts.")
+print("")
 filename = str(lsn).zfill(20) + ".xlog"
 wal = os.path.join(data_path, filename)
 
@@ -21,16 +23,16 @@ server.start()
 
 server.admin("space = box.schema.space.create('tweedledum')")
 if os.access(wal, os.F_OK):
-  print ".xlog exists"
+  print(".xlog exists")
 
 server.admin("index = space:create_index('primary', { type = 'hash' })")
 
 server.stop()
 lsn += 2
 
-print """
-# a new xlog must be opened after regular termination.
-"""
+print("")
+print("# a new xlog must be opened after regular termination.")
+print("")
 filename = str(lsn).zfill(20) + ".xlog"
 server.start()
 
@@ -39,18 +41,17 @@ wal = os.path.join(data_path, filename)
 server.admin("box.space.tweedledum:insert{3, 'third tuple'}")
 
 if os.access(wal, os.F_OK):
-  print "a new .xlog exists"
+  print("a new .xlog exists")
 
 server.stop()
 
 if os.access(wal, os.F_OK):
-  print ".xlog stays around after sutdown"
+  print(".xlog stays around after shutdown")
 lsn += 1
 
-print """
-# An xlog file with one record during recovery.
-"""
-
+print("")
+print("# An xlog file with one record during recovery.")
+print("")
 server.start()
 filename = str(lsn).zfill(20) + ".xlog"
 wal = os.path.join(data_path, filename)
@@ -63,7 +64,7 @@ if pid > 0:
 server.stop()
 
 if os.access(wal, os.F_OK):
-    print ".xlog exists after kill -9"
+    print(".xlog exists after kill -9")
     # Remove last byte from xlog
     f = open(wal, "a")
     size = f.tell()
@@ -73,7 +74,7 @@ if os.access(wal, os.F_OK):
 server.start()
 
 if os.access(wal, os.F_OK):
-  print "corrupt .xlog exists after start"
+  print("corrupt .xlog exists after start")
 server.stop()
 lsn += 1
 
@@ -98,4 +99,4 @@ for f in os.listdir(data_path):
 server.start()
 lsn = int(yaml.safe_load(admin("box.info.lsn", silent=True))[0])
 if lsn == orig_lsn:
-    print ".snap.inprogress is ignored"
+    print(".snap.inprogress is ignored")
diff --git a/test/xlog-py/missing.test.py b/test/xlog-py/missing.test.py
index df35dc6d7..2fff0df6c 100644
--- a/test/xlog-py/missing.test.py
+++ b/test/xlog-py/missing.test.py
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import yaml
 import os 
 #
@@ -34,11 +36,11 @@ os.unlink(wal)
 # this may lead to infinite recursion at start
 server.start()
 line="ignoring a gap in LSN"
-print "check log line for '%s'" % line
-print
+print("check log line for '{}'".format(line))
+print("")
 if server.logfile_pos.seek_once(line) >= 0:
-    print "'%s' exists in server log" % line
-print
+    print("'{}' exists in server log".format(line))
+print("")
 
 # missing tuples from removed xlog
 server.admin("box.space.test:select{}")
-- 
2.25.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x
       [not found] <cover.1607675470.git.sergeyb@tarantool.org>
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent sergeyb
@ 2020-12-11  8:42 ` sergeyb
  2020-12-13 17:58   ` Vladislav Shpilevoy
  2020-12-15 12:40   ` Leonid Vasiliev
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex " sergeyb
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 27+ messages in thread
From: sergeyb @ 2020-12-11  8:42 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

From: Sergey Bronnikov <sergeyb@tarantool.org>

In Python 2.x calling keys makes a copy of the key that you can iterate over
while modifying the dict. This doesn't work in Python 3.x because keys returns
an iterator instead of a list. Python 3 raise an exception "dictionary changed
size during iteration". To workaround it one can use list to force a copy of
the keys to be made.

Part of #5538
---
 test/box-py/iproto.test.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
index 5eccd40d3..25ead43c4 100644
--- a/test/box-py/iproto.test.py
+++ b/test/box-py/iproto.test.py
@@ -39,7 +39,7 @@ for (k,v) in list(globals().items()):
 
 def repr_dict(todump):
     d = {}
-    for (k, v) in list(todump.items()):
+    for (k, v) in todump.items():
         k_name = key_names.get(k, k)
         d[k_name] = v
     return repr(d)
-- 
2.25.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x
       [not found] <cover.1607675470.git.sergeyb@tarantool.org>
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent sergeyb
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x sergeyb
@ 2020-12-11  8:42 ` sergeyb
  2020-12-15 11:55   ` Leonid Vasiliev
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline sergeyb
  2020-12-13 19:02 ` [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code Sergey Bronnikov
  4 siblings, 1 reply; 27+ messages in thread
From: sergeyb @ 2020-12-11  8:42 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

From: Sergey Bronnikov <sergeyb@tarantool.org>

Part of #5538
---
 test/box-py/iproto.test.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
index 25ead43c4..72400923c 100644
--- a/test/box-py/iproto.test.py
+++ b/test/box-py/iproto.test.py
@@ -191,7 +191,11 @@ for test in TESTS:
     print("STR", size)
     print("--")
     for fmt in it:
-        print("0x" + fmt.encode("hex"), "=>", end=" ")
+        try:
+            # Python 3
+            print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
+        except AttributeError:
+            print("0x" + fmt.encode("hex"), "=>", end=" ")
         field = "*" * size
         c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
         tuple = space.select(field)[0]
-- 
2.25.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline
       [not found] <cover.1607675470.git.sergeyb@tarantool.org>
                   ` (2 preceding siblings ...)
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex " sergeyb
@ 2020-12-11  8:42 ` sergeyb
  2020-12-15 12:51   ` Leonid Vasiliev
  2020-12-13 19:02 ` [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code Sergey Bronnikov
  4 siblings, 1 reply; 27+ messages in thread
From: sergeyb @ 2020-12-11  8:42 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

From: Sergey Bronnikov <sergeyb@tarantool.org>

Closes #5538
---
 test/replication-py/init_storage.test.py | 6 +++---
 test/replication-py/swap.test.py         | 9 +--------
 test/xlog-py/dup_key.test.py             | 5 -----
 test/xlog-py/lsn_gap.test.py             | 1 -
 4 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/test/replication-py/init_storage.test.py b/test/replication-py/init_storage.test.py
index 43ebc8afb..a6e2d6563 100644
--- a/test/replication-py/init_storage.test.py
+++ b/test/replication-py/init_storage.test.py
@@ -21,7 +21,7 @@ master.admin("for k = 1, 9 do space:insert{k, k*k} end")
 
 replica = TarantoolServer(server.ini)
 replica.script = "replication-py/replica.lua"
-replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
+replica.vardir = server.vardir
 replica.rpl_master = master
 replica.deploy()
 replica.admin("box.space.test:select()")
@@ -42,7 +42,7 @@ lsn = master.get_lsn(master_id)
 
 replica = TarantoolServer(server.ini)
 replica.script = "replication-py/replica.lua"
-replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
+replica.vardir = server.vardir
 replica.rpl_master = master
 replica.deploy()
 
@@ -61,7 +61,7 @@ print("-------------------------------------------------------------")
 server.stop()
 replica = TarantoolServer(server.ini)
 replica.script = "replication-py/replica.lua"
-replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
+replica.vardir = server.vardir
 replica.rpl_master = master
 replica.deploy(wait=False)
 
diff --git a/test/replication-py/swap.test.py b/test/replication-py/swap.test.py
index b162ae241..ce1682641 100644
--- a/test/replication-py/swap.test.py
+++ b/test/replication-py/swap.test.py
@@ -45,7 +45,7 @@ os.putenv("MASTER", master.uri)
 # replica server
 replica = TarantoolServer()
 replica.script = "replication-py/replica.lua"
-replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
+replica.vardir = server.vardir
 replica.deploy()
 replica.admin("while box.info.id == 0 do require('fiber').sleep(0.01) end")
 replica.uri = "{}:{}@{}".format(LOGIN, PASSWORD, replica.iproto.uri)
@@ -56,13 +56,6 @@ for engine in engines:
     master.admin("s = box.schema.space.create('{}', {{ engine = '{}'}})".format(engine, engine))
     master.admin("index = s:create_index('primary', {type = 'tree'})")
 
-### gh-343: replica.cc must not add login and password to proc title
-#status = replica.get_param("status")
-#host_port = "%s:%s" % master.iproto.uri
-#m = re.search(r'replica/(.*)/.*', status)
-#if not m or m.group(1) != host_port:
-#    print 'invalid box.info.status', status, 'expected host:port', host_port
-
 master_id = master.get_param("id")
 replica_id = replica.get_param("id")
 
diff --git a/test/xlog-py/dup_key.test.py b/test/xlog-py/dup_key.test.py
index b1442c520..a40133ef2 100644
--- a/test/xlog-py/dup_key.test.py
+++ b/test/xlog-py/dup_key.test.py
@@ -3,11 +3,6 @@ from __future__ import print_function
 import os
 import yaml
 
-#print """
-#A test case for https://bugs.launchpad.net/tarantool/+bug/1052018
-#panic_on_wal_error doesn't work for duplicate key errors
-#"""
-
 server.stop()
 server.deploy()
 
diff --git a/test/xlog-py/lsn_gap.test.py b/test/xlog-py/lsn_gap.test.py
index 8da6166a2..b80b97146 100644
--- a/test/xlog-py/lsn_gap.test.py
+++ b/test/xlog-py/lsn_gap.test.py
@@ -38,4 +38,3 @@ print("")
 
 # missing tuple from removed xlog
 server.admin("box.space.test:select{}")
-
-- 
2.25.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent sergeyb
@ 2020-12-13 17:58   ` Vladislav Shpilevoy
  2020-12-14 11:44     ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Vladislav Shpilevoy @ 2020-12-13 17:58 UTC (permalink / raw)
  To: sergeyb, tarantool-patches, imun; +Cc: alexander.turenko

Hi! Thanks for the patch!

Finally, http_client.test.lua works on my machine.

I don't see the cover letter, with issue and branch links.
I assume the branch is ligurio/gh-5538-support-python3.

See 12 minor comments below.

On 11.12.2020 09:42, Sergey Bronnikov via Tarantool-patches wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
> 
> - convert print statement to function. In a Python 3 'print' becomes a
> function, see [1]. Patch makes 'print' in a regression tests compatible with
> Python 3.
> - according to PEP8, mixing using double quotes and quotes in a project looks
> inconsistent. Patch makes using quotes with strings consistent.> - print multiline strings with multiple print()

1. Why? Is it according to PEP too? The same for '%'.
What is wrong with using multiline strings?

> - use "format()" instead of "%" everywhere
> 1. https://docs.python.org/3/whatsnew/3.0.html#print-is-a-function
> 
> Part of #5538
> ---
> diff --git a/test/box-py/args.test.py b/test/box-py/args.test.py
> index c0fac9038..f1b840a85 100644
> --- a/test/box-py/args.test.py
> +++ b/test/box-py/args.test.py
> @@ -1,3 +1,5 @@
> +from __future__ import print_function

2. In this file I don't see you changing 'print' to 'print()'
anywhere. So why is this line needed? In this file I only see
"print" as a part of strings. As a word. Not as a function.

> +
>  import sys
>  import os
>  import re
> diff --git a/test/box-py/bad_trigger.result b/test/box-py/bad_trigger.result
> index 5d064b764..42cd9a7e8 100644
> --- a/test/box-py/bad_trigger.result
> +++ b/test/box-py/bad_trigger.result
> @@ -1,8 +1,6 @@
> -
>   #
>   # if on_connect() trigger raises an exception, the connection is dropped
>   #
> - 

3. Why is this file changed? It is .result file. Your changes are just
refactoring, so no .result files should be changed.

>  nosuchfunction = nil
>  ---
>  ...
> diff --git a/test/box-py/bad_trigger.test.py b/test/box-py/bad_trigger.test.py
> index 7d200b921..789fe8045 100644
> --- a/test/box-py/bad_trigger.test.py
> +++ b/test/box-py/bad_trigger.test.py
> @@ -24,12 +24,12 @@ conn.connect()
>  s = conn.socket
>  
>  # Read greeting
> -print 'greeting: ', len(s.recv(IPROTO_GREETING_SIZE)) == IPROTO_GREETING_SIZE
> +print("greeting:  {}".format(len(s.recv(IPROTO_GREETING_SIZE)) == IPROTO_GREETING_SIZE))
>  
>  # Read error packet
>  IPROTO_FIXHEADER_SIZE = 5
>  fixheader = s.recv(IPROTO_FIXHEADER_SIZE)
> -print 'fixheader: ', len(fixheader) == IPROTO_FIXHEADER_SIZE
> +print("fixheader:  {}".format(len(fixheader) == IPROTO_FIXHEADER_SIZE))

4. There was a single whitespace. You made it double. Why? The
same for the change above. And in one place below.

>  unpacker.feed(fixheader)
>  packet_len = unpacker.unpack()
>  packet = s.recv(packet_len)
> @@ -38,9 +38,9 @@ unpacker.feed(packet)
>  # Parse packet
>  header = unpacker.unpack()
>  body = unpacker.unpack()
> -print 'error code', (header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))
> -print 'error message: ', body[IPROTO_ERROR]
> -print 'eof:', len(s.recv(1024)) == 0
> +print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
> +print("error message:  {}".format(body[IPROTO_ERROR]))
> +print("eof: {}".format(len(s.recv(1024)) == 0))
>  s.close()
>  
>  server.admin("box.session.on_connect(nil, f1)")
> diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
> index 0876e77a6..865302698 100644
> --- a/test/box-py/bootstrap.result
> +++ b/test/box-py/bootstrap.result
> @@ -165,7 +165,7 @@ box.space._user:select{}
>    - [3, 1, 'replication', 'role', {}]
>    - [31, 1, 'super', 'role', {}]
>  ...
> -for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end
> +for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end

5. This is Lua. Not python. Why did you change it?

>  ---
>  - - [1, 1, 'box.schema.user.info', 1, 'LUA', '', 'function', [], 'any', 'none', 'none',
>      false, false, true, ['LUA'], {}, '', '', '']
> diff --git a/test/box-py/call.result b/test/box-py/call.result
> index d340ed6fa..e6b7b8dc9 100644
> --- a/test/box-py/call.result
> +++ b/test/box-py/call.result
> @@ -536,10 +536,10 @@ function f(...) return ... end
>  call f({'k2': 'v2', 'k1': 'v1'})
>  ---
>  - {'k2': 'v2', 'k1': 'v1'}
> -eval (return space:auto_increment({"transaction"}))()
> +eval (return space:auto_increment({'transaction'}))()
>  ---
>  - [1, 'transaction']
> -function f(...) return space:auto_increment({"transaction"}) end
> +function f(...) return space:auto_increment({'transaction'}) end

6. This whole file is Lua output. Why is it changed?

>  ---
>  ...
>  call f()
> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
> index cdd1a71c5..5eccd40d3 100644
> --- a/test/box-py/iproto.test.py
> +++ b/test/box-py/iproto.test.py
> @@ -11,46 +13,42 @@ from lib.tarantool_connection import TarantoolConnection
>  
>  admin("box.schema.user.grant('guest', 'read,write,execute', 'universe')")
>  
> -print """
> -#
> -# iproto packages test
> -#
> -"""
> +print("#")
> +print("# iproto packages test")
> +print("#")
>  
> -# opeing new connection to tarantool/box
> +# opening new connection to tarantool/box
>  conn = TarantoolConnection(server.iproto.host, server.iproto.port)
>  conn.connect()
>  s = conn.socket
>  
> -print """
> -# Test bug #899343 (server assertion failure on incorrect packet)
> -"""
> -print "# send the package with invalid length"
> -invalid_request = struct.pack('<LLL', 1, 4294967290, 1)
> -print s.send(invalid_request)
> -print "# check that is server alive"
> -print iproto.py_con.ping() > 0
> +print("# Test bug #899343 (server assertion failure on incorrect packet)")
> +print("# send the package with invalid length")
> +invalid_request = struct.pack("<LLL", 1, 4294967290, 1)
> +print(s.send(invalid_request))
> +print("# check that is server alive")
> +print(iproto.py_con.ping() > 0)
>  
>  # closing connection
>  s.close()
>  
>  key_names = {}
> -for (k,v) in globals().items():
> -    if type(k) == str and k.startswith('IPROTO_') and type(v) == int:
> +for (k,v) in list(globals().items()):

7. Why did you add list() call? I don't see in the commit
message any mentioning of why is it bad to use items() without
list(). The same below.

I suspect this has something to do with the second commit,
and therefore belongs to it.

> +    if type(k) == str and k.startswith("IPROTO_") and type(v) == int:
>          key_names[v] = k
> @@ -59,36 +57,34 @@ def test(header, body):
>      try:
>          s.send(query)
>      except OSError as e:
> -        print '   => ', 'Failed to send request'
> +        print("   => ", "Failed to send request")
>      c.close()
> -    print iproto.py_con.ping() > 0
> +    print(iproto.py_con.ping() > 0)
>  
> -print """
> -#  Test gh-206 "Segfault if sending IPROTO package without `KEY` field"
> -"""
> +print("#  Test gh-206 'Segfault if sending IPROTO package without `KEY` field'")

8. You changed the output. Previously it had one empty line before and
after the text. The same in some other places in this commit. No .result
files should be changed.

> diff --git a/test/replication-py/cluster.test.py b/test/replication-py/cluster.test.py
> index 088ca9c34..c770a9bc9 100644
> --- a/test/replication-py/cluster.test.py
> +++ b/test/replication-py/cluster.test.py
> @@ -27,56 +29,59 @@ replica_uuid = str(uuid.uuid4())
>  
>  ## Universal read permission is required to perform JOIN/SUBSCRIBE
>  rows = list(server.iproto.py_con.join(replica_uuid))
> -print len(rows) == 1 and rows[0].return_message.find('Read access') >= 0 and \
> -    'ok' or 'not ok', '-', 'join without read permissions on universe'
> +status = len(rows) == 1 and rows[0].return_message.find("Read access") >= 0 and \
> +        "ok" or "not ok"

9. I see, that at least in this file the indentation step is 4
symbols. Why did you change it to 8?

> +print("{} - join without read permissions on universe".format(status))
>  rows = list(server.iproto.py_con.subscribe(cluster_uuid, replica_uuid))
> -print len(rows) == 1 and rows[0].return_message.find('Read access') >= 0 and \
> -    'ok' or 'not ok', '-', 'subscribe without read permissions on universe'
> +status = len(rows) == 1 and rows[0].return_message.find("Read access") >= 0 and \
> +        "ok" or "not ok"
> +print("{} - subscribe without read permissions on universe".format(status))
>  ## Write permission to space `_cluster` is required to perform JOIN
>  server.admin("box.schema.user.grant('guest', 'read', 'universe')")
>  server.iproto.reconnect() # re-connect with new permissions
>  rows = list(server.iproto.py_con.join(replica_uuid))
> -print len(rows) == 1 and rows[0].return_message.find('Write access') >= 0 and \
> -    'ok' or 'not ok', '-', 'join without write permissions to _cluster'
> +status = len(rows) == 1 and rows[0].return_message.find("Write access") >= 0 and \
> +        "ok" or "not ok"> @@ -235,16 +240,16 @@ try:
>  except Exception as e:
>      line = "ER_READONLY"
>      if failed.logfile_pos.seek_once(line) >= 0:
> -        print "'%s' exists in server log" % line
> +        print("\'{}\' exists in server log".format(line))

10. You don't need to escape ' when they are inside of ".

> -master.admin('box.cfg { read_only = false }')
> +master.admin("box.cfg { read_only = false }")
>  
> -print '-------------------------------------------------------------'
> -print 'JOIN replica with different replica set UUID'
> -print '-------------------------------------------------------------'
> +print("-------------------------------------------------------------")
> +print("JOIN replica with different replica set UUID")
> +print("-------------------------------------------------------------")
>  
>  failed = TarantoolServer(server.ini)
> -failed.script = 'replication-py/uuid_mismatch.lua'
> +failed.script = "replication-py/uuid_mismatch.lua"
>  failed.vardir = server.vardir
>  failed.rpl_master = master
>  failed.name = "uuid_mismatch"
> @@ -254,15 +259,15 @@ try:
>  except Exception as e:
>      line = "ER_REPLICASET_UUID_MISMATCH"
>      if failed.logfile_pos.seek_once(line) >= 0:
> -        print "'%s' exists in server log" % line
> +        print("\'{}\' exists in server log".format(line))

11. You don't need to escape ' when they are inside of ".

12. There is also one place, where you removed an empty line in the
end of file. I can't find it again, but it belongs to the last
commit. Please, move it.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x sergeyb
@ 2020-12-13 17:58   ` Vladislav Shpilevoy
  2020-12-15 12:40   ` Leonid Vasiliev
  1 sibling, 0 replies; 27+ messages in thread
From: Vladislav Shpilevoy @ 2020-12-13 17:58 UTC (permalink / raw)
  To: sergeyb, tarantool-patches, imun; +Cc: alexander.turenko

Thanks for the patch!

On 11.12.2020 09:42, Sergey Bronnikov via Tarantool-patches wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
> 
> In Python 2.x calling keys makes a copy of the key that you can iterate over

What is 'keys' that I can call? Did you mean 'items'?

> while modifying the dict. This doesn't work in Python 3.x because keys returns
> an iterator instead of a list. Python 3 raise an exception "dictionary changed
> size during iteration". To workaround it one can use list to force a copy of
> the keys to be made.
> 
> Part of #5538
> ---

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code
       [not found] <cover.1607675470.git.sergeyb@tarantool.org>
                   ` (3 preceding siblings ...)
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline sergeyb
@ 2020-12-13 19:02 ` Sergey Bronnikov
  2020-12-23 10:07   ` Leonid Vasiliev
  4 siblings, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-13 19:02 UTC (permalink / raw)
  To: lvasiliev, tarantool-patches; +Cc: Vladislav Shpilevoy, alexander.turenko

+ tarantool-patches@dev.tarantool.org

On 11.12.2020 11:42, sergeyb@tarantool.org wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
>
> Changes v1:
> - convert print statements to functions
> - use "format()" instead of "%" everywhere
>
> Changes v2:
> - make using quotes with strings consistent
> - remove dead code
> - remove empty prints
> - added make target for running flake8
> - added flake8 config
> - added job to run flake8 on Gitlab CI
>
> Changes v3:
> - removed three patches with flake8 integration
> - fixed rest patches according to comments on review
> - add a separate patch with converting dict.items() to a list
> - add a new patch with conversion string to hex
>
> Gitlab CI: https://gitlab.com/tarantool/tarantool/-/jobs/904769000
> Branch: https://github.com/tarantool/tarantool/tree/ligurio/gh-5538-support-python3
> Issue: https://github.com/tarantool/tarantool/issues/5538
>
> Sergey Bronnikov (4):
>    test: convert print to function and make quotes use consistent
>    test: make dict.items() compatible with Python 3.x
>    test: make convert to hex compatible with Python 3.x
>    test: remove dead code in Python tests end extra newline
>
>   test/app-tap/httpd.py                    |  42 ++---
>   test/box-py/args.test.py                 |  14 +-
>   test/box-py/bad_trigger.result           |   2 -
>   test/box-py/bad_trigger.test.py          |  20 +--
>   test/box-py/bootstrap.result             |   2 +-
>   test/box-py/bootstrap.test.py            |  16 +-
>   test/box-py/call.result                  |  12 +-
>   test/box-py/call.test.py                 |  92 +++++-----
>   test/box-py/iproto.result                |  10 +-
>   test/box-py/iproto.test.py               | 220 +++++++++++------------
>   test/box-py/print.result                 |   6 +-
>   test/box-py/print.test.py                |  24 +--
>   test/box-py/snapshot.result              |   4 +-
>   test/box-py/snapshot.test.py             |  33 ++--
>   test/long_run-py/finalizers.result       |   2 +-
>   test/long_run-py/finalizers.test.py      |   8 +-
>   test/replication-py/cluster.result       |   6 +-
>   test/replication-py/cluster.test.py      | 217 +++++++++++-----------
>   test/replication-py/conflict.test.py     |  54 +++---
>   test/replication-py/init_storage.test.py |  58 +++---
>   test/replication-py/multi.test.py        |  78 ++++----
>   test/replication-py/swap.test.py         |  55 +++---
>   test/xlog-py/big_lsn.test.py             |   4 +-
>   test/xlog-py/dup_key.test.py             |  22 +--
>   test/xlog-py/empty.test.py               |   4 +-
>   test/xlog-py/lsn_gap.test.py             |  11 +-
>   test/xlog-py/misc.test.py                |  33 ++--
>   test/xlog-py/missing.test.py             |  10 +-
>   28 files changed, 530 insertions(+), 529 deletions(-)
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
  2020-12-13 17:58   ` Vladislav Shpilevoy
@ 2020-12-14 11:44     ` Sergey Bronnikov
  2020-12-15 10:05       ` Leonid Vasiliev
  0 siblings, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-14 11:44 UTC (permalink / raw)
  To: Vladislav Shpilevoy, tarantool-patches; +Cc: alexander.turenko

Hello,

thanks for review!

On 13.12.2020 20:58, Vladislav Shpilevoy wrote:
> Hi! Thanks for the patch!
>
> Finally, http_client.test.lua works on my machine.
>
> I don't see the cover letter, with issue and branch links.
> I assume the branch is ligurio/gh-5538-support-python3.

Yep, it's a right branch. Cover letter is here [1], first time it was 
send without ML address.

> See 12 minor comments below.
>
> On 11.12.2020 09:42, Sergey Bronnikov via Tarantool-patches wrote:
>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>
>> - convert print statement to function. In a Python 3 'print' becomes a
>> function, see [1]. Patch makes 'print' in a regression tests compatible with
>> Python 3.
>> - according to PEP8, mixing using double quotes and quotes in a project looks
>> inconsistent. Patch makes using quotes with strings consistent.> - print multiline strings with multiple print()
> 1. Why? Is it according to PEP too? The same for '%'.
> What is wrong with using multiline strings?

On first iteration I have converted print statements to functions as it 
is required by Python 3.

Leonid asked me to fix code style of strings too and I did it on second 
iteration, see conversation here [2].

Nothing wrong with multi-line prints, but for my taste it looks ugly.

I don't want to have yet another conversation about code style, if you 
are happy with multi-line strings in print - it's fine.

So I reverted changes related to multi-line strings because the main 
purpose of the series is Python 3 support.

>
>> - use "format()" instead of "%" everywhere
>> 1. https://docs.python.org/3/whatsnew/3.0.html#print-is-a-function
>>
>> Part of #5538
>> ---
>> diff --git a/test/box-py/args.test.py b/test/box-py/args.test.py
>> index c0fac9038..f1b840a85 100644
>> --- a/test/box-py/args.test.py
>> +++ b/test/box-py/args.test.py
>> @@ -1,3 +1,5 @@
>> +from __future__ import print_function
> 2. In this file I don't see you changing 'print' to 'print()'
> anywhere. So why is this line needed? In this file I only see
> "print" as a part of strings. As a word. Not as a function.
You are right. Removed import and force-pushed.
>
>> +
>>   import sys
>>   import os
>>   import re
>> diff --git a/test/box-py/bad_trigger.result b/test/box-py/bad_trigger.result
>> index 5d064b764..42cd9a7e8 100644
>> --- a/test/box-py/bad_trigger.result
>> +++ b/test/box-py/bad_trigger.result
>> @@ -1,8 +1,6 @@
>> -
>>    #
>>    # if on_connect() trigger raises an exception, the connection is dropped
>>    #
>> -
> 3. Why is this file changed? It is .result file. Your changes are just
> refactoring, so no .result files should be changed.
Added newlines.
>
>>   nosuchfunction = nil
>>   ---
>>   ...
>> diff --git a/test/box-py/bad_trigger.test.py b/test/box-py/bad_trigger.test.py
>> index 7d200b921..789fe8045 100644
>> --- a/test/box-py/bad_trigger.test.py
>> +++ b/test/box-py/bad_trigger.test.py
>> @@ -24,12 +24,12 @@ conn.connect()
>>   s = conn.socket
>>   
>>   # Read greeting
>> -print 'greeting: ', len(s.recv(IPROTO_GREETING_SIZE)) == IPROTO_GREETING_SIZE
>> +print("greeting:  {}".format(len(s.recv(IPROTO_GREETING_SIZE)) == IPROTO_GREETING_SIZE))
>>   
>>   # Read error packet
>>   IPROTO_FIXHEADER_SIZE = 5
>>   fixheader = s.recv(IPROTO_FIXHEADER_SIZE)
>> -print 'fixheader: ', len(fixheader) == IPROTO_FIXHEADER_SIZE
>> +print("fixheader:  {}".format(len(fixheader) == IPROTO_FIXHEADER_SIZE))
> 4. There was a single whitespace. You made it double. Why? The
> same for the change above. And in one place below.

Python2 print automatically adds a whitespace before an argument:

Python 2.7.18 (default, Aug  4 2020, 11:16:42)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
 >>> print "X", 3
X 3
 >>> from __future__ import print_function
 >>> print("X{}".format(3))
X3
 >>>

To produce same output as in a .result file additional whitespace has 
been added in a code.

>
>>   unpacker.feed(fixheader)
>>   packet_len = unpacker.unpack()
>>   packet = s.recv(packet_len)
>> @@ -38,9 +38,9 @@ unpacker.feed(packet)
>>   # Parse packet
>>   header = unpacker.unpack()
>>   body = unpacker.unpack()
>> -print 'error code', (header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))
>> -print 'error message: ', body[IPROTO_ERROR]
>> -print 'eof:', len(s.recv(1024)) == 0
>> +print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
>> +print("error message:  {}".format(body[IPROTO_ERROR]))
>> +print("eof: {}".format(len(s.recv(1024)) == 0))
>>   s.close()
>>   
>>   server.admin("box.session.on_connect(nil, f1)")
>> diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
>> index 0876e77a6..865302698 100644
>> --- a/test/box-py/bootstrap.result
>> +++ b/test/box-py/bootstrap.result
>> @@ -165,7 +165,7 @@ box.space._user:select{}
>>     - [3, 1, 'replication', 'role', {}]
>>     - [31, 1, 'super', 'role', {}]
>>   ...
>> -for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end
>> +for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end
> 5. This is Lua. Not python. Why did you change it?

I just made using quotes consistent in a Python code. Outer quotes are 
double quote and internal quote is a single one.

--- a/test/box-py/bootstrap.test.py
+++ b/test/box-py/bootstrap.test.py
@@ -1,11 +1,11 @@
-server.admin('box.internal.bootstrap()')
-server.admin('box.space._schema:select{}')
-server.admin('box.space._cluster:select{}')
-server.admin('box.space._space:select{}')
-server.admin('box.space._index:select{}')
-server.admin('box.space._user:select{}')
-server.admin('for _, v in box.space._func:pairs{} do r = {} 
table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end')
-server.admin('box.space._priv:select{}')
+server.admin("box.internal.bootstrap()")
+server.admin("box.space._schema:select{}")
+server.admin("box.space._cluster:select{}")
+server.admin("box.space._space:select{}")
+server.admin("box.space._index:select{}")
+server.admin("box.space._user:select{}")
+server.admin("for _, v in box.space._func:pairs{} do r = {} 
table.insert(r, v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end")
+server.admin("box.space._priv:select{}")

  # Cleanup
  server.stop()

>
>>   ---
>>   - - [1, 1, 'box.schema.user.info', 1, 'LUA', '', 'function', [], 'any', 'none', 'none',
>>       false, false, true, ['LUA'], {}, '', '', '']
>> diff --git a/test/box-py/call.result b/test/box-py/call.result
>> index d340ed6fa..e6b7b8dc9 100644
>> --- a/test/box-py/call.result
>> +++ b/test/box-py/call.result
>> @@ -536,10 +536,10 @@ function f(...) return ... end
>>   call f({'k2': 'v2', 'k1': 'v1'})
>>   ---
>>   - {'k2': 'v2', 'k1': 'v1'}
>> -eval (return space:auto_increment({"transaction"}))()
>> +eval (return space:auto_increment({'transaction'}))()
>>   ---
>>   - [1, 'transaction']
>> -function f(...) return space:auto_increment({"transaction"}) end
>> +function f(...) return space:auto_increment({'transaction'}) end
> 6. This whole file is Lua output. Why is it changed?

Same as in answer to the previous comment. Using single quote inside 
double quotes.

Relevant part of code:

  # Transactions
-test('space:auto_increment({"transaction"})')
-test('space:select{}')
-test('box.begin(), space:auto_increment({"failed"}), box.rollback()')
-test('space:select{}')
-test('require("fiber").sleep(0)')
+test("space:auto_increment({'transaction'})")
+test("space:select{}")
+test("box.begin(), space:auto_increment({'failed'}), box.rollback()")
+test("space:select{}")
+test("require('fiber').sleep(0)")

>>   ---
>>   ...
>>   call f()
>> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>> index cdd1a71c5..5eccd40d3 100644
>> --- a/test/box-py/iproto.test.py
>> +++ b/test/box-py/iproto.test.py
>> @@ -11,46 +13,42 @@ from lib.tarantool_connection import TarantoolConnection
>>   
>>   admin("box.schema.user.grant('guest', 'read,write,execute', 'universe')")
>>   
>> -print """
>> -#
>> -# iproto packages test
>> -#
>> -"""
>> +print("#")
>> +print("# iproto packages test")
>> +print("#")
>>   
>> -# opeing new connection to tarantool/box
>> +# opening new connection to tarantool/box
>>   conn = TarantoolConnection(server.iproto.host, server.iproto.port)
>>   conn.connect()
>>   s = conn.socket
>>   
>> -print """
>> -# Test bug #899343 (server assertion failure on incorrect packet)
>> -"""
>> -print "# send the package with invalid length"
>> -invalid_request = struct.pack('<LLL', 1, 4294967290, 1)
>> -print s.send(invalid_request)
>> -print "# check that is server alive"
>> -print iproto.py_con.ping() > 0
>> +print("# Test bug #899343 (server assertion failure on incorrect packet)")
>> +print("# send the package with invalid length")
>> +invalid_request = struct.pack("<LLL", 1, 4294967290, 1)
>> +print(s.send(invalid_request))
>> +print("# check that is server alive")
>> +print(iproto.py_con.ping() > 0)
>>   
>>   # closing connection
>>   s.close()
>>   
>>   key_names = {}
>> -for (k,v) in globals().items():
>> -    if type(k) == str and k.startswith('IPROTO_') and type(v) == int:
>> +for (k,v) in list(globals().items()):
> 7. Why did you add list() call? I don't see in the commit
> message any mentioning of why is it bad to use items() without
> list(). The same below.

To fix exceptions when Python 3 used:

[006]   File "box-py/iproto.test.py", line 40, in <module>
[006]     for (k,v) in globals().items():
[006] RuntimeError: dictionary changed size during iteration

>
> I suspect this has something to do with the second commit,
> and therefore belongs to it.
Right, moved to a separate commit.
>
>> +    if type(k) == str and k.startswith("IPROTO_") and type(v) == int:
>>           key_names[v] = k
>> @@ -59,36 +57,34 @@ def test(header, body):
>>       try:
>>           s.send(query)
>>       except OSError as e:
>> -        print '   => ', 'Failed to send request'
>> +        print("   => ", "Failed to send request")
>>       c.close()
>> -    print iproto.py_con.ping() > 0
>> +    print(iproto.py_con.ping() > 0)
>>   
>> -print """
>> -#  Test gh-206 "Segfault if sending IPROTO package without `KEY` field"
>> -"""
>> +print("#  Test gh-206 'Segfault if sending IPROTO package without `KEY` field'")
> 8. You changed the output. Previously it had one empty line before and
> after the text. The same in some other places in this commit. No .result
> files should be changed.
>
>> diff --git a/test/replication-py/cluster.test.py b/test/replication-py/cluster.test.py
>> index 088ca9c34..c770a9bc9 100644
>> --- a/test/replication-py/cluster.test.py
>> +++ b/test/replication-py/cluster.test.py
>> @@ -27,56 +29,59 @@ replica_uuid = str(uuid.uuid4())
>>   
>>   ## Universal read permission is required to perform JOIN/SUBSCRIBE
>>   rows = list(server.iproto.py_con.join(replica_uuid))
>> -print len(rows) == 1 and rows[0].return_message.find('Read access') >= 0 and \
>> -    'ok' or 'not ok', '-', 'join without read permissions on universe'
>> +status = len(rows) == 1 	clge.find("Read access") >= 0 and \
>> +        "ok" or "not ok"
> 9. I see, that at least in this file the indentation step is 4
> symbols. Why did you change it to 8?

reverted indentation here and in two lines below:

--- a/test/replication-py/cluster.test.py
+++ b/test/replication-py/cluster.test.py
@@ -30,18 +30,18 @@ replica_uuid = str(uuid.uuid4())
  ## Universal read permission is required to perform JOIN/SUBSCRIBE
  rows = list(server.iproto.py_con.join(replica_uuid))
  status = len(rows) == 1 and rows[0].return_message.find("Read access") 
 >= 0 and \
-        "ok" or "not ok"
+    "ok" or "not ok"
  print("{} - join without read permissions on universe".format(status))
  rows = list(server.iproto.py_con.subscribe(cluster_uuid, replica_uuid))
  status = len(rows) == 1 and rows[0].return_message.find("Read access") 
 >= 0 and \
-        "ok" or "not ok"
+    "ok" or "not ok"
  print("{} - subscribe without read permissions on 
universe".format(status))
  ## Write permission to space `_cluster` is required to perform JOIN
  server.admin("box.schema.user.grant('guest', 'read', 'universe')")
  server.iproto.reconnect() # re-connect with new permissions
  rows = list(server.iproto.py_con.join(replica_uuid))
  status = len(rows) == 1 and rows[0].return_message.find("Write 
access") >= 0 and \
-        "ok" or "not ok"
+    "ok" or "not ok"
  print("{} - join without write permissions to _cluster".format(status))

  def check_join(msg):

>
>> +print("{} - join without read permissions on universe".format(status))
>>   rows = list(server.iproto.py_con.subscribe(cluster_uuid, replica_uuid))
>> -print len(rows) == 1 and rows[0].return_message.find('Read access') >= 0 and \
>> -    'ok' or 'not ok', '-', 'subscribe without read permissions on universe'
>> +status = len(rows) == 1 and rows[0].return_message.find("Read access") >= 0 and \
>> +        "ok" or "not ok"
>> +print("{} - subscribe without read permissions on universe".format(status))
>>   ## Write permission to space `_cluster` is required to perform JOIN
>>   server.admin("box.schema.user.grant('guest', 'read', 'universe')")
>>   server.iproto.reconnect() # re-connect with new permissions
>>   rows = list(server.iproto.py_con.join(replica_uuid))
>> -print len(rows) == 1 and rows[0].return_message.find('Write access') >= 0 and \
>> -    'ok' or 'not ok', '-', 'join without write permissions to _cluster'
>> +status = len(rows) == 1 and rows[0].return_message.find("Write access") >= 0 and \
>> +        "ok" or "not ok"> @@ -235,16 +240,16 @@ try:
>>   except Exception as e:
>>       line = "ER_READONLY"
>>       if failed.logfile_pos.seek_once(line) >= 0:
>> -        print "'%s' exists in server log" % line
>> +        print("\'{}\' exists in server log".format(line))
> 10. You don't need to escape ' when they are inside of ".
--- a/test/replication-py/cluster.test.py
+++ b/test/replication-py/cluster.test.py
@@ -240,7 +240,7 @@ try:
  except Exception as e:
      line = "ER_READONLY"
      if failed.logfile_pos.seek_once(line) >= 0:
-        print("\'{}\' exists in server log".format(line))
+        print("'{}' exists in server log".format(line))

  master.admin("box.cfg { read_only = false }")
>
>> -master.admin('box.cfg { read_only = false }')
>> +master.admin("box.cfg { read_only = false }")
>>   
>> -print '-------------------------------------------------------------'
>> -print 'JOIN replica with different replica set UUID'
>> -print '-------------------------------------------------------------'
>> +print("-------------------------------------------------------------")
>> +print("JOIN replica with different replica set UUID")
>> +print("-------------------------------------------------------------")
>>   
>>   failed = TarantoolServer(server.ini)
>> -failed.script = 'replication-py/uuid_mismatch.lua'
>> +failed.script = "replication-py/uuid_mismatch.lua"
>>   failed.vardir = server.vardir
>>   failed.rpl_master = master
>>   failed.name = "uuid_mismatch"
>> @@ -254,15 +259,15 @@ try:
>>   except Exception as e:
>>       line = "ER_REPLICASET_UUID_MISMATCH"
>>       if failed.logfile_pos.seek_once(line) >= 0:
>> -        print "'%s' exists in server log" % line
>> +        print("\'{}\' exists in server log".format(line))
> 11. You don't need to escape ' when they are inside of ".

Right.

@@ -259,7 +259,7 @@ try:
  except Exception as e:
      line = "ER_REPLICASET_UUID_MISMATCH"
      if failed.logfile_pos.seek_once(line) >= 0:
-        print("\'{}\' exists in server log".format(line))
+        print("'{}' exists in server log".format(line))

  failed.cleanup()

>
> 12. There is also one place, where you removed an empty line in the
> end of file. I can't find it again, but it belongs to the last
> commit. Please, move it.

Done, it was xlog-py/dup_key.test.py.


1. 
https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021323.html

2. 
https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021044.html

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
  2020-12-14 11:44     ` Sergey Bronnikov
@ 2020-12-15 10:05       ` Leonid Vasiliev
  2020-12-15 11:51         ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-15 10:05 UTC (permalink / raw)
  To: Sergey Bronnikov, Vladislav Shpilevoy, tarantool-patches
  Cc: alexander.turenko

Hi! I looked at the commit 1f34abf6e059532ddfa097e4c1a86030d34341a9 on
the branch, because not all the diff has been attached here (or I can't
find them).
Not all multi-line prints were reverted. Let's finish the revert.
As for the rest of the changes:"I think this patch can be considered
complete." (LGTM)


On 14.12.2020 14:44, Sergey Bronnikov via Tarantool-patches wrote:
> Hello,
> 
> thanks for review!
> 
> On 13.12.2020 20:58, Vladislav Shpilevoy wrote:
>> Hi! Thanks for the patch!
>>
>> Finally, http_client.test.lua works on my machine.
>>
>> I don't see the cover letter, with issue and branch links.
>> I assume the branch is ligurio/gh-5538-support-python3.
> 
> Yep, it's a right branch. Cover letter is here [1], first time it was 
> send without ML address.
> 
>> See 12 minor comments below.
>>
>> On 11.12.2020 09:42, Sergey Bronnikov via Tarantool-patches wrote:
>>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>>
>>> - convert print statement to function. In a Python 3 'print' becomes a
>>> function, see [1]. Patch makes 'print' in a regression tests 
>>> compatible with
>>> Python 3.
>>> - according to PEP8, mixing using double quotes and quotes in a 
>>> project looks
>>> inconsistent. Patch makes using quotes with strings consistent.> - 
>>> print multiline strings with multiple print()
>> 1. Why? Is it according to PEP too? The same for '%'.
>> What is wrong with using multiline strings?
> 
> On first iteration I have converted print statements to functions as it 
> is required by Python 3.
> 
> Leonid asked me to fix code style of strings too and I did it on second 
> iteration, see conversation here [2].
> 
> Nothing wrong with multi-line prints, but for my taste it looks ugly.
> 
> I don't want to have yet another conversation about code style, if you 
> are happy with multi-line strings in print - it's fine.
> 
> So I reverted changes related to multi-line strings because the main 
> purpose of the series is Python 3 support.
> 
>>
>>> - use "format()" instead of "%" everywhere
>>> 1. https://docs.python.org/3/whatsnew/3.0.html#print-is-a-function
>>>
>>> Part of #5538
>>> ---
>>> diff --git a/test/box-py/args.test.py b/test/box-py/args.test.py
>>> index c0fac9038..f1b840a85 100644
>>> --- a/test/box-py/args.test.py
>>> +++ b/test/box-py/args.test.py
>>> @@ -1,3 +1,5 @@
>>> +from __future__ import print_function
>> 2. In this file I don't see you changing 'print' to 'print()'
>> anywhere. So why is this line needed? In this file I only see
>> "print" as a part of strings. As a word. Not as a function.
> You are right. Removed import and force-pushed.
>>
>>> +
>>>   import sys
>>>   import os
>>>   import re
>>> diff --git a/test/box-py/bad_trigger.result 
>>> b/test/box-py/bad_trigger.result
>>> index 5d064b764..42cd9a7e8 100644
>>> --- a/test/box-py/bad_trigger.result
>>> +++ b/test/box-py/bad_trigger.result
>>> @@ -1,8 +1,6 @@
>>> -
>>>    #
>>>    # if on_connect() trigger raises an exception, the connection is 
>>> dropped
>>>    #
>>> -
>> 3. Why is this file changed? It is .result file. Your changes are just
>> refactoring, so no .result files should be changed.
> Added newlines.
>>
>>>   nosuchfunction = nil
>>>   ---
>>>   ...
>>> diff --git a/test/box-py/bad_trigger.test.py 
>>> b/test/box-py/bad_trigger.test.py
>>> index 7d200b921..789fe8045 100644
>>> --- a/test/box-py/bad_trigger.test.py
>>> +++ b/test/box-py/bad_trigger.test.py
>>> @@ -24,12 +24,12 @@ conn.connect()
>>>   s = conn.socket
>>>   # Read greeting
>>> -print 'greeting: ', len(s.recv(IPROTO_GREETING_SIZE)) == 
>>> IPROTO_GREETING_SIZE
>>> +print("greeting:  {}".format(len(s.recv(IPROTO_GREETING_SIZE)) == 
>>> IPROTO_GREETING_SIZE))
>>>   # Read error packet
>>>   IPROTO_FIXHEADER_SIZE = 5
>>>   fixheader = s.recv(IPROTO_FIXHEADER_SIZE)
>>> -print 'fixheader: ', len(fixheader) == IPROTO_FIXHEADER_SIZE
>>> +print("fixheader:  {}".format(len(fixheader) == IPROTO_FIXHEADER_SIZE))
>> 4. There was a single whitespace. You made it double. Why? The
>> same for the change above. And in one place below.
> 
> Python2 print automatically adds a whitespace before an argument:
> 
> Python 2.7.18 (default, Aug  4 2020, 11:16:42)
> [GCC 9.3.0] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>  >>> print "X", 3
> X 3
>  >>> from __future__ import print_function
>  >>> print("X{}".format(3))
> X3
>  >>>
> 
> To produce same output as in a .result file additional whitespace has 
> been added in a code.
> 
>>
>>>   unpacker.feed(fixheader)
>>>   packet_len = unpacker.unpack()
>>>   packet = s.recv(packet_len)
>>> @@ -38,9 +38,9 @@ unpacker.feed(packet)
>>>   # Parse packet
>>>   header = unpacker.unpack()
>>>   body = unpacker.unpack()
>>> -print 'error code', (header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))
>>> -print 'error message: ', body[IPROTO_ERROR]
>>> -print 'eof:', len(s.recv(1024)) == 0
>>> +print("error code {}".format((header[IPROTO_CODE] & 
>>> (REQUEST_TYPE_ERROR - 1))))
>>> +print("error message:  {}".format(body[IPROTO_ERROR]))
>>> +print("eof: {}".format(len(s.recv(1024)) == 0))
>>>   s.close()
>>>   server.admin("box.session.on_connect(nil, f1)")
>>> diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
>>> index 0876e77a6..865302698 100644
>>> --- a/test/box-py/bootstrap.result
>>> +++ b/test/box-py/bootstrap.result
>>> @@ -165,7 +165,7 @@ box.space._user:select{}
>>>     - [3, 1, 'replication', 'role', {}]
>>>     - [31, 1, 'super', 'role', {}]
>>>   ...
>>> -for _, v in box.space._func:pairs{} do r = {} table.insert(r, 
>>> v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end
>>> +for _, v in box.space._func:pairs{} do r = {} table.insert(r, 
>>> v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end
>> 5. This is Lua. Not python. Why did you change it?
> 
> I just made using quotes consistent in a Python code. Outer quotes are 
> double quote and internal quote is a single one.
> 
> --- a/test/box-py/bootstrap.test.py
> +++ b/test/box-py/bootstrap.test.py
> @@ -1,11 +1,11 @@
> -server.admin('box.internal.bootstrap()')
> -server.admin('box.space._schema:select{}')
> -server.admin('box.space._cluster:select{}')
> -server.admin('box.space._space:select{}')
> -server.admin('box.space._index:select{}')
> -server.admin('box.space._user:select{}')
> -server.admin('for _, v in box.space._func:pairs{} do r = {} 
> table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end')
> -server.admin('box.space._priv:select{}')
> +server.admin("box.internal.bootstrap()")
> +server.admin("box.space._schema:select{}")
> +server.admin("box.space._cluster:select{}")
> +server.admin("box.space._space:select{}")
> +server.admin("box.space._index:select{}")
> +server.admin("box.space._user:select{}")
> +server.admin("for _, v in box.space._func:pairs{} do r = {} 
> table.insert(r, v:update({{'=', 18, ''}, {'=', 19, ''}})) return r end")
> +server.admin("box.space._priv:select{}")
> 
>   # Cleanup
>   server.stop()
> 
>>
>>>   ---
>>>   - - [1, 1, 'box.schema.user.info', 1, 'LUA', '', 'function', [], 
>>> 'any', 'none', 'none',
>>>       false, false, true, ['LUA'], {}, '', '', '']
>>> diff --git a/test/box-py/call.result b/test/box-py/call.result
>>> index d340ed6fa..e6b7b8dc9 100644
>>> --- a/test/box-py/call.result
>>> +++ b/test/box-py/call.result
>>> @@ -536,10 +536,10 @@ function f(...) return ... end
>>>   call f({'k2': 'v2', 'k1': 'v1'})
>>>   ---
>>>   - {'k2': 'v2', 'k1': 'v1'}
>>> -eval (return space:auto_increment({"transaction"}))()
>>> +eval (return space:auto_increment({'transaction'}))()
>>>   ---
>>>   - [1, 'transaction']
>>> -function f(...) return space:auto_increment({"transaction"}) end
>>> +function f(...) return space:auto_increment({'transaction'}) end
>> 6. This whole file is Lua output. Why is it changed?
> 
> Same as in answer to the previous comment. Using single quote inside 
> double quotes.
> 
> Relevant part of code:
> 
>   # Transactions
> -test('space:auto_increment({"transaction"})')
> -test('space:select{}')
> -test('box.begin(), space:auto_increment({"failed"}), box.rollback()')
> -test('space:select{}')
> -test('require("fiber").sleep(0)')
> +test("space:auto_increment({'transaction'})")
> +test("space:select{}")
> +test("box.begin(), space:auto_increment({'failed'}), box.rollback()")
> +test("space:select{}")
> +test("require('fiber').sleep(0)")
> 
>>>   ---
>>>   ...
>>>   call f()
>>> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>>> index cdd1a71c5..5eccd40d3 100644
>>> --- a/test/box-py/iproto.test.py
>>> +++ b/test/box-py/iproto.test.py
>>> @@ -11,46 +13,42 @@ from lib.tarantool_connection import 
>>> TarantoolConnection
>>>   admin("box.schema.user.grant('guest', 'read,write,execute', 
>>> 'universe')")
>>> -print """
>>> -#
>>> -# iproto packages test
>>> -#
>>> -"""
>>> +print("#")
>>> +print("# iproto packages test")
>>> +print("#")
>>> -# opeing new connection to tarantool/box
>>> +# opening new connection to tarantool/box
>>>   conn = TarantoolConnection(server.iproto.host, server.iproto.port)
>>>   conn.connect()
>>>   s = conn.socket
>>> -print """
>>> -# Test bug #899343 (server assertion failure on incorrect packet)
>>> -"""
>>> -print "# send the package with invalid length"
>>> -invalid_request = struct.pack('<LLL', 1, 4294967290, 1)
>>> -print s.send(invalid_request)
>>> -print "# check that is server alive"
>>> -print iproto.py_con.ping() > 0
>>> +print("# Test bug #899343 (server assertion failure on incorrect 
>>> packet)")
>>> +print("# send the package with invalid length")
>>> +invalid_request = struct.pack("<LLL", 1, 4294967290, 1)
>>> +print(s.send(invalid_request))
>>> +print("# check that is server alive")
>>> +print(iproto.py_con.ping() > 0)
>>>   # closing connection
>>>   s.close()
>>>   key_names = {}
>>> -for (k,v) in globals().items():
>>> -    if type(k) == str and k.startswith('IPROTO_') and type(v) == int:
>>> +for (k,v) in list(globals().items()):
>> 7. Why did you add list() call? I don't see in the commit
>> message any mentioning of why is it bad to use items() without
>> list(). The same below.
> 
> To fix exceptions when Python 3 used:
> 
> [006]   File "box-py/iproto.test.py", line 40, in <module>
> [006]     for (k,v) in globals().items():
> [006] RuntimeError: dictionary changed size during iteration
> 
>>
>> I suspect this has something to do with the second commit,
>> and therefore belongs to it.
> Right, moved to a separate commit.
>>
>>> +    if type(k) == str and k.startswith("IPROTO_") and type(v) == int:
>>>           key_names[v] = k
>>> @@ -59,36 +57,34 @@ def test(header, body):
>>>       try:
>>>           s.send(query)
>>>       except OSError as e:
>>> -        print '   => ', 'Failed to send request'
>>> +        print("   => ", "Failed to send request")
>>>       c.close()
>>> -    print iproto.py_con.ping() > 0
>>> +    print(iproto.py_con.ping() > 0)
>>> -print """
>>> -#  Test gh-206 "Segfault if sending IPROTO package without `KEY` field"
>>> -"""
>>> +print("#  Test gh-206 'Segfault if sending IPROTO package without 
>>> `KEY` field'")
>> 8. You changed the output. Previously it had one empty line before and
>> after the text. The same in some other places in this commit. No .result
>> files should be changed.
>>
>>> diff --git a/test/replication-py/cluster.test.py 
>>> b/test/replication-py/cluster.test.py
>>> index 088ca9c34..c770a9bc9 100644
>>> --- a/test/replication-py/cluster.test.py
>>> +++ b/test/replication-py/cluster.test.py
>>> @@ -27,56 +29,59 @@ replica_uuid = str(uuid.uuid4())
>>>   ## Universal read permission is required to perform JOIN/SUBSCRIBE
>>>   rows = list(server.iproto.py_con.join(replica_uuid))
>>> -print len(rows) == 1 and rows[0].return_message.find('Read access') 
>>> >= 0 and \
>>> -    'ok' or 'not ok', '-', 'join without read permissions on universe'
>>> +status = len(rows) == 1     clge.find("Read access") >= 0 and \
>>> +        "ok" or "not ok"
>> 9. I see, that at least in this file the indentation step is 4
>> symbols. Why did you change it to 8?
> 
> reverted indentation here and in two lines below:
> 
> --- a/test/replication-py/cluster.test.py
> +++ b/test/replication-py/cluster.test.py
> @@ -30,18 +30,18 @@ replica_uuid = str(uuid.uuid4())
>   ## Universal read permission is required to perform JOIN/SUBSCRIBE
>   rows = list(server.iproto.py_con.join(replica_uuid))
>   status = len(rows) == 1 and rows[0].return_message.find("Read access") 
>  >= 0 and \
> -        "ok" or "not ok"
> +    "ok" or "not ok"
>   print("{} - join without read permissions on universe".format(status))
>   rows = list(server.iproto.py_con.subscribe(cluster_uuid, replica_uuid))
>   status = len(rows) == 1 and rows[0].return_message.find("Read access") 
>  >= 0 and \
> -        "ok" or "not ok"
> +    "ok" or "not ok"
>   print("{} - subscribe without read permissions on 
> universe".format(status))
>   ## Write permission to space `_cluster` is required to perform JOIN
>   server.admin("box.schema.user.grant('guest', 'read', 'universe')")
>   server.iproto.reconnect() # re-connect with new permissions
>   rows = list(server.iproto.py_con.join(replica_uuid))
>   status = len(rows) == 1 and rows[0].return_message.find("Write 
> access") >= 0 and \
> -        "ok" or "not ok"
> +    "ok" or "not ok"
>   print("{} - join without write permissions to _cluster".format(status))
> 
>   def check_join(msg):
> 
>>
>>> +print("{} - join without read permissions on universe".format(status))
>>>   rows = list(server.iproto.py_con.subscribe(cluster_uuid, 
>>> replica_uuid))
>>> -print len(rows) == 1 and rows[0].return_message.find('Read access') 
>>> >= 0 and \
>>> -    'ok' or 'not ok', '-', 'subscribe without read permissions on 
>>> universe'
>>> +status = len(rows) == 1 and rows[0].return_message.find("Read 
>>> access") >= 0 and \
>>> +        "ok" or "not ok"
>>> +print("{} - subscribe without read permissions on 
>>> universe".format(status))
>>>   ## Write permission to space `_cluster` is required to perform JOIN
>>>   server.admin("box.schema.user.grant('guest', 'read', 'universe')")
>>>   server.iproto.reconnect() # re-connect with new permissions
>>>   rows = list(server.iproto.py_con.join(replica_uuid))
>>> -print len(rows) == 1 and rows[0].return_message.find('Write access') 
>>> >= 0 and \
>>> -    'ok' or 'not ok', '-', 'join without write permissions to _cluster'
>>> +status = len(rows) == 1 and rows[0].return_message.find("Write 
>>> access") >= 0 and \
>>> +        "ok" or "not ok"> @@ -235,16 +240,16 @@ try:
>>>   except Exception as e:
>>>       line = "ER_READONLY"
>>>       if failed.logfile_pos.seek_once(line) >= 0:
>>> -        print "'%s' exists in server log" % line
>>> +        print("\'{}\' exists in server log".format(line))
>> 10. You don't need to escape ' when they are inside of ".
> --- a/test/replication-py/cluster.test.py
> +++ b/test/replication-py/cluster.test.py
> @@ -240,7 +240,7 @@ try:
>   except Exception as e:
>       line = "ER_READONLY"
>       if failed.logfile_pos.seek_once(line) >= 0:
> -        print("\'{}\' exists in server log".format(line))
> +        print("'{}' exists in server log".format(line))
> 
>   master.admin("box.cfg { read_only = false }")
>>
>>> -master.admin('box.cfg { read_only = false }')
>>> +master.admin("box.cfg { read_only = false }")
>>> -print '-------------------------------------------------------------'
>>> -print 'JOIN replica with different replica set UUID'
>>> -print '-------------------------------------------------------------'
>>> +print("-------------------------------------------------------------")
>>> +print("JOIN replica with different replica set UUID")
>>> +print("-------------------------------------------------------------")
>>>   failed = TarantoolServer(server.ini)
>>> -failed.script = 'replication-py/uuid_mismatch.lua'
>>> +failed.script = "replication-py/uuid_mismatch.lua"
>>>   failed.vardir = server.vardir
>>>   failed.rpl_master = master
>>>   failed.name = "uuid_mismatch"
>>> @@ -254,15 +259,15 @@ try:
>>>   except Exception as e:
>>>       line = "ER_REPLICASET_UUID_MISMATCH"
>>>       if failed.logfile_pos.seek_once(line) >= 0:
>>> -        print "'%s' exists in server log" % line
>>> +        print("\'{}\' exists in server log".format(line))
>> 11. You don't need to escape ' when they are inside of ".
> 
> Right.
> 
> @@ -259,7 +259,7 @@ try:
>   except Exception as e:
>       line = "ER_REPLICASET_UUID_MISMATCH"
>       if failed.logfile_pos.seek_once(line) >= 0:
> -        print("\'{}\' exists in server log".format(line))
> +        print("'{}' exists in server log".format(line))
> 
>   failed.cleanup()
> 
>>
>> 12. There is also one place, where you removed an empty line in the
>> end of file. I can't find it again, but it belongs to the last
>> commit. Please, move it.
> 
> Done, it was xlog-py/dup_key.test.py.
> 
> 
> 1. 
> https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021323.html 
> 
> 
> 2. 
> https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021044.html 
> 
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
  2020-12-15 10:05       ` Leonid Vasiliev
@ 2020-12-15 11:51         ` Sergey Bronnikov
  2020-12-20 16:47           ` Vladislav Shpilevoy
  0 siblings, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-15 11:51 UTC (permalink / raw)
  To: Leonid Vasiliev, Vladislav Shpilevoy, tarantool-patches; +Cc: alexander.turenko

Hello,

thanks for review!

On 15.12.2020 13:05, Leonid Vasiliev wrote:
> Hi! I looked at the commit 1f34abf6e059532ddfa097e4c1a86030d34341a9 on
> the branch, because not all the diff has been attached here (or I can't
> find them).
> Not all multi-line prints were reverted. Let's finish the revert.
> As for the rest of the changes:"I think this patch can be considered
> complete." (LGTM)
>
>
Yep, there were some places. Reverted and force-pushed. CI is green [1].

1. https://gitlab.com/tarantool/tarantool/-/pipelines/230020600


diff --git a/test/box-py/call.test.py b/test/box-py/call.test.py
index 75ced1dff..9f508268d 100644
--- a/test/box-py/call.test.py
+++ b/test/box-py/call.test.py
@@ -23,11 +23,11 @@ call("f1")
  # IPROTO required!
  call("box.error", 33333, "Hey!")

-print("")
-print("# A test case for Bug#103491")
-print("# server CALL processing bug with name path longer than two")
-print("# https://bugs.launchpad.net/tarantool/+bug/1034912")
-print("")
+print("""
+# A test case for Bug#103491
+# server CALL processing bug with name path longer than two
+# https://bugs.launchpad.net/tarantool/+bug/1034912
+""")
  admin("f = function() return 'OK' end")
  admin("test = {}")
  admin("test.f = f")
@@ -37,11 +37,11 @@ call("f")
  call("test.f")
  call("test.test.f")

-print("")
-print("# Test for Bug #955226")
-print("# Lua Numbers are passed back wrongly as strings")
-print("#")
-print("")
+print("""
+# Test for Bug #955226
+# Lua Numbers are passed back wrongly as strings
+#
+""")
  admin("function foo() return 1, 2, '1', '2' end")
  call("foo")

diff --git a/test/box-py/snapshot.result b/test/box-py/snapshot.result
index 034f0bba7..fbaab912f 100644
--- a/test/box-py/snapshot.result
+++ b/test/box-py/snapshot.result
@@ -44,7 +44,7 @@ space:delete{2}
  ...
  #
  # A test case for http://bugs.launchpad.net/bugs/727174
-# 'tarantool_box crashes when saving snapshot on SIGUSR1'
+# "tarantool_box crashes when saving snapshot on SIGUSR1"
  #

  # Increment the lsn number, to make sure there is no such snapshot yet

diff --git a/test/box-py/snapshot.test.py b/test/box-py/snapshot.test.py
index 7d660d9bf..e34126ed2 100644
--- a/test/box-py/snapshot.test.py
+++ b/test/box-py/snapshot.test.py
@@ -41,13 +41,14 @@ os.rmdir(snapshot)
  admin("space:delete{1}")
  admin("space:delete{2}")

-print("#")
-print("# A test case for http://bugs.launchpad.net/bugs/727174")
-print("# 'tarantool_box crashes when saving snapshot on SIGUSR1'")
-print("#\n")
+print("""#
+# A test case for http://bugs.launchpad.net/bugs/727174
+# "tarantool_box crashes when saving snapshot on SIGUSR1"
+#""")

-print("# Increment the lsn number, to make sure there is no such 
snapshot yet")
-print("#")
+print("""
+# Increment the lsn number, to make sure there is no such snapshot yet
+#""")

  admin("space:insert{1, 'Test tuple'}")

diff --git a/test/xlog-py/misc.test.py b/test/xlog-py/misc.test.py
index 3fcda9504..3330a8e57 100644
--- a/test/xlog-py/misc.test.py
+++ b/test/xlog-py/misc.test.py
@@ -13,9 +13,9 @@ server.stop()

  data_path = os.path.join(server.vardir, server.name)

-print("")
-print("# xlog file must exist after inserts.")
-print("")
+print("""
+# xlog file must exist after inserts.
+""")
  filename = str(lsn).zfill(20) + ".xlog"
  wal = os.path.join(data_path, filename)

@@ -30,9 +30,9 @@ server.admin("index = space:create_index('primary', { 
type = 'hash' })")
  server.stop()
  lsn += 2

-print("")
-print("# a new xlog must be opened after regular termination.")
-print("")
+print("""
+# a new xlog must be opened after regular termination.
+""")
  filename = str(lsn).zfill(20) + ".xlog"
  server.start()

@@ -49,9 +49,10 @@ if os.access(wal, os.F_OK):
    print(".xlog stays around after shutdown")
  lsn += 1

-print("")
-print("# An xlog file with one record during recovery.")
-print("")
+print("""
+# An xlog file with one record during recovery.
+""")
+
  server.start()
  filename = str(lsn).zfill(20) + ".xlog"
  wal = os.path.join(data_path, filename)

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex " sergeyb
@ 2020-12-15 11:55   ` Leonid Vasiliev
  2020-12-16 14:04     ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-15 11:55 UTC (permalink / raw)
  To: sergeyb, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hi! Thank you for the patch.

On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
> 
> Part of #5538
> ---
>   test/box-py/iproto.test.py | 6 +++++-
>   1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
> index 25ead43c4..72400923c 100644
> --- a/test/box-py/iproto.test.py
> +++ b/test/box-py/iproto.test.pyHi
> @@ -191,7 +191,11 @@ for test in TESTS:
>       print("STR", size)
>       print("--")
>       for fmt in it:
> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
> +        try:
> +            # Python 3
> +            print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")

Maybe fmt.encode("utf-8").hex()?
Please, add a comment that describing the difference between python2 and
python3 in this print.

> +        except AttributeError:
> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>           field = "*" * size
>           c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
>           tuple = space.select(field)[0]
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x sergeyb
  2020-12-13 17:58   ` Vladislav Shpilevoy
@ 2020-12-15 12:40   ` Leonid Vasiliev
  1 sibling, 0 replies; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-15 12:40 UTC (permalink / raw)
  To: sergeyb, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hi! Thank you for the patch.
Current patch(AFAIU):

test: make dict.items() compatible with Python 3.x

In Python 2.x calling items() makes a copy of the keys that you can iterate
over while modifying the dict. This doesn't work in Python 3.x because 
items()
returns an iterator instead of a list and Python 3 raise an exception
     "dictionary changed size during iteration". To workaround it one 
can use list
to force a copy of the keys to be made.

Part of #5538

f9ecd7a22fcb148c60867e7d1fcd02b1a6fda9fc
  test/box-py/iproto.test.py | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
index 6ed4905..6723e03 100644
--- a/test/box-py/iproto.test.py
+++ b/test/box-py/iproto.test.py
@@ -37,7 +37,7 @@ print(iproto.py_con.ping() > 0)
  s.close()

  key_names = {}
-for (k,v) in globals().items():
+for (k,v) in list(globals().items()):
      if type(k) == str and k.startswith("IPROTO_") and type(v) == int:
          key_names[v] = k


if I understand correctly- LGTM.

On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
> 
> In Python 2.x calling keys makes a copy of the key that you can iterate over
> while modifying the dict. This doesn't work in Python 3.x because keys returns
> an iterator instead of a list. Python 3 raise an exception "dictionary changed
> size during iteration". To workaround it one can use list to force a copy of
> the keys to be made.
> 
> Part of #5538
> ---
>   test/box-py/iproto.test.py | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
> index 5eccd40d3..25ead43c4 100644
> --- a/test/box-py/iproto.test.py
> +++ b/test/box-py/iproto.test.py
> @@ -39,7 +39,7 @@ for (k,v) in list(globals().items()):
>   
>   def repr_dict(todump):
>       d = {}
> -    for (k, v) in list(todump.items()):
> +    for (k, v) in todump.items():
>           k_name = key_names.get(k, k)
>           d[k_name] = v
>       return repr(d)
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline
  2020-12-11  8:42 ` [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline sergeyb
@ 2020-12-15 12:51   ` Leonid Vasiliev
  2020-12-15 13:00     ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-15 12:51 UTC (permalink / raw)
  To: sergeyb, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hi! Thank you for the patch.
Generally LGTM.
Look one commit below:

On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
> 
> Closes #5538
> ---
>   test/replication-py/init_storage.test.py | 6 +++---
>   test/replication-py/swap.test.py         | 9 +--------
>   test/xlog-py/dup_key.test.py             | 5 -----
>   test/xlog-py/lsn_gap.test.py             | 1 -
>   4 files changed, 4 insertions(+), 17 deletions(-)
> 
> diff --git a/test/replication-py/init_storage.test.py b/test/replication-py/init_storage.test.py
> index 43ebc8afb..a6e2d6563 100644
> --- a/test/replication-py/init_storage.test.py
> +++ b/test/replication-py/init_storage.test.py
> @@ -21,7 +21,7 @@ master.admin("for k = 1, 9 do space:insert{k, k*k} end")
>   
>   replica = TarantoolServer(server.ini)
>   replica.script = "replication-py/replica.lua"
> -replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
> +replica.vardir = server.vardir
>   replica.rpl_master = master
>   replica.deploy()
>   replica.admin("box.space.test:select()")
> @@ -42,7 +42,7 @@ lsn = master.get_lsn(master_id)
>   
>   replica = TarantoolServer(server.ini)
>   replica.script = "replication-py/replica.lua"
> -replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
> +replica.vardir = server.vardir
>   replica.rpl_master = master
>   replica.deploy()
>   
> @@ -61,7 +61,7 @@ print("-------------------------------------------------------------")
>   server.stop()
>   replica = TarantoolServer(server.ini)
>   replica.script = "replication-py/replica.lua"
> -replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
> +replica.vardir = server.vardir
>   replica.rpl_master = master
>   replica.deploy(wait=False)
>   
> diff --git a/test/replication-py/swap.test.py b/test/replication-py/swap.test.py
> index b162ae241..ce1682641 100644
> --- a/test/replication-py/swap.test.py
> +++ b/test/replication-py/swap.test.py
> @@ -45,7 +45,7 @@ os.putenv("MASTER", master.uri)
>   # replica server
>   replica = TarantoolServer()
>   replica.script = "replication-py/replica.lua"
> -replica.vardir = server.vardir #os.path.join(server.vardir, 'replica')
> +replica.vardir = server.vardir
>   replica.deploy()
>   replica.admin("while box.info.id == 0 do require('fiber').sleep(0.01) end")
>   replica.uri = "{}:{}@{}".format(LOGIN, PASSWORD, replica.iproto.uri)
> @@ -56,13 +56,6 @@ for engine in engines:
>       master.admin("s = box.schema.space.create('{}', {{ engine = '{}'}})".format(engine, engine))
>       master.admin("index = s:create_index('primary', {type = 'tree'})")
>   
> -### gh-343: replica.cc must not add login and password to proc title
> -#status = replica.get_param("status")
> -#host_port = "%s:%s" % master.iproto.uri
> -#m = re.search(r'replica/(.*)/.*', status)
> -#if not m or m.group(1) != host_port:
> -#    print 'invalid box.info.status', status, 'expected host:port', host_port
> -
>   master_id = master.get_param("id")
>   replica_id = replica.get_param("id")
>   
> diff --git a/test/xlog-py/dup_key.test.py b/test/xlog-py/dup_key.test.py
> index b1442c520..a40133ef2 100644
> --- a/test/xlog-py/dup_key.test.py
> +++ b/test/xlog-py/dup_key.test.py
> @@ -3,11 +3,6 @@ from __future__ import print_function
>   import os
>   import yaml
>   
> -#print """
> -#A test case for https://bugs.launchpad.net/tarantool/+bug/1052018
> -#panic_on_wal_error doesn't work for duplicate key errors
> -#"""

Seems like
```
#A test case for https://bugs.launchpad.net/tarantool/+bug/1052018
#panic_on_wal_error doesn't work for duplicate key errors
```
can be left as a comment to the test (without `print`).

> -
>   server.stop()
>   server.deploy()
>   
> diff --git a/test/xlog-py/lsn_gap.test.py b/test/xlog-py/lsn_gap.test.py
> index 8da6166a2..b80b97146 100644
> --- a/test/xlog-py/lsn_gap.test.py
> +++ b/test/xlog-py/lsn_gap.test.py
> @@ -38,4 +38,3 @@ print("")
>   
>   # missing tuple from removed xlog
>   server.admin("box.space.test:select{}")
> -
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline
  2020-12-15 12:51   ` Leonid Vasiliev
@ 2020-12-15 13:00     ` Sergey Bronnikov
  0 siblings, 0 replies; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-15 13:00 UTC (permalink / raw)
  To: Leonid Vasiliev, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko


On 15.12.2020 15:51, Leonid Vasiliev wrote:
> Hi! Thank you for the patch.
> Generally LGTM.
> Look one commit below:
>
> On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>> <snipped>
>> index b1442c520..a40133ef2 100644
>> --- a/test/xlog-py/dup_key.test.py
>> +++ b/test/xlog-py/dup_key.test.py
>> @@ -3,11 +3,6 @@ from __future__ import print_function
>>   import os
>>   import yaml
>>   -#print """
>> -#A test case for https://bugs.launchpad.net/tarantool/+bug/1052018
>> -#panic_on_wal_error doesn't work for duplicate key errors
>> -#"""
>
> Seems like
> ```
> #A test case for https://bugs.launchpad.net/tarantool/+bug/1052018
> #panic_on_wal_error doesn't work for duplicate key errors
> ```
> can be left as a comment to the test (without `print`).

Agree.

--- a/test/xlog-py/dup_key.test.py
+++ b/test/xlog-py/dup_key.test.py
@@ -3,6 +3,9 @@ from __future__ import print_function
  import os
  import yaml

+# A test case for https://bugs.launchpad.net/tarantool/+bug/1052018
+# panic_on_wal_error doesn't work for duplicate key errors
+
  server.stop()
  server.deploy()

>
>> -
>>   server.stop()
>>   server.deploy()
>>   diff --git a/test/xlog-py/lsn_gap.test.py 
>> b/test/xlog-py/lsn_gap.test.py
>> index 8da6166a2..b80b97146 100644
>> --- a/test/xlog-py/lsn_gap.test.py
>> +++ b/test/xlog-py/lsn_gap.test.py
>> @@ -38,4 +38,3 @@ print("")
>>     # missing tuple from removed xlog
>>   server.admin("box.space.test:select{}")
>> -
>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x
  2020-12-15 11:55   ` Leonid Vasiliev
@ 2020-12-16 14:04     ` Sergey Bronnikov
  2020-12-17 18:26       ` Leonid Vasiliev
  0 siblings, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-16 14:04 UTC (permalink / raw)
  To: Leonid Vasiliev, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hello,


On 15.12.2020 14:55, Leonid Vasiliev wrote:
> Hi! Thank you for the patch.
>
> On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>
>> Part of #5538
>> ---
>>   test/box-py/iproto.test.py | 6 +++++-
>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>> index 25ead43c4..72400923c 100644
>> --- a/test/box-py/iproto.test.py
>> +++ b/test/box-py/iproto.test.pyHi
>> @@ -191,7 +191,11 @@ for test in TESTS:
>>       print("STR", size)
>>       print("--")
>>       for fmt in it:
>> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
>> +        try:
>> +            # Python 3
>> +            print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
>
> Maybe fmt.encode("utf-8").hex()?

I would be glad to use it in Python 3, but fmt module was removed there.


> Please, add a comment that describing the difference between python2 and
> python3 in this print.
>
Added comment to a commit message and force-pushed.
>> +        except AttributeError:
>> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>>           field = "*" * size
>>           c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
>>           tuple = space.select(field)[0]
>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x
  2020-12-16 14:04     ` Sergey Bronnikov
@ 2020-12-17 18:26       ` Leonid Vasiliev
  2020-12-22  8:15         ` [Tarantool-patches] [PATCH] test: make strings compatible with Python 3 sergeyb
  2020-12-22  8:19         ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x Sergey Bronnikov
  0 siblings, 2 replies; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-17 18:26 UTC (permalink / raw)
  To: Sergey Bronnikov, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hi!

On 16.12.2020 17:04, Sergey Bronnikov wrote:
> Hello,
> 
> 
> On 15.12.2020 14:55, Leonid Vasiliev wrote:
>> Hi! Thank you for the patch.
>>
>> On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
>>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>>
>>> Part of #5538
>>> ---
>>>   test/box-py/iproto.test.py | 6 +++++-
>>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>>> index 25ead43c4..72400923c 100644
>>> --- a/test/box-py/iproto.test.py
>>> +++ b/test/box-py/iproto.test.pyHi
>>> @@ -191,7 +191,11 @@ for test in TESTS:
>>>       print("STR", size)
>>>       print("--")
>>>       for fmt in it:
>>> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
>>> +        try:
>>> +            # Python 3
>>> +            print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
>>
>> Maybe fmt.encode("utf-8").hex()?
> 
> I would be glad to use it in Python 3, but fmt module was removed there.

Sorry, but I don't understand which module "fmt" you mean. I don't see
any `import fmt...` here. AFAIU `fmt` in this context is a string from
one of the tuples from the list `TESTS`.

So, I copy this hunk:
```
from __future__ import print_function

TESTS = [
     (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", "\xdb\x00\x00\x00\x01"),
     (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", "\xdb\x00\x00\x00\x1f"),
     (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
     (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
     (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
     (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
     (65536, "\xdb\x00\x01\x00\x00"),
]

for test in TESTS:
     it = iter(test)
     size = next(it)
     print("STR", size)
     print("--")
     for fmt in it:
         try:
             # Python 3
             print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
         except AttributeError:
             print("0x" + fmt.encode("hex"), "=>", end=" ")
         print()
     print()
```

and run it on python2 and python3.
Results doesn't look identically.

Python2:
```
┌─[leonid@vasya-L460]─[~/work/mail/tarantool/tmp]
└──╼ python2 test.py
STR 1
--
0xa1 =>
0xd901 =>
0xda0001 =>
0xdb00000001 =>

STR 31
--
0xbf =>
0xd91f =>
0xda001f =>
0xdb0000001f =>

STR 32
--
0xd920 =>
0xda0020 =>
0xdb00000020 =>

STR 255
--
0xd9ff =>
0xda00ff =>
0xdb000000ff =>

STR 256
--
0xda0100 =>
0xdb00000100 =>

STR 65535
--
0xdaffff =>
0xdb0000ffff =>

STR 65536
--
0xdb00010000 =>

```

Python3:
```
┌─[leonid@vasya-L460]─[~/work/mail/tarantool/tmp]
└──╼ python3 test.py
STR 1
--
0x686578 =>
0x686578 =>
0x686578 =>
0x686578 =>

STR 31
--
0x686578 =>
0x686578 =>
0x686578 =>
0x686578 =>

STR 32
--
0x686578 =>
0x686578 =>
0x686578 =>

STR 255
--
0x686578 =>
0x686578 =>
0x686578 =>

STR 256
--
0x686578 =>
0x686578 =>

STR 65535
--
0x686578 =>
0x686578 =>

STR 65536
--
0x686578 =>

```

Am I doing something wrong or a bug in the patch?

> 
> 
>> Please, add a comment that describing the difference between python2 and
>> python3 in this print.
>>
> Added comment to a commit message and force-pushed.
>>> +        except AttributeError:
>>> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>>>           field = "*" * size
>>>           c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
>>>           tuple = space.select(field)[0]
>>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
  2020-12-15 11:51         ` Sergey Bronnikov
@ 2020-12-20 16:47           ` Vladislav Shpilevoy
  2020-12-23 12:34             ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Vladislav Shpilevoy @ 2020-12-20 16:47 UTC (permalink / raw)
  To: Sergey Bronnikov, Leonid Vasiliev, tarantool-patches; +Cc: alexander.turenko

> @@ -38,9 +40,9 @@ unpacker.feed(packet)
>  # Parse packet
>  header = unpacker.unpack()
>  body = unpacker.unpack()
> -print 'error code', (header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))
> -print 'error message: ', body[IPROTO_ERROR]
> -print 'eof:', len(s.recv(1024)) == 0
> +print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
> +print("error message:  {}".format(body[IPROTO_ERROR]))
> +print("eof: {}".format(len(s.recv(1024)) == 0))
>  s.close()
>  
>  server.admin("box.session.on_connect(nil, f1)")
> diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result

Please, ensure no .result files are changed. They have nothing to do
with Python strings and quotes.

Currently you have changed test/box-py/bootstrap.result,
test/box-py/call.result, test/box-py/print.result,
test/replication-py/cluster.result.

Everything else looks good.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [Tarantool-patches] [PATCH] test: make strings compatible with Python 3
  2020-12-17 18:26       ` Leonid Vasiliev
@ 2020-12-22  8:15         ` sergeyb
  2020-12-23  9:59           ` Leonid Vasiliev
  2020-12-22  8:19         ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x Sergey Bronnikov
  1 sibling, 1 reply; 27+ messages in thread
From: sergeyb @ 2020-12-22  8:15 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, lvasiliev

From: Sergey Bronnikov <sergeyb@tarantool.org>

The largest change in Python 3 is the handling of strings.
In Python 2, the str type was used for two different
kinds of values – text and bytes, whereas in Python 3,
these are separate and incompatible types.
Patch converts strings to byte strings where it is required
to make tests compatible with Python 3.

Part of #5538
---
 test/box-py/bad_trigger.test.py      |  2 +-
 test/box-py/iproto.test.py           | 42 +++++++++++++++++-----------
 test/replication-py/conflict.test.py |  5 ++--
 3 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/test/box-py/bad_trigger.test.py b/test/box-py/bad_trigger.test.py
index 9dd6e17c9..03b7efcda 100644
--- a/test/box-py/bad_trigger.test.py
+++ b/test/box-py/bad_trigger.test.py
@@ -41,7 +41,7 @@ unpacker.feed(packet)
 header = unpacker.unpack()
 body = unpacker.unpack()
 print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
-print("error message:  {}".format(body[IPROTO_ERROR]))
+print("error message:  {}".format(body[IPROTO_ERROR].decode("utf-8")))
 print("eof: {}".format(len(s.recv(1024)) == 0))
 s.close()
 
diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
index 6723e03f5..ff0469f10 100644
--- a/test/box-py/iproto.test.py
+++ b/test/box-py/iproto.test.py
@@ -1,5 +1,6 @@
 from __future__ import print_function
 
+import binascii
 import os
 import sys
 import struct
@@ -163,7 +164,7 @@ class RawInsert(Request):
 
     def __init__(self, conn, space_no, blob):
         super(RawInsert, self).__init__(conn)
-        request_body = "\x82" + msgpack.dumps(IPROTO_SPACE_ID) + \
+        request_body = b'\x82' + msgpack.dumps(IPROTO_SPACE_ID) + \
             msgpack.dumps(space_id) + msgpack.dumps(IPROTO_TUPLE) + blob
         self._body = request_body
 
@@ -172,7 +173,7 @@ class RawSelect(Request):
 
     def __init__(self, conn, space_no, blob):
         super(RawSelect, self).__init__(conn)
-        request_body = "\x83" + msgpack.dumps(IPROTO_SPACE_ID) + \
+        request_body = b'\x83' + msgpack.dumps(IPROTO_SPACE_ID) + \
             msgpack.dumps(space_id) + msgpack.dumps(IPROTO_KEY) + blob + \
             msgpack.dumps(IPROTO_LIMIT) + msgpack.dumps(100);
         self._body = request_body
@@ -182,13 +183,13 @@ space = c.space("test")
 space_id = space.space_no
 
 TESTS = [
-    (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", "\xdb\x00\x00\x00\x01"),
-    (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", "\xdb\x00\x00\x00\x1f"),
-    (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
-    (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
-    (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
-    (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
-    (65536, "\xdb\x00\x01\x00\x00"),
+    (1,     b'\xa1', b'\xd9\x01', b'\xda\x00\x01', b'\xdb\x00\x00\x00\x01'),
+    (31,    b'\xbf', b'\xd9\x1f', b'\xda\x00\x1f', b'\xdb\x00\x00\x00\x1f'),
+    (32,    b'\xd9\x20', b'\xda\x00\x20', b'\xdb\x00\x00\x00\x20'),
+    (255,   b'\xd9\xff', b'\xda\x00\xff', b'\xdb\x00\x00\x00\xff'),
+    (256,   b'\xda\x01\x00', b'\xdb\x00\x00\x01\x00'),
+    (65535, b'\xda\xff\xff', b'\xdb\x00\x00\xff\xff'),
+    (65536, b'\xdb\x00\x01\x00\x00'),
 ]
 
 for test in TESTS:
@@ -197,16 +198,19 @@ for test in TESTS:
     print("STR", size)
     print("--")
     for fmt in it:
-        print("0x" + fmt.encode("hex"), "=>", end=" ")
+        if sys.version[0] == '2':
+            print("0x" + fmt.encode("hex"), "=>", end=" ")
+        else:
+            print("0x" + fmt.hex(), "=>", end=" ")
         field = "*" * size
-        c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
+        c._send_request(RawInsert(c, space_id, b'\x91' + fmt + field.encode("utf-8")))
         tuple = space.select(field)[0]
         print(len(tuple[0])== size and "ok" or "fail", end=" ")
         it2 = iter(test)
         next(it2)
         for fmt2 in it2:
             tuple = c._send_request(RawSelect(c, space_id,
-                "\x91" + fmt2 + field))[0]
+                b'\x91' + fmt2 + field.encode("utf-8")))[0]
             print(len(tuple[0]) == size and "ok" or "fail", end=" ")
         tuple = space.delete(field)[0]
         print(len(tuple[0]) == size and "ok" or "fail", end="")
@@ -357,15 +361,18 @@ s = c._socket
 header = { "hello": "world"}
 body = { "bug": 272 }
 resp = test_request(header, body)
-print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
+print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
+        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
 header = { IPROTO_CODE : REQUEST_TYPE_SELECT }
 header[IPROTO_SYNC] = 1234
 resp = test_request(header, body)
-print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
+print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
+        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
 header[IPROTO_SYNC] = 5678
 body = { IPROTO_SPACE_ID: 304, IPROTO_KEY: [], IPROTO_LIMIT: 1 }
 resp = test_request(header, body)
-print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
+print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
+        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
 c.close()
 
 
@@ -424,7 +431,10 @@ header = { IPROTO_CODE: REQUEST_TYPE_CALL, IPROTO_SYNC: 100 }
 body = { IPROTO_FUNCTION_NAME: "kek" }
 resp = test_request(header, body)
 print("Sync: ", resp["header"][IPROTO_SYNC])
-print("Retcode: ", resp["body"][IPROTO_DATA])
+body = resp["body"][IPROTO_DATA]
+if sys.version[0] == '3':
+    body = [body[0].decode("utf-8")]
+print("Retcode: ", body)
 
 c.close()
 
diff --git a/test/replication-py/conflict.test.py b/test/replication-py/conflict.test.py
index 5e19d0c40..925ae046b 100644
--- a/test/replication-py/conflict.test.py
+++ b/test/replication-py/conflict.test.py
@@ -20,9 +20,8 @@ replica.deploy()
 def parallel_run(cmd1, cmd2, compare):
     print("parallel send: {}".format(cmd1))
     print("parallel send: {}".format(cmd2))
-    master.admin.socket.sendall("{}\n".format(cmd1))
-    replica.admin.socket.sendall("{}\n".format(cmd2))
-
+    master.admin.socket.sendall(cmd1.encode("utf-8") + b'\n')
+    replica.admin.socket.sendall(cmd2.encode("utf-8") + b'\n')
     master.admin.socket.recv(2048)
     replica.admin.socket.recv(2048)
 
-- 
2.25.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x
  2020-12-17 18:26       ` Leonid Vasiliev
  2020-12-22  8:15         ` [Tarantool-patches] [PATCH] test: make strings compatible with Python 3 sergeyb
@ 2020-12-22  8:19         ` Sergey Bronnikov
  2020-12-23 10:00           ` Leonid Vasiliev
  1 sibling, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-22  8:19 UTC (permalink / raw)
  To: Leonid Vasiliev, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hi,

On 17.12.2020 21:26, Leonid Vasiliev wrote:
> Hi!
>
> On 16.12.2020 17:04, Sergey Bronnikov wrote:
>> Hello,
>>
>>
>> On 15.12.2020 14:55, Leonid Vasiliev wrote:
>>> Hi! Thank you for the patch.
>>>
>>> On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
>>>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>>>
>>>> Part of #5538
>>>> ---
>>>>   test/box-py/iproto.test.py | 6 +++++-
>>>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>>>> index 25ead43c4..72400923c 100644
>>>> --- a/test/box-py/iproto.test.py
>>>> +++ b/test/box-py/iproto.test.pyHi
>>>> @@ -191,7 +191,11 @@ for test in TESTS:
>>>>       print("STR", size)
>>>>       print("--")
>>>>       for fmt in it:
>>>> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
>>>> +        try:
>>>> +            # Python 3
>>>> +            print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
>>>
>>> Maybe fmt.encode("utf-8").hex()?
>>
>> I would be glad to use it in Python 3, but fmt module was removed there.
>
> Sorry, but I don't understand which module "fmt" you mean. I don't see
> any `import fmt...` here. AFAIU `fmt` in this context is a string from
> one of the tuples from the list `TESTS`.
>
> So, I copy this hunk:
> ```
> from __future__ import print_function
>
> TESTS = [
>     (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", "\xdb\x00\x00\x00\x01"),
>     (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", "\xdb\x00\x00\x00\x1f"),
>     (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
>     (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
>     (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
>     (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
>     (65536, "\xdb\x00\x01\x00\x00"),
> ]
>
> for test in TESTS:
>     it = iter(test)
>     size = next(it)
>     print("STR", size)
>     print("--")
>     for fmt in it:
>         try:
>             # Python 3
>             print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
>         except AttributeError:
>             print("0x" + fmt.encode("hex"), "=>", end=" ")
>         print()
>     print()
> ```
>
> and run it on python2 and python3.
> Results doesn't look identically.
>
> Python2:
> ```
> ┌─[leonid@vasya-L460]─[~/work/mail/tarantool/tmp]
> └──╼ python2 test.py
> STR 1
> -- 
> 0xa1 =>
> 0xd901 =>
> 0xda0001 =>
> 0xdb00000001 =>
>
> STR 31
> -- 
> 0xbf =>
> 0xd91f =>
> 0xda001f =>
> 0xdb0000001f =>
>
> STR 32
> -- 
> 0xd920 =>
> 0xda0020 =>
> 0xdb00000020 =>
>
> STR 255
> -- 
> 0xd9ff =>
> 0xda00ff =>
> 0xdb000000ff =>
>
> STR 256
> -- 
> 0xda0100 =>
> 0xdb00000100 =>
>
> STR 65535
> -- 
> 0xdaffff =>
> 0xdb0000ffff =>
>
> STR 65536
> -- 
> 0xdb00010000 =>
>
> ```
>
> Python3:
> ```
> ┌─[leonid@vasya-L460]─[~/work/mail/tarantool/tmp]
> └──╼ python3 test.py
> STR 1
> -- 
> 0x686578 =>
> 0x686578 =>
> 0x686578 =>
> 0x686578 =>
>
> STR 31
> -- 
> 0x686578 =>
> 0x686578 =>
> 0x686578 =>
> 0x686578 =>
>
> STR 32
> -- 
> 0x686578 =>
> 0x686578 =>
> 0x686578 =>
>
> STR 255
> -- 
> 0x686578 =>
> 0x686578 =>
> 0x686578 =>
>
> STR 256
> -- 
> 0x686578 =>
> 0x686578 =>
>
> STR 65535
> -- 
> 0x686578 =>
> 0x686578 =>
>
> STR 65536
> -- 
> 0x686578 =>
>
> ```
>
> Am I doing something wrong or a bug in the patch?

Yep, patch was incorrect. I have removed it and added new one to the 
branch and send to this thread [1].

Could you please take a look?

1. 
https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021528.html


>
>>
>>
>>> Please, add a comment that describing the difference between python2 
>>> and
>>> python3 in this print.
>>>
>> Added comment to a commit message and force-pushed.
>>>> +        except AttributeError:
>>>> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>>>>           field = "*" * size
>>>>           c._send_request(RawInsert(c, space_id, "\x91" + fmt + 
>>>> field))
>>>>           tuple = space.select(field)[0]
>>>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH] test: make strings compatible with Python 3
  2020-12-22  8:15         ` [Tarantool-patches] [PATCH] test: make strings compatible with Python 3 sergeyb
@ 2020-12-23  9:59           ` Leonid Vasiliev
  2020-12-23 10:35             ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-23  9:59 UTC (permalink / raw)
  To: sergeyb, tarantool-patches, v.shpilevoy

Hi! Thank you for the patch.
Generally I'm comfortable with the patch. But I have a few questions:

On 22.12.2020 11:15, sergeyb@tarantool.org wrote:
> From: Sergey Bronnikov <sergeyb@tarantool.org>
> 
> The largest change in Python 3 is the handling of strings.
> In Python 2, the str type was used for two different
> kinds of values – text and bytes, whereas in Python 3,
> these are separate and incompatible types.
> Patch converts strings to byte strings where it is required
> to make tests compatible with Python 3.
> 
> Part of #5538
> ---
>   test/box-py/bad_trigger.test.py      |  2 +-
>   test/box-py/iproto.test.py           | 42 +++++++++++++++++-----------
>   test/replication-py/conflict.test.py |  5 ++--
>   3 files changed, 29 insertions(+), 20 deletions(-)
> 
> diff --git a/test/box-py/bad_trigger.test.py b/test/box-py/bad_trigger.test.py
> index 9dd6e17c9..03b7efcda 100644
> --- a/test/box-py/bad_trigger.test.py
> +++ b/test/box-py/bad_trigger.test.py
> @@ -41,7 +41,7 @@ unpacker.feed(packet)
>   header = unpacker.unpack()
>   body = unpacker.unpack()
>   print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
> -print("error message:  {}".format(body[IPROTO_ERROR]))
> +print("error message:  {}".format(body[IPROTO_ERROR].decode("utf-8")))
>   print("eof: {}".format(len(s.recv(1024)) == 0))
>   s.close()
>   
> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
> index 6723e03f5..ff0469f10 100644
> --- a/test/box-py/iproto.test.py
> +++ b/test/box-py/iproto.test.py
> @@ -1,5 +1,6 @@
>   from __future__ import print_function
>   
> +import binascii

Where is the module used?

>   import os
>   import sys
>   import struct
> @@ -163,7 +164,7 @@ class RawInsert(Request):
>   
>       def __init__(self, conn, space_no, blob):
>           super(RawInsert, self).__init__(conn)
> -        request_body = "\x82" + msgpack.dumps(IPROTO_SPACE_ID) + \
> +        request_body = b'\x82' + msgpack.dumps(IPROTO_SPACE_ID) + \
>               msgpack.dumps(space_id) + msgpack.dumps(IPROTO_TUPLE) + blob
>           self._body = request_body
>   
> @@ -172,7 +173,7 @@ class RawSelect(Request):
>   
>       def __init__(self, conn, space_no, blob):
>           super(RawSelect, self).__init__(conn)
> -        request_body = "\x83" + msgpack.dumps(IPROTO_SPACE_ID) + \
> +        request_body = b'\x83' + msgpack.dumps(IPROTO_SPACE_ID) + \
>               msgpack.dumps(space_id) + msgpack.dumps(IPROTO_KEY) + blob + \
>               msgpack.dumps(IPROTO_LIMIT) + msgpack.dumps(100);
>           self._body = request_body
> @@ -182,13 +183,13 @@ space = c.space("test")
>   space_id = space.space_no
>   
>   TESTS = [
> -    (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", "\xdb\x00\x00\x00\x01"),
> -    (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", "\xdb\x00\x00\x00\x1f"),
> -    (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
> -    (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
> -    (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
> -    (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
> -    (65536, "\xdb\x00\x01\x00\x00"),
> +    (1,     b'\xa1', b'\xd9\x01', b'\xda\x00\x01', b'\xdb\x00\x00\x00\x01'),
> +    (31,    b'\xbf', b'\xd9\x1f', b'\xda\x00\x1f', b'\xdb\x00\x00\x00\x1f'),
> +    (32,    b'\xd9\x20', b'\xda\x00\x20', b'\xdb\x00\x00\x00\x20'),
> +    (255,   b'\xd9\xff', b'\xda\x00\xff', b'\xdb\x00\x00\x00\xff'),
> +    (256,   b'\xda\x01\x00', b'\xdb\x00\x00\x01\x00'),
> +    (65535, b'\xda\xff\xff', b'\xdb\x00\x00\xff\xff'),
> +    (65536, b'\xdb\x00\x01\x00\x00'),

Why do you choose single quotes for byte strings and double quotes for
strings? Maybe we will use double quotes for all strings? (applies to
the whole patch)

>   ]
>   
>   for test in TESTS:
> @@ -197,16 +198,19 @@ for test in TESTS:
>       print("STR", size)
>       print("--")
>       for fmt in it:
> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
> +        if sys.version[0] == '2':
> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
> +        else:
> +            print("0x" + fmt.hex(), "=>", end=" ")
>           field = "*" * size
> -        c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
> +        c._send_request(RawInsert(c, space_id, b'\x91' + fmt + field.encode("utf-8")))
>           tuple = space.select(field)[0]
>           print(len(tuple[0])== size and "ok" or "fail", end=" ")
>           it2 = iter(test)
>           next(it2)
>           for fmt2 in it2:
>               tuple = c._send_request(RawSelect(c, space_id,
> -                "\x91" + fmt2 + field))[0]
> +                b'\x91' + fmt2 + field.encode("utf-8")))[0]
>               print(len(tuple[0]) == size and "ok" or "fail", end=" ")
>           tuple = space.delete(field)[0]
>           print(len(tuple[0]) == size and "ok" or "fail", end="")
> @@ -357,15 +361,18 @@ s = c._socket
>   header = { "hello": "world"}
>   body = { "bug": 272 }
>   resp = test_request(header, body)
> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>   header = { IPROTO_CODE : REQUEST_TYPE_SELECT }
>   header[IPROTO_SYNC] = 1234
>   resp = test_request(header, body)
> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>   header[IPROTO_SYNC] = 5678
>   body = { IPROTO_SPACE_ID: 304, IPROTO_KEY: [], IPROTO_LIMIT: 1 }
>   resp = test_request(header, body)
> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], resp["body"].get(IPROTO_ERROR)))
> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>   c.close()
>   
>   
> @@ -424,7 +431,10 @@ header = { IPROTO_CODE: REQUEST_TYPE_CALL, IPROTO_SYNC: 100 }
>   body = { IPROTO_FUNCTION_NAME: "kek" }
>   resp = test_request(header, body)
>   print("Sync: ", resp["header"][IPROTO_SYNC])
> -print("Retcode: ", resp["body"][IPROTO_DATA])
> +body = resp["body"][IPROTO_DATA]
> +if sys.version[0] == '3':
> +    body = [body[0].decode("utf-8")]
> +print("Retcode: ", body)
>   
>   c.close()
>   
> diff --git a/test/replication-py/conflict.test.py b/test/replication-py/conflict.test.py
> index 5e19d0c40..925ae046b 100644
> --- a/test/replication-py/conflict.test.py
> +++ b/test/replication-py/conflict.test.py
> @@ -20,9 +20,8 @@ replica.deploy()
>   def parallel_run(cmd1, cmd2, compare):
>       print("parallel send: {}".format(cmd1))
>       print("parallel send: {}".format(cmd2))
> -    master.admin.socket.sendall("{}\n".format(cmd1))
> -    replica.admin.socket.sendall("{}\n".format(cmd2))
> -
> +    master.admin.socket.sendall(cmd1.encode("utf-8") + b'\n')
> +    replica.admin.socket.sendall(cmd2.encode("utf-8") + b'\n')
>       master.admin.socket.recv(2048)
>       replica.admin.socket.recv(2048)
>   
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x
  2020-12-22  8:19         ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x Sergey Bronnikov
@ 2020-12-23 10:00           ` Leonid Vasiliev
  0 siblings, 0 replies; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-23 10:00 UTC (permalink / raw)
  To: Sergey Bronnikov, tarantool-patches, v.shpilevoy, imun; +Cc: alexander.turenko

Hi!

On 22.12.2020 11:19, Sergey Bronnikov wrote:
> Hi,
> 
> On 17.12.2020 21:26, Leonid Vasiliev wrote:
>> Hi!
>>
>> On 16.12.2020 17:04, Sergey Bronnikov wrote:
>>> Hello,
>>>
>>>
>>> On 15.12.2020 14:55, Leonid Vasiliev wrote:
>>>> Hi! Thank you for the patch.
>>>>
>>>> On 11.12.2020 11:42, Sergey Bronnikov via Tarantool-patches wrote:
>>>>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>>>>
>>>>> Part of #5538
>>>>> ---
>>>>>   test/box-py/iproto.test.py | 6 +++++-
>>>>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>>>>> index 25ead43c4..72400923c 100644
>>>>> --- a/test/box-py/iproto.test.py
>>>>> +++ b/test/box-py/iproto.test.pyHi
>>>>> @@ -191,7 +191,11 @@ for test in TESTS:
>>>>>       print("STR", size)
>>>>>       print("--")
>>>>>       for fmt in it:
>>>>> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
>>>>> +        try:
>>>>> +            # Python 3
>>>>> +            print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
>>>>
>>>> Maybe fmt.encode("utf-8").hex()?
>>>
>>> I would be glad to use it in Python 3, but fmt module was removed there.
>>
>> Sorry, but I don't understand which module "fmt" you mean. I don't see
>> any `import fmt...` here. AFAIU `fmt` in this context is a string from
>> one of the tuples from the list `TESTS`.
>>
>> So, I copy this hunk:
>> ```
>> from __future__ import print_function
>>
>> TESTS = [
>>     (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", "\xdb\x00\x00\x00\x01"),
>>     (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", "\xdb\x00\x00\x00\x1f"),
>>     (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
>>     (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
>>     (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
>>     (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
>>     (65536, "\xdb\x00\x01\x00\x00"),
>> ]
>>
>> for test in TESTS:
>>     it = iter(test)
>>     size = next(it)
>>     print("STR", size)
>>     print("--")
>>     for fmt in it:
>>         try:
>>             # Python 3
>>             print("0x" + "hex".encode("utf-8").hex(), "=>", end=" ")
>>         except AttributeError:
>>             print("0x" + fmt.encode("hex"), "=>", end=" ")
>>         print()
>>     print()
>> ```
>>
>> and run it on python2 and python3.
>> Results doesn't look identically.
>>
>> Python2:
>> ```
>> ┌─[leonid@vasya-L460]─[~/work/mail/tarantool/tmp]
>> └──╼ python2 test.py
>> STR 1
>> -- 
>> 0xa1 =>
>> 0xd901 =>
>> 0xda0001 =>
>> 0xdb00000001 =>
>>
>> STR 31
>> -- 
>> 0xbf =>
>> 0xd91f =>
>> 0xda001f =>
>> 0xdb0000001f =>
>>
>> STR 32
>> -- 
>> 0xd920 =>
>> 0xda0020 =>
>> 0xdb00000020 =>
>>
>> STR 255
>> -- 
>> 0xd9ff =>
>> 0xda00ff =>
>> 0xdb000000ff =>
>>
>> STR 256
>> -- 
>> 0xda0100 =>
>> 0xdb00000100 =>
>>
>> STR 65535
>> -- 
>> 0xdaffff =>
>> 0xdb0000ffff =>
>>
>> STR 65536
>> -- 
>> 0xdb00010000 =>
>>
>> ```
>>
>> Python3:
>> ```
>> ┌─[leonid@vasya-L460]─[~/work/mail/tarantool/tmp]
>> └──╼ python3 test.py
>> STR 1
>> -- 
>> 0x686578 =>
>> 0x686578 =>
>> 0x686578 =>
>> 0x686578 =>
>>
>> STR 31
>> -- 
>> 0x686578 =>
>> 0x686578 =>
>> 0x686578 =>
>> 0x686578 =>
>>
>> STR 32
>> -- 
>> 0x686578 =>
>> 0x686578 =>
>> 0x686578 =>
>>
>> STR 255
>> -- 
>> 0x686578 =>
>> 0x686578 =>
>> 0x686578 =>
>>
>> STR 256
>> -- 
>> 0x686578 =>
>> 0x686578 =>
>>
>> STR 65535
>> -- 
>> 0x686578 =>
>> 0x686578 =>
>>
>> STR 65536
>> -- 
>> 0x686578 =>
>>
>> ```
>>
>> Am I doing something wrong or a bug in the patch?
> 
> Yep, patch was incorrect. I have removed it and added new one to the 
> branch and send to this thread [1].
> 
> Could you please take a look?
> 
> 1. 
> https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021528.html 

Done.

> 
> 
> 
>>
>>>
>>>
>>>> Please, add a comment that describing the difference between python2 
>>>> and
>>>> python3 in this print.
>>>>
>>> Added comment to a commit message and force-pushed.
>>>>> +        except AttributeError:
>>>>> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>>>>>           field = "*" * size
>>>>>           c._send_request(RawInsert(c, space_id, "\x91" + fmt + 
>>>>> field))
>>>>>           tuple = space.select(field)[0]
>>>>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code
  2020-12-13 19:02 ` [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code Sergey Bronnikov
@ 2020-12-23 10:07   ` Leonid Vasiliev
  2020-12-23 12:42     ` Sergey Bronnikov
  0 siblings, 1 reply; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-23 10:07 UTC (permalink / raw)
  To: Sergey Bronnikov, tarantool-patches
  Cc: Vladislav Shpilevoy, alexander.turenko

Hi!
As far as I can see, the composition of the patchset has much changed
(also, it now has five patches instead of four). I suggest to send a new
clean version of the patchset.

On 13.12.2020 22:02, Sergey Bronnikov wrote:
> + tarantool-patches@dev.tarantool.org
> 
> On 11.12.2020 11:42, sergeyb@tarantool.org wrote:
>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>
>> Changes v1:
>> - convert print statements to functions
>> - use "format()" instead of "%" everywhere
>>
>> Changes v2:
>> - make using quotes with strings consistent
>> - remove dead code
>> - remove empty prints
>> - added make target for running flake8
>> - added flake8 config
>> - added job to run flake8 on Gitlab CI
>>
>> Changes v3:
>> - removed three patches with flake8 integration
>> - fixed rest patches according to comments on review
>> - add a separate patch with converting dict.items() to a list
>> - add a new patch with conversion string to hex
>>
>> Gitlab CI: https://gitlab.com/tarantool/tarantool/-/jobs/904769000
>> Branch: 
>> https://github.com/tarantool/tarantool/tree/ligurio/gh-5538-support-python3 
>>
>> Issue: https://github.com/tarantool/tarantool/issues/5538
>>
>> Sergey Bronnikov (4):
>>    test: convert print to function and make quotes use consistent
>>    test: make dict.items() compatible with Python 3.x
>>    test: make convert to hex compatible with Python 3.x
>>    test: remove dead code in Python tests end extra newline
>>
>>   test/app-tap/httpd.py                    |  42 ++---
>>   test/box-py/args.test.py                 |  14 +-
>>   test/box-py/bad_trigger.result           |   2 -
>>   test/box-py/bad_trigger.test.py          |  20 +--
>>   test/box-py/bootstrap.result             |   2 +-
>>   test/box-py/bootstrap.test.py            |  16 +-
>>   test/box-py/call.result                  |  12 +-
>>   test/box-py/call.test.py                 |  92 +++++-----
>>   test/box-py/iproto.result                |  10 +-
>>   test/box-py/iproto.test.py               | 220 +++++++++++------------
>>   test/box-py/print.result                 |   6 +-
>>   test/box-py/print.test.py                |  24 +--
>>   test/box-py/snapshot.result              |   4 +-
>>   test/box-py/snapshot.test.py             |  33 ++--
>>   test/long_run-py/finalizers.result       |   2 +-
>>   test/long_run-py/finalizers.test.py      |   8 +-
>>   test/replication-py/cluster.result       |   6 +-
>>   test/replication-py/cluster.test.py      | 217 +++++++++++-----------
>>   test/replication-py/conflict.test.py     |  54 +++---
>>   test/replication-py/init_storage.test.py |  58 +++---
>>   test/replication-py/multi.test.py        |  78 ++++----
>>   test/replication-py/swap.test.py         |  55 +++---
>>   test/xlog-py/big_lsn.test.py             |   4 +-
>>   test/xlog-py/dup_key.test.py             |  22 +--
>>   test/xlog-py/empty.test.py               |   4 +-
>>   test/xlog-py/lsn_gap.test.py             |  11 +-
>>   test/xlog-py/misc.test.py                |  33 ++--
>>   test/xlog-py/missing.test.py             |  10 +-
>>   28 files changed, 530 insertions(+), 529 deletions(-)
>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH] test: make strings compatible with Python 3
  2020-12-23  9:59           ` Leonid Vasiliev
@ 2020-12-23 10:35             ` Sergey Bronnikov
  2020-12-23 11:09               ` Leonid Vasiliev
  0 siblings, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-23 10:35 UTC (permalink / raw)
  To: Leonid Vasiliev, tarantool-patches, v.shpilevoy

Hi,


thanks for review


On 23.12.2020 12:59, Leonid Vasiliev wrote:
> Hi! Thank you for the patch.
> Generally I'm comfortable with the patch. But I have a few questions:
>
> On 22.12.2020 11:15, sergeyb@tarantool.org wrote:
>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>
>> The largest change in Python 3 is the handling of strings.
>> In Python 2, the str type was used for two different
>> kinds of values – text and bytes, whereas in Python 3,
>> these are separate and incompatible types.
>> Patch converts strings to byte strings where it is required
>> to make tests compatible with Python 3.
>>
>> Part of #5538
>> ---
>>   test/box-py/bad_trigger.test.py      |  2 +-
>>   test/box-py/iproto.test.py           | 42 +++++++++++++++++-----------
>>   test/replication-py/conflict.test.py |  5 ++--
>>   3 files changed, 29 insertions(+), 20 deletions(-)
>>
>> diff --git a/test/box-py/bad_trigger.test.py 
>> b/test/box-py/bad_trigger.test.py
>> index 9dd6e17c9..03b7efcda 100644
>> --- a/test/box-py/bad_trigger.test.py
>> +++ b/test/box-py/bad_trigger.test.py
>> @@ -41,7 +41,7 @@ unpacker.feed(packet)
>>   header = unpacker.unpack()
>>   body = unpacker.unpack()
>>   print("error code {}".format((header[IPROTO_CODE] & 
>> (REQUEST_TYPE_ERROR - 1))))
>> -print("error message:  {}".format(body[IPROTO_ERROR]))
>> +print("error message: {}".format(body[IPROTO_ERROR].decode("utf-8")))
>>   print("eof: {}".format(len(s.recv(1024)) == 0))
>>   s.close()
>>   diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>> index 6723e03f5..ff0469f10 100644
>> --- a/test/box-py/iproto.test.py
>> +++ b/test/box-py/iproto.test.py
>> @@ -1,5 +1,6 @@
>>   from __future__ import print_function
>>   +import binascii
>
> Where is the module used?

Left after another implementation, removed and force-pushed.


>
>>   import os
>>   import sys
>>   import struct
>> @@ -163,7 +164,7 @@ class RawInsert(Request):
>>         def __init__(self, conn, space_no, blob):
>>           super(RawInsert, self).__init__(conn)
>> -        request_body = "\x82" + msgpack.dumps(IPROTO_SPACE_ID) + \
>> +        request_body = b'\x82' + msgpack.dumps(IPROTO_SPACE_ID) + \
>>               msgpack.dumps(space_id) + msgpack.dumps(IPROTO_TUPLE) + 
>> blob
>>           self._body = request_body
>>   @@ -172,7 +173,7 @@ class RawSelect(Request):
>>         def __init__(self, conn, space_no, blob):
>>           super(RawSelect, self).__init__(conn)
>> -        request_body = "\x83" + msgpack.dumps(IPROTO_SPACE_ID) + \
>> +        request_body = b'\x83' + msgpack.dumps(IPROTO_SPACE_ID) + \
>>               msgpack.dumps(space_id) + msgpack.dumps(IPROTO_KEY) + 
>> blob + \
>>               msgpack.dumps(IPROTO_LIMIT) + msgpack.dumps(100);
>>           self._body = request_body
>> @@ -182,13 +183,13 @@ space = c.space("test")
>>   space_id = space.space_no
>>     TESTS = [
>> -    (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", 
>> "\xdb\x00\x00\x00\x01"),
>> -    (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", 
>> "\xdb\x00\x00\x00\x1f"),
>> -    (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
>> -    (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
>> -    (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
>> -    (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
>> -    (65536, "\xdb\x00\x01\x00\x00"),
>> +    (1,     b'\xa1', b'\xd9\x01', b'\xda\x00\x01', 
>> b'\xdb\x00\x00\x00\x01'),
>> +    (31,    b'\xbf', b'\xd9\x1f', b'\xda\x00\x1f', 
>> b'\xdb\x00\x00\x00\x1f'),
>> +    (32,    b'\xd9\x20', b'\xda\x00\x20', b'\xdb\x00\x00\x00\x20'),
>> +    (255,   b'\xd9\xff', b'\xda\x00\xff', b'\xdb\x00\x00\x00\xff'),
>> +    (256,   b'\xda\x01\x00', b'\xdb\x00\x00\x01\x00'),
>> +    (65535, b'\xda\xff\xff', b'\xdb\x00\x00\xff\xff'),
>> +    (65536, b'\xdb\x00\x01\x00\x00'),
>
> Why do you choose single quotes for byte strings and double quotes for
> strings? Maybe we will use double quotes for all strings? (applies to
> the whole patch)

I use double quotes for strings and single quotes for bytes literals, 
see [1].

1. https://www.python.org/dev/peps/pep-3112/

>
>>   ]
>>     for test in TESTS:
>> @@ -197,16 +198,19 @@ for test in TESTS:
>>       print("STR", size)
>>       print("--")
>>       for fmt in it:
>> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
>> +        if sys.version[0] == '2':
>> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>> +        else:
>> +            print("0x" + fmt.hex(), "=>", end=" ")
>>           field = "*" * size
>> -        c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
>> +        c._send_request(RawInsert(c, space_id, b'\x91' + fmt + 
>> field.encode("utf-8")))
>>           tuple = space.select(field)[0]
>>           print(len(tuple[0])== size and "ok" or "fail", end=" ")
>>           it2 = iter(test)
>>           next(it2)
>>           for fmt2 in it2:
>>               tuple = c._send_request(RawSelect(c, space_id,
>> -                "\x91" + fmt2 + field))[0]
>> +                b'\x91' + fmt2 + field.encode("utf-8")))[0]
>>               print(len(tuple[0]) == size and "ok" or "fail", end=" ")
>>           tuple = space.delete(field)[0]
>>           print(len(tuple[0]) == size and "ok" or "fail", end="")
>> @@ -357,15 +361,18 @@ s = c._socket
>>   header = { "hello": "world"}
>>   body = { "bug": 272 }
>>   resp = test_request(header, body)
>> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], 
>> resp["body"].get(IPROTO_ERROR)))
>> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
>> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>>   header = { IPROTO_CODE : REQUEST_TYPE_SELECT }
>>   header[IPROTO_SYNC] = 1234
>>   resp = test_request(header, body)
>> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], 
>> resp["body"].get(IPROTO_ERROR)))
>> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
>> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>>   header[IPROTO_SYNC] = 5678
>>   body = { IPROTO_SPACE_ID: 304, IPROTO_KEY: [], IPROTO_LIMIT: 1 }
>>   resp = test_request(header, body)
>> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], 
>> resp["body"].get(IPROTO_ERROR)))
>> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
>> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>>   c.close()
>>     @@ -424,7 +431,10 @@ header = { IPROTO_CODE: REQUEST_TYPE_CALL, 
>> IPROTO_SYNC: 100 }
>>   body = { IPROTO_FUNCTION_NAME: "kek" }
>>   resp = test_request(header, body)
>>   print("Sync: ", resp["header"][IPROTO_SYNC])
>> -print("Retcode: ", resp["body"][IPROTO_DATA])
>> +body = resp["body"][IPROTO_DATA]
>> +if sys.version[0] == '3':
>> +    body = [body[0].decode("utf-8")]
>> +print("Retcode: ", body)
>>     c.close()
>>   diff --git a/test/replication-py/conflict.test.py 
>> b/test/replication-py/conflict.test.py
>> index 5e19d0c40..925ae046b 100644
>> --- a/test/replication-py/conflict.test.py
>> +++ b/test/replication-py/conflict.test.py
>> @@ -20,9 +20,8 @@ replica.deploy()
>>   def parallel_run(cmd1, cmd2, compare):
>>       print("parallel send: {}".format(cmd1))
>>       print("parallel send: {}".format(cmd2))
>> -    master.admin.socket.sendall("{}\n".format(cmd1))
>> -    replica.admin.socket.sendall("{}\n".format(cmd2))
>> -
>> +    master.admin.socket.sendall(cmd1.encode("utf-8") + b'\n')
>> +    replica.admin.socket.sendall(cmd2.encode("utf-8") + b'\n')
>>       master.admin.socket.recv(2048)
>>       replica.admin.socket.recv(2048)
>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH] test: make strings compatible with Python 3
  2020-12-23 10:35             ` Sergey Bronnikov
@ 2020-12-23 11:09               ` Leonid Vasiliev
  0 siblings, 0 replies; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-23 11:09 UTC (permalink / raw)
  To: Sergey Bronnikov, tarantool-patches, v.shpilevoy

Hi!
LGTM.

On 23.12.2020 13:35, Sergey Bronnikov wrote:
> Hi,
> 
> 
> thanks for review
> 
> 
> On 23.12.2020 12:59, Leonid Vasiliev wrote:
>> Hi! Thank you for the patch.
>> Generally I'm comfortable with the patch. But I have a few questions:
>>
>> On 22.12.2020 11:15, sergeyb@tarantool.org wrote:
>>> From: Sergey Bronnikov <sergeyb@tarantool.org>
>>>
>>> The largest change in Python 3 is the handling of strings.
>>> In Python 2, the str type was used for two different
>>> kinds of values – text and bytes, whereas in Python 3,
>>> these are separate and incompatible types.
>>> Patch converts strings to byte strings where it is required
>>> to make tests compatible with Python 3.
>>>
>>> Part of #5538
>>> ---
>>>   test/box-py/bad_trigger.test.py      |  2 +-
>>>   test/box-py/iproto.test.py           | 42 +++++++++++++++++-----------
>>>   test/replication-py/conflict.test.py |  5 ++--
>>>   3 files changed, 29 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/test/box-py/bad_trigger.test.py 
>>> b/test/box-py/bad_trigger.test.py
>>> index 9dd6e17c9..03b7efcda 100644
>>> --- a/test/box-py/bad_trigger.test.py
>>> +++ b/test/box-py/bad_trigger.test.py
>>> @@ -41,7 +41,7 @@ unpacker.feed(packet)
>>>   header = unpacker.unpack()
>>>   body = unpacker.unpack()
>>>   print("error code {}".format((header[IPROTO_CODE] & 
>>> (REQUEST_TYPE_ERROR - 1))))
>>> -print("error message:  {}".format(body[IPROTO_ERROR]))
>>> +print("error message: {}".format(body[IPROTO_ERROR].decode("utf-8")))
>>>   print("eof: {}".format(len(s.recv(1024)) == 0))
>>>   s.close()
>>>   diff --git a/test/box-py/iproto.test.py b/test/box-py/iproto.test.py
>>> index 6723e03f5..ff0469f10 100644
>>> --- a/test/box-py/iproto.test.py
>>> +++ b/test/box-py/iproto.test.py
>>> @@ -1,5 +1,6 @@
>>>   from __future__ import print_function
>>>   +import binascii
>>
>> Where is the module used?
> 
> Left after another implementation, removed and force-pushed.
> 
> 
>>
>>>   import os
>>>   import sys
>>>   import struct
>>> @@ -163,7 +164,7 @@ class RawInsert(Request):
>>>         def __init__(self, conn, space_no, blob):
>>>           super(RawInsert, self).__init__(conn)
>>> -        request_body = "\x82" + msgpack.dumps(IPROTO_SPACE_ID) + \
>>> +        request_body = b'\x82' + msgpack.dumps(IPROTO_SPACE_ID) + \
>>>               msgpack.dumps(space_id) + msgpack.dumps(IPROTO_TUPLE) + 
>>> blob
>>>           self._body = request_body
>>>   @@ -172,7 +173,7 @@ class RawSelect(Request):
>>>         def __init__(self, conn, space_no, blob):
>>>           super(RawSelect, self).__init__(conn)
>>> -        request_body = "\x83" + msgpack.dumps(IPROTO_SPACE_ID) + \
>>> +        request_body = b'\x83' + msgpack.dumps(IPROTO_SPACE_ID) + \
>>>               msgpack.dumps(space_id) + msgpack.dumps(IPROTO_KEY) + 
>>> blob + \
>>>               msgpack.dumps(IPROTO_LIMIT) + msgpack.dumps(100);
>>>           self._body = request_body
>>> @@ -182,13 +183,13 @@ space = c.space("test")
>>>   space_id = space.space_no
>>>     TESTS = [
>>> -    (1,     "\xa1", "\xd9\x01", "\xda\x00\x01", 
>>> "\xdb\x00\x00\x00\x01"),
>>> -    (31,    "\xbf", "\xd9\x1f", "\xda\x00\x1f", 
>>> "\xdb\x00\x00\x00\x1f"),
>>> -    (32,    "\xd9\x20", "\xda\x00\x20", "\xdb\x00\x00\x00\x20"),
>>> -    (255,   "\xd9\xff", "\xda\x00\xff", "\xdb\x00\x00\x00\xff"),
>>> -    (256,   "\xda\x01\x00", "\xdb\x00\x00\x01\x00"),
>>> -    (65535, "\xda\xff\xff", "\xdb\x00\x00\xff\xff"),
>>> -    (65536, "\xdb\x00\x01\x00\x00"),
>>> +    (1,     b'\xa1', b'\xd9\x01', b'\xda\x00\x01', 
>>> b'\xdb\x00\x00\x00\x01'),
>>> +    (31,    b'\xbf', b'\xd9\x1f', b'\xda\x00\x1f', 
>>> b'\xdb\x00\x00\x00\x1f'),
>>> +    (32,    b'\xd9\x20', b'\xda\x00\x20', b'\xdb\x00\x00\x00\x20'),
>>> +    (255,   b'\xd9\xff', b'\xda\x00\xff', b'\xdb\x00\x00\x00\xff'),
>>> +    (256,   b'\xda\x01\x00', b'\xdb\x00\x00\x01\x00'),
>>> +    (65535, b'\xda\xff\xff', b'\xdb\x00\x00\xff\xff'),
>>> +    (65536, b'\xdb\x00\x01\x00\x00'),
>>
>> Why do you choose single quotes for byte strings and double quotes for
>> strings? Maybe we will use double quotes for all strings? (applies to
>> the whole patch)
> 
> I use double quotes for strings and single quotes for bytes literals, 
> see [1].
> 
> 1. https://www.python.org/dev/peps/pep-3112/

Ok.

> 
>>
>>>   ]
>>>     for test in TESTS:
>>> @@ -197,16 +198,19 @@ for test in TESTS:
>>>       print("STR", size)
>>>       print("--")
>>>       for fmt in it:
>>> -        print("0x" + fmt.encode("hex"), "=>", end=" ")
>>> +        if sys.version[0] == '2':
>>> +            print("0x" + fmt.encode("hex"), "=>", end=" ")
>>> +        else:
>>> +            print("0x" + fmt.hex(), "=>", end=" ")
>>>           field = "*" * size
>>> -        c._send_request(RawInsert(c, space_id, "\x91" + fmt + field))
>>> +        c._send_request(RawInsert(c, space_id, b'\x91' + fmt + 
>>> field.encode("utf-8")))
>>>           tuple = space.select(field)[0]
>>>           print(len(tuple[0])== size and "ok" or "fail", end=" ")
>>>           it2 = iter(test)
>>>           next(it2)
>>>           for fmt2 in it2:
>>>               tuple = c._send_request(RawSelect(c, space_id,
>>> -                "\x91" + fmt2 + field))[0]
>>> +                b'\x91' + fmt2 + field.encode("utf-8")))[0]
>>>               print(len(tuple[0]) == size and "ok" or "fail", end=" ")
>>>           tuple = space.delete(field)[0]
>>>           print(len(tuple[0]) == size and "ok" or "fail", end="")
>>> @@ -357,15 +361,18 @@ s = c._socket
>>>   header = { "hello": "world"}
>>>   body = { "bug": 272 }
>>>   resp = test_request(header, body)
>>> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], 
>>> resp["body"].get(IPROTO_ERROR)))
>>> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
>>> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>>>   header = { IPROTO_CODE : REQUEST_TYPE_SELECT }
>>>   header[IPROTO_SYNC] = 1234
>>>   resp = test_request(header, body)
>>> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], 
>>> resp["body"].get(IPROTO_ERROR)))
>>> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
>>> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>>>   header[IPROTO_SYNC] = 5678
>>>   body = { IPROTO_SPACE_ID: 304, IPROTO_KEY: [], IPROTO_LIMIT: 1 }
>>>   resp = test_request(header, body)
>>> -print("sync={}, {}".format(resp["header"][IPROTO_SYNC], 
>>> resp["body"].get(IPROTO_ERROR)))
>>> +print("sync={}, {}".format(resp["header"][IPROTO_SYNC],
>>> +        resp["body"].get(IPROTO_ERROR).decode("utf-8")))
>>>   c.close()
>>>     @@ -424,7 +431,10 @@ header = { IPROTO_CODE: REQUEST_TYPE_CALL, 
>>> IPROTO_SYNC: 100 }
>>>   body = { IPROTO_FUNCTION_NAME: "kek" }
>>>   resp = test_request(header, body)
>>>   print("Sync: ", resp["header"][IPROTO_SYNC])
>>> -print("Retcode: ", resp["body"][IPROTO_DATA])
>>> +body = resp["body"][IPROTO_DATA]
>>> +if sys.version[0] == '3':
>>> +    body = [body[0].decode("utf-8")]
>>> +print("Retcode: ", body)
>>>     c.close()
>>>   diff --git a/test/replication-py/conflict.test.py 
>>> b/test/replication-py/conflict.test.py
>>> index 5e19d0c40..925ae046b 100644
>>> --- a/test/replication-py/conflict.test.py
>>> +++ b/test/replication-py/conflict.test.py
>>> @@ -20,9 +20,8 @@ replica.deploy()
>>>   def parallel_run(cmd1, cmd2, compare):
>>>       print("parallel send: {}".format(cmd1))
>>>       print("parallel send: {}".format(cmd2))
>>> -    master.admin.socket.sendall("{}\n".format(cmd1))
>>> -    replica.admin.socket.sendall("{}\n".format(cmd2))
>>> -
>>> +    master.admin.socket.sendall(cmd1.encode("utf-8") + b'\n')
>>> +    replica.admin.socket.sendall(cmd2.encode("utf-8") + b'\n')
>>>       master.admin.socket.recv(2048)
>>>       replica.admin.socket.recv(2048)
>>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent
  2020-12-20 16:47           ` Vladislav Shpilevoy
@ 2020-12-23 12:34             ` Sergey Bronnikov
  0 siblings, 0 replies; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-23 12:34 UTC (permalink / raw)
  To: Vladislav Shpilevoy, Leonid Vasiliev, tarantool-patches; +Cc: alexander.turenko

Hi,

On 20.12.2020 19:47, Vladislav Shpilevoy wrote:
>> @@ -38,9 +40,9 @@ unpacker.feed(packet)
>>   # Parse packet
>>   header = unpacker.unpack()
>>   body = unpacker.unpack()
>> -print 'error code', (header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))
>> -print 'error message: ', body[IPROTO_ERROR]
>> -print 'eof:', len(s.recv(1024)) == 0
>> +print("error code {}".format((header[IPROTO_CODE] & (REQUEST_TYPE_ERROR - 1))))
>> +print("error message:  {}".format(body[IPROTO_ERROR]))
>> +print("eof: {}".format(len(s.recv(1024)) == 0))
>>   s.close()
>>   
>>   server.admin("box.session.on_connect(nil, f1)")
>> diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
> Please, ensure no .result files are changed. They have nothing to do
> with Python strings and quotes.
>
> Currently you have changed test/box-py/bootstrap.result,
> test/box-py/call.result, test/box-py/print.result,
> test/replication-py/cluster.result.
>
> Everything else looks good.
>
reverted changes that updates .result files, force-pushed.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code
  2020-12-23 10:07   ` Leonid Vasiliev
@ 2020-12-23 12:42     ` Sergey Bronnikov
  2020-12-23 23:51       ` Leonid Vasiliev
  0 siblings, 1 reply; 27+ messages in thread
From: Sergey Bronnikov @ 2020-12-23 12:42 UTC (permalink / raw)
  To: Leonid Vasiliev, tarantool-patches; +Cc: Vladislav Shpilevoy, alexander.turenko


On 23.12.2020 13:07, Leonid Vasiliev wrote:
> Hi!
> As far as I can see, the composition of the patchset has much changed
> (also, it now has five patches instead of four). I suggest to send a new
> clean version of the patchset.
>

Could you take a look once again on v4?

https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021602.html

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code
  2020-12-23 12:42     ` Sergey Bronnikov
@ 2020-12-23 23:51       ` Leonid Vasiliev
  0 siblings, 0 replies; 27+ messages in thread
From: Leonid Vasiliev @ 2020-12-23 23:51 UTC (permalink / raw)
  To: Sergey Bronnikov, tarantool-patches
  Cc: Vladislav Shpilevoy, alexander.turenko

Hi!

On 23.12.2020 15:42, Sergey Bronnikov wrote:
> 
> On 23.12.2020 13:07, Leonid Vasiliev wrote:
>> Hi!
>> As far as I can see, the composition of the patchset has much changed
>> (also, it now has five patches instead of four). I suggest to send a new
>> clean version of the patchset.
>>
> 
> Could you take a look once again on v4?
> 
> https://lists.tarantool.org/pipermail/tarantool-patches/2020-December/021602.html

Done. But, why "v4" prefixed with "PATCH v3"? I think this is just a
typo)

> 
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2020-12-23 23:51 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1607675470.git.sergeyb@tarantool.org>
2020-12-11  8:42 ` [Tarantool-patches] [PATCH 1/4] test: convert print to function and make quotes use consistent sergeyb
2020-12-13 17:58   ` Vladislav Shpilevoy
2020-12-14 11:44     ` Sergey Bronnikov
2020-12-15 10:05       ` Leonid Vasiliev
2020-12-15 11:51         ` Sergey Bronnikov
2020-12-20 16:47           ` Vladislav Shpilevoy
2020-12-23 12:34             ` Sergey Bronnikov
2020-12-11  8:42 ` [Tarantool-patches] [PATCH 2/4] test: make dict.items() compatible with Python 3.x sergeyb
2020-12-13 17:58   ` Vladislav Shpilevoy
2020-12-15 12:40   ` Leonid Vasiliev
2020-12-11  8:42 ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex " sergeyb
2020-12-15 11:55   ` Leonid Vasiliev
2020-12-16 14:04     ` Sergey Bronnikov
2020-12-17 18:26       ` Leonid Vasiliev
2020-12-22  8:15         ` [Tarantool-patches] [PATCH] test: make strings compatible with Python 3 sergeyb
2020-12-23  9:59           ` Leonid Vasiliev
2020-12-23 10:35             ` Sergey Bronnikov
2020-12-23 11:09               ` Leonid Vasiliev
2020-12-22  8:19         ` [Tarantool-patches] [PATCH 3/4] test: make convert to hex compatible with Python 3.x Sergey Bronnikov
2020-12-23 10:00           ` Leonid Vasiliev
2020-12-11  8:42 ` [Tarantool-patches] [PATCH 4/4] test: remove dead code in Python tests end extra newline sergeyb
2020-12-15 12:51   ` Leonid Vasiliev
2020-12-15 13:00     ` Sergey Bronnikov
2020-12-13 19:02 ` [Tarantool-patches] [PATCH v3 0/4] Support Python 3 in tests and PEPify source code Sergey Bronnikov
2020-12-23 10:07   ` Leonid Vasiliev
2020-12-23 12:42     ` Sergey Bronnikov
2020-12-23 23:51       ` Leonid Vasiliev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox