]> git.lyx.org Git - lyx.git/blobdiff - development/autotests/keytest.py
keytests: Print proc-info in case lyx_status() signals "dead"
[lyx.git] / development / autotests / keytest.py
index a48f85676b0a606df9cff85c29deedd23f01ab26..7bf240c1371d834a27c012d1f66cb697354dc57b 100755 (executable)
@@ -8,6 +8,7 @@
 # Adapted by Tommaso Cucinotta from the original MonKey Test by
 # John McCabe-Dansted.
 
+from __future__ import print_function
 import random
 import os
 import re
@@ -16,7 +17,7 @@ import time
 #from subprocess import call
 import subprocess
 
-print 'Beginning keytest.py'
+print('Beginning keytest.py')
 
 FNULL = open('/dev/null', 'w')
 
@@ -78,7 +79,7 @@ class CommandSourceFromFile(CommandSource):
         self.infile.close()
         linesbak = self.lines
         self.p = p
-        print p, self.p, 'self.p'
+        print(p, self.p, 'self.p')
         self.i = 0
         self.count = 0
         self.loops = 0
@@ -88,10 +89,10 @@ class CommandSourceFromFile(CommandSource):
 
         if p > 0.001:
             if random.uniform(0, 1) < 0.5:
-                print 'randomdrop_independant\n'
+                print('randomdrop_independant\n')
                 self.randomdrop_independant()
             else:
-                print 'randomdrop_slice\n'
+                print('randomdrop_slice\n')
                 self.randomdrop_slice()
         if screenshot_out is None:
             count_atleast = 100
@@ -113,11 +114,11 @@ class CommandSourceFromFile(CommandSource):
         self.lines = []
         for l in origlines:
             if random.uniform(0, 1) < self.p:
-                print 'Randomly dropping line ' + l + '\n'
+                print('Randomly dropping line ' + l + '\n')
             else:
                 self.lines.append(l)
-        print 'LINES\n'
-        print self.lines
+        print('LINES\n')
+        print(self.lines)
         sys.stdout.flush()
 
     def randomdrop_slice(self):
@@ -131,10 +132,10 @@ class CommandSourceFromFile(CommandSource):
         drop_mid = random.randint(0, num_lines)
         drop_start = max(drop_mid - num_drop / 2, 0)
         drop_end = min(drop_start + num_drop, num_lines)
-        print drop_start, drop_mid, drop_end
-        print lines
+        print(drop_start, drop_mid, drop_end)
+        print(lines)
         del lines[drop_start:drop_end]
-        print lines
+        print(lines)
         self.lines = lines
 
     def getCommand(self):
@@ -151,98 +152,228 @@ class CommandSourceFromFile(CommandSource):
         self.i = self.i + 1
         return line
 
+def get_proc_pid(proc_name):
+    pid=os.popen("pidof " + proc_name).read().rstrip()
+    return pid
+
+wlistreg = re.compile(r'^(0x[0-9a-f]{5,9})\s+[^\s]+\s+([0-9]+)\s.*$')
+def get_proc_win_id(pid, ignoreid):
+    nlist = os.popen("wmctrl -l -p").read()
+    wlist = nlist.split("\n")
+    for item in wlist:
+        m = wlistreg.match(item)
+        if m:
+            win_id = m.group(1)
+            win_pid = m.group(2)
+            if win_pid == pid:
+                if win_id != ignoreid:
+                    return win_id
+    return None
+
 def lyx_exists():
     if lyx_pid is None:
         return False
     fname = '/proc/' + lyx_pid + '/status'
     return os.path.exists(fname)
 
-def lyx_sleeping():
-    fname = '/proc/' + lyx_pid + '/status'
-    f = open(fname, 'r')
-    lines = f.readlines()
-    sleeping = lines[1].find('(sleeping)') > 0
-
-    # print 'LYX_STATE', lines[1] , 'SLEEPING=', sleeping
-
-    return sleeping
-
 
 # Interruptible os.system()
 def intr_system(cmd, ignore_err = False):
-    print "Executing " + cmd + "\n"
+    print("Executing " + cmd)
     ret = os.system(cmd)
     if os.WIFSIGNALED(ret):
         raise KeyboardInterrupt
     if ret != 0 and not ignore_err:
-        raise BaseException("command failed.")
+        raise BaseException("command failed:" + cmd)
     return ret
 
+statreg = re.compile(r'^State:.*\(([a-z]+)\)')
 
-def sendKeystring(keystr, LYX_PID):
+resstatus = []
+def printresstatus():
+    for line in resstatus:
+        line = line.rstrip()
+        print("    " + line.rstrip())
+    print('End of /proc-lines')
 
-    # print "sending keystring "+keystr+"\n"
+def lyx_status(pid):
+    resstatus = []
+    if lyx_pid is None:
+        return "dead"
+    fname = '/proc/' + pid + '/status'
+    status = "dead"
+    try:
+        f = open(fname)
+        found = False
+        for line in f:
+            resstatus.extend([line])
+            m = statreg.match(line)
+            if m:
+                status = m.group(1)
+                found = True
+        f.close()
+        return status
+    except IOError as e:
+        print("I/O error({0}): {1}".format(e.errno, e.strerror))
+        return "dead"
+    except:
+        print("Unexpected error:", sys.exc_info()[0])
+        return "dead"
+    return status
+
+# Return true if LyX (identified via lyx_pid) is sleeping
+def lyx_sleeping():
+    return lyx_status(lyx_pid) == "sleeping"
+
+# Return true if LyX (identified via lyx_pid) is zombie
+def lyx_zombie():
+    return lyx_status(lyx_pid) == "zombie"
 
-    if not re.match(".*\w.*", keystr):
-        print 'print .' + keystr + '.\n'
-        keystr = 'a'
+def lyx_dead():
+    status = lyx_status(lyx_pid)
+    return (status == "dead") or (status == "zombie")
+
+def wait_until_lyx_sleeping():
     before_secs = time.time()
-    while lyx_exists() and not lyx_sleeping():
-        time.sleep(0.02)
-        sys.stdout.flush()
+    while True:
+        status = lyx_status(lyx_pid)
+        if status == "sleeping":
+            return
+        if (status == "dead") or (status == "zombie"):
+            print('Lyx is dead, exiting')
+            printresstatus()
+            sys.stdout.flush()
+            os._exit(1)
         if time.time() - before_secs > 180:
-            print 'Killing due to freeze (KILL_FREEZE)'
+            print('Killing due to freeze (KILL_FREEZE)')
 
             # Do profiling, but sysprof has no command line interface?
             # intr_system("killall -KILL lyx")
-
+            printresstatus()
+            sys.stdout.flush()
             os._exit(1)
+        time.sleep(0.02)
+
+def sendKeystringLocal(keystr, LYX_PID):
+    wait_until_lyx_sleeping()
     if not screenshot_out is None:
-        while lyx_exists() and not lyx_sleeping():
-            time.sleep(0.02)
-            sys.stdout.flush()
-        print 'Making Screenshot: ' + screenshot_out + ' OF ' + infilename
+        print('Making Screenshot: ' + screenshot_out + ' OF ' + infilename)
         time.sleep(0.2)
         intr_system('import -window root '+screenshot_out+str(x.count)+".png")
         time.sleep(0.1)
-    sys.stdout.flush()
     actual_delay = key_delay
     if actual_delay == '':
         actual_delay = def_delay
-    if not xvkbd_hacked:
-        subprocess.call([xvkbd_exe, "-xsendevent", "-window", lyx_window_name,
-                         "-delay", actual_delay, "-text", keystr], stdout = FNULL, stderr = FNULL)
+    xvpar = [xvkbd_exe]
+    if qt_frontend == 'QT5':
+        xvpar.extend(["-jump-pointer", "-no-back-pointer"])
+    else:
+        xvpar.extend(["-xsendevent"])
+    if lyx_other_window_name is None:
+        xvpar.extend(["-window", lyx_window_name])
     else:
-        subprocess.call([xvkbd_exe, "-no_root", "-wait_idle", lyx_pid,
-                         "-xsendevent", "-window", lyx_window_name,
-                         "-delay", actual_delay, "-text", keystr], stdout = FNULL, stderr = FNULL)
+        xvpar.extend(["-window", lyx_other_window_name])
+    xvpar.extend(["-delay", actual_delay, "-text", keystr])
+    print("Sending \"" + keystr + "\"")
+    subprocess.call(xvpar, stdout = FNULL, stderr = FNULL)
+    sys.stdout.flush()
+
+Axreg = re.compile(r'^(.*)\\Ax([^\\]*)(.*)$')
+returnreg = re.compile(r'(\\\[[A-Z][a-z]+\])(.*)$')
+
+# recursive wrapper around sendKeystringLocal()
+# handling \Ax-entries
+def sendKeystringAx(line, LYX_PID):
+    global key_delay
+    saved_delay = key_delay
+    m = Axreg.match(line)
+    if m:
+        prefix = m.group(1)
+        content = m.group(2)
+        rest = m.group(3);
+        if prefix != "":
+            # since (.*) is greedy, check prefix for '\Ax' again
+            sendKeystringAx(prefix, LYX_PID)
+        sendKeystringLocal('\Ax', LYX_PID)
+        time.sleep(0.1)
+        m2 = returnreg.match(rest)
+        if m2:
+            line = m2.group(2)
+            ctrlk = m2.group(1)
+            key_delay = "1"
+            sendKeystringLocal(content + ctrlk, LYX_PID)
+            key_delay = saved_delay
+            time.sleep(controlkey_delay)
+            if line != "":
+                sendKeystringLocal(line, LYX_PID)
+        else:
+            if content != "":
+                sendKeystringLocal(content, LYX_PID)
+            if rest != "":
+                sendKeystringLocal(rest, LYX_PID)
+    else:
+        if line != "":
+            sendKeystringLocal(line, LYX_PID)
+
+specialkeyreg = re.compile(r'(.+)(\\[AC]([a-zA-Z]|\\\[[A-Z][a-z]+\]).*)$')
+# Split line at start of each meta or controll char
+
+def sendKeystringAC(line, LYX_PID):
+    m = specialkeyreg.match(line)
+    if m:
+        first = m.group(1)
+        second = m.group(2)
+        sendKeystringAC(first, LYX_PID)
+        sendKeystringAC(second, LYX_PID)
+    else:
+        sendKeystringAx(line, LYX_PID)
+
+controlkeyreg = re.compile(r'^(.*\\\[[A-Z][a-z]+\])(.*\\\[[A-Z][a-z]+\])(.*)$')
+# Make sure, only one of \[Return], \[Tab], \[Down], \[Home] etc are in one sent line
+# e.g. split the input line on each keysym
+def sendKeystringRT(line, LYX_PID):
+    m = controlkeyreg.match(line)
+    if m:
+        first = m.group(1)
+        second = m.group(2)
+        third = m.group(3)
+        sendKeystringRT(first, LYX_PID)
+        time.sleep(controlkey_delay)
+        sendKeystringRT(second, LYX_PID)
+        time.sleep(controlkey_delay)
+        if third != "":
+            sendKeystringRT(third, LYX_PID)
+    else:
+        sendKeystringAC(line, LYX_PID)
 
 def system_retry(num_retry, cmd):
     i = 0
     rtn = intr_system(cmd)
     while ( ( i < num_retry ) and ( rtn != 0) ):
         i = i + 1
-       rtn = intr_system(cmd)
+        rtn = intr_system(cmd)
         time.sleep(1)
     if ( rtn != 0 ):
-        print "Command Failed: "+cmd
-        print " EXITING!\n"
+        print("Command Failed: "+cmd)
+        print(" EXITING!\n")
         os._exit(1)
 
 def RaiseWindow():
     #intr_system("echo x-session-manager PID: $X_PID.")
     #intr_system("echo x-session-manager open files: `lsof -p $X_PID | grep ICE-unix | wc -l`")
     ####intr_system("wmctrl -l | ( grep '"+lyx_window_name+"' || ( killall lyx ; sleep 1 ; killall -9 lyx ))")
-    #intr_system("wmctrl -R '"+lyx_window_name+"' ;sleep 0.1")
+    print("lyx_window_name = " + lyx_window_name + "\n")
+    intr_system("wmctrl -R '"+lyx_window_name+"' ;sleep 0.1")
     system_retry(30, "wmctrl -i -a '"+lyx_window_name+"'")
 
 
 lyx_pid = os.environ.get('LYX_PID')
-print 'lyx_pid: ' + str(lyx_pid) + '\n'
+print('lyx_pid: ' + str(lyx_pid) + '\n')
 infilename = os.environ.get('KEYTEST_INFILE')
 outfilename = os.environ.get('KEYTEST_OUTFILE')
 max_drop = os.environ.get('MAX_DROP')
 lyx_window_name = os.environ.get('LYX_WINDOW_NAME')
+lyx_other_window_name = None
 screenshot_out = os.environ.get('SCREENSHOT_OUT')
 lyx_userdir = os.environ.get('LYX_USERDIR')
 
@@ -252,11 +383,11 @@ if max_loops is None:
 
 PACKAGE = os.environ.get('PACKAGE')
 if not PACKAGE is None:
-  print "PACKAGE = " + PACKAGE + "\n"
+  print("PACKAGE = " + PACKAGE + "\n")
 
 PO_BUILD_DIR = os.environ.get('PO_BUILD_DIR')
 if not PO_BUILD_DIR is None:
-  print "PO_BUILD_DIR = " + PO_BUILD_DIR + "\n"
+  print("PO_BUILD_DIR = " + PO_BUILD_DIR + "\n")
 
 lyx = os.environ.get('LYX')
 if lyx is None:
@@ -270,7 +401,13 @@ xvkbd_exe = os.environ.get('XVKBD_EXE')
 if xvkbd_exe is None:
     xvkbd_exe = "xvkbd"
 
-xvkbd_hacked = os.environ.get('XVKBD_HACKED') != None
+qt_frontend = os.environ.get('QT_FRONTEND')
+if qt_frontend is None:
+    qt_frontend = 'QT4'
+if qt_frontend == 'QT5':
+    controlkey_delay = 0.01
+else:
+    controlkey_delay = 0.4
 
 locale_dir = os.environ.get('LOCALE_DIR')
 if locale_dir is None:
@@ -278,7 +415,10 @@ if locale_dir is None:
 
 def_delay = os.environ.get('XVKBD_DELAY')
 if def_delay is None:
-    def_delay = '100'
+    if qt_frontend == 'QT5':
+        def_delay = '5'
+    else:
+        def_delay = '1'
 
 file_new_command = os.environ.get('FILE_NEW_COMMAND')
 if file_new_command is None:
@@ -292,69 +432,90 @@ if ResetCommand is None:
 if lyx_window_name is None:
     lyx_window_name = 'LyX'
 
-print 'outfilename: ' + outfilename + '\n'
-print 'max_drop: ' + max_drop + '\n'
+print('outfilename: ' + outfilename + '\n')
+print('max_drop: ' + max_drop + '\n')
 
 if infilename is None:
-    print 'infilename is None\n'
+    print('infilename is None\n')
     x = CommandSource()
-    print 'Using x=CommandSource\n'
+    print('Using x=CommandSource\n')
 else:
-    print 'infilename: ' + infilename + '\n'
+    print('infilename: ' + infilename + '\n')
     probability_we_drop_a_command = random.uniform(0, float(max_drop))
-    print 'probability_we_drop_a_command: '
-    print '%s' % probability_we_drop_a_command
-    print '\n'
+    print('probability_we_drop_a_command: ')
+    print('%s' % probability_we_drop_a_command)
+    print('\n')
     x = CommandSourceFromFile(infilename, probability_we_drop_a_command)
-    print 'Using x=CommandSourceFromFile\n'
+    print('Using x=CommandSourceFromFile\n')
 
 outfile = open(outfilename, 'w')
 
 if not lyx_pid is None:
     RaiseWindow()
-    sendKeystring("\Afn", lyx_pid)
+    # Next command is language dependent
+    #sendKeystringRT("\Afn", lyx_pid)
 
 write_commands = True
 failed = False
+lineempty = re.compile(r'^\s*$')
 
 while not failed:
     #intr_system('echo -n LOADAVG:; cat /proc/loadavg')
     c = x.getCommand()
     if c is None:
         break
-    if c.strip() == "":
+
+    # Do not strip trailing spaces, only check for 'empty' lines
+    if lineempty.match(c):
         continue
     outfile.writelines(c + '\n')
     outfile.flush()
     if c[0] == '#':
-        print "Ignoring comment line: " + c
+        print("Ignoring comment line: " + c)
     elif c[0:9] == 'TestBegin':
-        print "\n"
-        lyx_pid=os.popen("pidof " + lyx).read()
+        print("\n")
+        lyx_pid=get_proc_pid(lyx)
         if lyx_pid != "":
-            print "Found running instance(s) of LyX: " + lyx_pid + ": killing them all\n"
+            print("Found running instance(s) of LyX: " + lyx_pid + ": killing them all\n")
             intr_system("killall " + lyx, True)
             time.sleep(0.5)
             intr_system("killall -KILL " + lyx, True)
         time.sleep(0.2)
-        print "Starting LyX . . ."
+        print("Starting LyX . . .")
         if lyx_userdir is None:
             intr_system(lyx_exe + c[9:] + "&")
         else:
             intr_system(lyx_exe + " -userdir " + lyx_userdir + " " + c[9:] + "&")
-        while True:
-            lyx_pid=os.popen("pidof " + lyx).read().rstrip()
+        count = 5
+        old_lyx_pid = "-7"
+        old_lyx_window_name = None
+        print("Waiting for LyX to show up . . .")
+        while count > 0:
+            lyx_pid=get_proc_pid(lyx)
+            if lyx_pid != old_lyx_pid:
+                print('lyx_pid=' + lyx_pid)
+                old_lyx_pid = lyx_pid
             if lyx_pid != "":
-                lyx_window_name=os.popen("wmctrl -l -p | grep ' " + str(lyx_pid) +  " ' | cut -d ' ' -f 1").read().rstrip()
-                if lyx_window_name != "":
+                lyx_window_name=get_proc_win_id(lyx_pid, "")
+                if not lyx_window_name is None:
+                    if old_lyx_window_name != lyx_window_name:
+                        print('lyx_win=' + lyx_window_name, '\n')
+                        old_lyx_window_name = lyx_window_name
                     break
-            print 'lyx_win: ' + lyx_window_name + '\n'
-            print "Waiting for LyX to show up . . ."
+            else:
+                count = count - 1
             time.sleep(1)
-        print 'lyx_pid: ' + lyx_pid + '\n'
-        print 'lyx_win: ' + lyx_window_name + '\n'
+        if count <= 0:
+            print('Timeout: could not start ' + lyx_exe, '\n')
+            sys.stdout.flush()
+            failed = True
+        else:
+            print('lyx_pid: ' + lyx_pid)
+            print('lyx_win: ' + lyx_window_name)
+            sendKeystringLocal("\C\[Home]", lyx_pid)
+            time.sleep(controlkey_delay)
     elif c[0:5] == 'Sleep':
-        print "Sleeping for " + c[6:] + " seconds\n"
+        print("Sleeping for " + c[6:] + " seconds")
         time.sleep(float(c[6:]))
     elif c[0:4] == 'Exec':
         cmd = c[5:].rstrip()
@@ -362,53 +523,90 @@ while not failed:
     elif c == 'Loop':
         outfile.close()
         outfile = open(outfilename + '+', 'w')
-        print 'Now Looping'
+        print('Now Looping')
     elif c == 'RaiseLyx':
-        print 'Raising Lyx'
+        print('Raising Lyx')
         RaiseWindow()
     elif c[0:4] == 'KK: ':
         if lyx_exists():
-            sendKeystring(c[4:], lyx_pid)
+            sendKeystringRT(c[4:], lyx_pid)
         else:
             ##intr_system('killall lyx; sleep 2 ; killall -9 lyx')
             if lyx_pid is None:
-              print 'No path /proc/xxxx/status, exiting'
+              print('No path /proc/xxxx/status, exiting')
             else:
-              print 'No path /proc/' + lyx_pid + '/status, exiting'
+              print('No path /proc/' + lyx_pid + '/status, exiting')
             os._exit(1)
     elif c[0:4] == 'KD: ':
         key_delay = c[4:].rstrip('\n')
-        print 'Setting DELAY to ' + key_delay + '.\n'
+        print('Setting DELAY to ' + key_delay)
     elif c == 'Loop':
         RaiseWindow()
-        sendKeystring(ResetCommand, lyx_pid)
+        sendKeystringRT(ResetCommand, lyx_pid)
     elif c[0:6] == 'Assert':
         cmd = c[7:].rstrip()
-        print "Executing " + cmd
         result = intr_system(cmd)
         failed = failed or (result != 0)
-        print "result=" + str(result) + ", failed=" + str(failed)
+        print("result=" + str(result) + ", failed=" + str(failed))
+    elif c[0:15] == 'TestEndWithKill':
+        cmd = c[16:].rstrip()
+        if lyx_dead():
+            print("LyX instance not found because of crash or assert !\n")
+            failed = True
+        else:
+            print("    ------------    Forcing kill of lyx instance: " + str(lyx_pid) + "    ------------")
+            # This line below is there only to allow lyx to update its log-file
+            sendKeystringLocal("\[Escape]", lyx_pid)
+            while not lyx_dead():
+                intr_system("kill -9 " + str(lyx_pid), True);
+                time.sleep(0.5)
+            if cmd != "":
+                print("Executing " + cmd)
+                result = intr_system(cmd)
+                failed = failed or (result != 0)
+                print("result=" + str(result) + ", failed=" + str(failed))
+            else:
+                print("failed=" + str(failed))
     elif c[0:7] == 'TestEnd':
-        time.sleep(0.5)
-        if not lyx_exists():
-            print "LyX instance not found because of crash or assert !\n"
-            failed = true
+        #lyx_other_window_name = None
+        if lyx_dead():
+            print("LyX instance not found because of crash or assert !\n")
+            failed = True
         else:
-            print "Terminating lyx instance: " + str(lyx_pid) + "\n"
-            intr_system("kill -9 " + str(lyx_pid), True);
-            while lyx_exists():
-                print "Waiting for lyx to die...\n"
+            print("    ------------    Forcing quit of lyx instance: " + str(lyx_pid) + "    ------------")
+            # \Ax Enter command line is sometimes blocked
+            # \[Escape] works after this
+            sendKeystringAx("\Ax\[Escape]", lyx_pid)
+            time.sleep(controlkey_delay)
+            # now we should be outside any dialog
+            # and so the function lyx-quit should work
+            sendKeystringLocal("\Cq", lyx_pid)
+            time.sleep(0.5)
+            if lyx_sleeping():
+                # probably waiting for Save/Discard/Abort, we select 'Discard'
+                sendKeystringRT("\[Tab]\[Return]", lyx_pid)
+                lcount = 0
+            else:
+                lcount = 1
+            while not lyx_dead():
+                lcount = lcount + 1
+                if lcount > 20:
+                    print("LyX still up, killing process and waiting for it to die...\n")
+                    intr_system("kill -9 " + str(lyx_pid), True);
                 time.sleep(0.5)
         cmd = c[8:].rstrip()
-        print "Executing " + cmd
-        result = intr_system(cmd)
-        failed = failed or (result != 0)
-        print "result=" + str(result) + ", failed=" + str(failed)
+        if cmd != "":
+            print("Executing " + cmd)
+            result = intr_system(cmd)
+            failed = failed or (result != 0)
+            print("result=" + str(result) + ", failed=" + str(failed))
+        else:
+            print("failed=" + str(failed))
     elif c[0:4] == 'Lang':
         lang = c[5:].rstrip()
-        print "Setting LANG=" + lang + "\n"
+        print("Setting LANG=" + lang)
         os.environ['LANG'] = lang
-        os.environ['LANGUAGE'] = lang
+        os.environ['LC_ALL'] = lang
 # If it doesn't exist, create a link <locale_dir>/<country-code>/LC_MESSAGES/lyx<version-suffix>.mo
 # pointing to the corresponding .gmo file. Needed to let lyx find the right translation files.
 # See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg165613.html
@@ -418,7 +616,7 @@ while not failed:
         else:
             ccode = lang
 
-        print "Setting LANGUAGE=" + ccode + "\n"
+        print("Setting LANGUAGE=" + ccode)
         os.environ['LANGUAGE'] = ccode
 
         idx = lang.find("_")
@@ -431,10 +629,10 @@ while not failed:
           # on cmake-build there is no Makefile in this directory
           # so PACKAGE has to be provided
           if os.path.exists(lyx_dir + "/Makefile"):
-            print "Executing: grep 'PACKAGE =' " + lyx_dir + "/Makefile | sed -e 's/PACKAGE = \(.*\)/\\1/'"
+            print("Executing: grep 'PACKAGE =' " + lyx_dir + "/Makefile | sed -e 's/PACKAGE = \(.*\)/\\1/'")
             lyx_name = os.popen("grep 'PACKAGE =' " + lyx_dir + "/Makefile | sed -e 's/PACKAGE = \(.*\)/\\1/'").read().rstrip()
           else:
-            print 'Could not determine PACKAGE name needed for translations\n'
+            print('Could not determine PACKAGE name needed for translations\n')
             failed = True
         else:
           lyx_name = PACKAGE
@@ -449,13 +647,13 @@ while not failed:
         else:
             intr_system("ln -s " + PO_BUILD_DIR + "/" + short_code + ".gmo " + locale_dir + "/" + ccode + "/LC_MESSAGES/" + lyx_name + ".mo")
     else:
-        print "Unrecognised Command '" + c + "'\n"
+        print("Unrecognised Command '" + c + "'\n")
         failed = True
 
-print "Test case terminated: "
+print("Test case terminated: ")
 if failed:
-    print "FAIL\n"
+    print("FAIL\n")
     os._exit(1)
 else:
-    print "Ok\n"
+    print("Ok\n")
     os._exit(0)