]> granicus.if.org Git - recode/commitdiff
Port to Python 3 (fix #15)
authorReuben Thomas <rrt@sc3d.org>
Tue, 10 Sep 2019 16:41:18 +0000 (17:41 +0100)
committerReuben Thomas <rrt@sc3d.org>
Tue, 10 Sep 2019 21:12:26 +0000 (22:12 +0100)
20 files changed:
.travis.yml
HACKING.org
README.org
appveyor.yml
build-aux/appveyor-install.sh
configure.ac
src/mergelex.py
tables.py
tests/.gitignore
tests/Makefile.am
tests/Recode.pyx
tests/common.py
tests/pytest
tests/setup.py.in
tests/t40_java.py
tests/t50_methods.py
tests/t70_inferenz.py
tests/t80_error.py
tests/t90_bigauto.py
tests/valgrind-python.supp

index b374bcf1d3a8e743401821b4b97db2c7a3a7bab8..522b618dae6aff7d140f10a1792367c3216e67eb 100644 (file)
@@ -8,8 +8,8 @@ addons:
     sources:
       - ubuntu-toolchain-r-test
     packages: &default_deps
-      - python-dbg
-      - cython
+      - python3-dbg
+      - cython3
       - flex
       - help2man
       - autopoint
@@ -26,16 +26,21 @@ matrix:
     - os: linux
       env:
         - COMPILER=gcc-5
-        - PYTHON=/usr/bin/python-dbg
-        - DISTCHECK_CONFIGURE_FLAGS="PYTHON=/usr/bin/python-dbg"
+        - PYTHON=/usr/bin/python3-dbg
+        - CYTHON=/usr/bin/cython3
+        - DISTCHECK_CONFIGURE_FLAGS="PYTHON=/usr/bin/python3-dbg CYTHON=/usr/bin/cython3"
     - os: osx
       osx_image: xcode9.2
       env:
         - LDFLAGS="-L/usr/local/opt/flex/lib -L/usr/local/opt/texinfo/lib"
         - CPPFLAGS="-I/usr/local/opt/flex/include"
+        - PYTHON=/usr/local/bin/python3
     - compiler: gcc
       env:
         - COMPILER=gcc-6
+        - PYTHON=/usr/bin/python3-dbg
+        - CYTHON=/usr/bin/cython3
+        - DISTCHECK_CONFIGURE_FLAGS="PYTHON=/usr/bin/python3-dbg CYTHON=/usr/bin/cython3"
       addons:
         apt:
           sources:
@@ -46,12 +51,12 @@ matrix:
 
 before_install:
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew unlink python ; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python@2 flex help2man texinfo ; fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pip install cython ; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python ; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install flex help2man texinfo ; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pip3 install cython ; fi
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/flex/bin:/usr/local/opt/texinfo/bin:/usr/local/opt/gettext/bin:$PATH" ; fi
 
 script:
   - ./bootstrap
-  - ./configure --enable-silent-rules CC=$COMPILER
+  - ./configure --enable-silent-rules CC=$COMPILER $DISTCHECK_CONFIGURE_FLAGS
   - make && make distcheck
index e9b301f81c29ac84a1a4119e075554ca8ebdae85..a68acd1f392841e8cde04fa9e0357e932b727f06 100644 (file)
@@ -17,7 +17,7 @@ m4, GNU Make, libtool, Autoconf, automake, Gettext, Help2man, Perl, Flex, Python
 
 * Testing with Valgrind
 
-Currently, Valgrind does not play nice with CPython, even with a fairly extensive suppressions file. It works on Ubuntu with the debug build of Python, from the package ~python-dbg~. Having installed this, configure with the option ~PYTHON=/usr/bin/python-dbg~ (the full path is required).
+Currently, Valgrind does not play nice with CPython, even with a fairly extensive suppressions file. It works on Ubuntu with the debug build of Python, from the package ~python3-dbg~. Having installed this, configure with the option ~PYTHON=/usr/bin/python3-dbg~ (the full path is required).
 
 To ensure that Valgrind is used for testing releases too, the above setting can be added to ~DISTCHECK_CONFIGURE_FLAGS~.
 
index 6fb0b2ec18c0595093540634849811d00606c8bc..29efbe54ea0eb7f6c546ff91343187f99f285832 100644 (file)
@@ -38,9 +38,9 @@ Consider documentation errors as bugs, and report them as such.  If
 you develop anything pertaining to Recode or have suggestions, please
 share them on GitHub.
 
-The [[https://github.com/pinard/Recode][Git repository]] for Recode gives access, through the magic of Git
-and GitHub, to all distribution releases, would they be actual or
-past, pretest or official, as well as individual files.
+The [[https://github.com/pinard/Recode][Git repository]] for Recode gives access, through the magic of Git and
+GitHub, to all distribution releases, be they actual or past, pretest or
+official, as well as individual files.
 
 * Installation
 ** In a hurry?
@@ -49,17 +49,15 @@ See =INSTALL=.
 More fine-grained instructions follow.
 
 ** Prerequisites
-Simple installation of Recode requires the usual tools and facilities
-as those needed for most GNU packages.  If not already bundled with
-your system, you also need to pre-install [[http://www.python.org][Python]], version 2.2 or
-later.
-
-It is also convenient to have some *iconv* library already present on
-your system, this much extends Recode capabilities, especially in the
-area of Asiatic character sets.  GNU *libc*, as found on Linux systems
-and a few others, already has such an *iconv* library.  Otherwise, you
-might consider pre-installing the [[http://www.gnu.org/software/libiconv/][portable libiconv]], written by Bruno
-Haible.
+Simple installation of Recode requires the usual tools and facilities as
+those needed for most GNU packages.  If not already bundled with your
+system, you also need to install [[https://www.python.org][Python]], version 3.5 or later.
+
+It is also convenient to have some *iconv* library already present on your
+system, this much extends Recode capabilities, especially in the area of
+Asiatic character sets.  GNU *libc*, as found on Linux systems and a few
+others, already has such an *iconv* library.  Otherwise, you might consider
+installing the [[https://www.gnu.org/software/libiconv/][portable libiconv]], written by Bruno Haible.
 
 ** Getting a release
 Source files and various distributions (either latest, prestest, or
index 27ebd7896abedea0ed439e1392cf23b44b65ff31..061139c0de92e3dc12cfe75cbca99bc3e17fa7b9 100644 (file)
@@ -4,7 +4,6 @@ clone_folder: c:\projects\recode
 environment:
   global:
     VERBOSE: 1 # Get test logs in output
-    CONFIGURE_FLAGS: PYTHON=python2 CYTHON=cython2
   matrix:
     # - MSYSTEM: MSYS (no cython available)
     - MSYSTEM: MINGW64
index f584a8a5098b455698cb6908f3019ba32269f84e..445c745983053156c3f972376c2ad79f3cec9b1d 100644 (file)
@@ -18,4 +18,4 @@ case $MSYSTEM in
 esac
 
 # Build dependencies
-pacman --noconfirm -S rsync mingw-w64-$MINGW_BITS-python2 mingw-w64-$MINGW_BITS-cython2
+pacman --noconfirm -S rsync mingw-w64-$MINGW_BITS-python3 mingw-w64-$MINGW_BITS-cython
index 475c6c3b96ccaac355cb3d40c273b65b1d038c6c..e7bb60b67fb4068d1156b898c84d357ff4b01969 100644 (file)
@@ -37,7 +37,7 @@ AC_PROG_CC_C99
 gl_EARLY
 LT_INIT
 AC_PROG_LEX
-AM_PATH_PYTHON([2.2])
+AM_PATH_PYTHON([3.5])
 gl_INIT
 
 dnl help2man
index e92a1c06aaa9ead43010882be543ccaa5e631103..c74134919149beec4e63024d47bf168a2f13c02b 100644 (file)
@@ -57,7 +57,9 @@ definitions = {}
 section = 3
 
 while True:
-    line = sys.stdin.readline()
+    # FIXME: Treating all the input as latin1 is a hack: some of the files
+    # we read are UTF-8 encoded.
+    line = sys.stdin.buffer.readline().decode('latin1')
     if not line:
         break
 
index c0c4f921cbf201aae1242130100d8d952a4f3d0c..1227472b189ad254870ff1e4d8d94e4372fdc318 100755 (executable)
--- a/tables.py
+++ b/tables.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 # -*- coding: utf-8 -*-
 # Automatically derive Recode table files from various sources.
 # Copyright © 1993, 1994, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
@@ -40,7 +40,7 @@ from Keld's chset* packages.  The digesting order is usually important.
 When `-F' and `-n' are used, process Alain's tables.
 """
 
-import re, sys
+import re, sys, io
 
 # Character constants.
 REPLACEMENT_CHARACTER = 0xFFFD
@@ -200,12 +200,11 @@ class Charnames(Options):
 
     def digest_french(self, input):
         self.preset_french()
-        fold_table = range(256)
-        for before, after in map(
-                None,
+        fold_table = list(range(256))
+        for before, after in zip(
                 u'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÂÇÈÉÊÎÏÑÔÖÛ'.encode('ISO-8859-1'),
                 u'abcdefghijklmnopqrstuvwxyzàâçèéêîïñôöû'.encode('ISO-8859-1')):
-            fold_table[ord(before)] = ord(after)
+            fold_table[before] = after
         folding = ''.join(map(chr, fold_table))
         ignorables = (
                 u'<commande>'.encode('ISO-8859-1'),
@@ -267,7 +266,7 @@ class Charnames(Options):
             u"séparateur d'article (rs)",                        # 001E
             u"séparateur de sous-article (us)",                  # 001F
             ):
-            self.declare(ucs, text.encode('ISO-8859-1'))
+            self.declare(ucs, text)
             ucs += 1
         ucs = 0x007F
         for text in (
@@ -305,7 +304,7 @@ class Charnames(Options):
             u"message privé (pm)",                               # 009E
             u"commande de progiciel (apc)",                      # 009F
             ):
-            self.declare(ucs, text.encode('ISO-8859-1'))
+            self.declare(ucs, text)
             ucs += 1
 
     def declare(self, ucs, text):
@@ -333,18 +332,18 @@ class Charnames(Options):
         # the second cycling faster from 1 to 255.
         if run.verbose:
             sys.stdout.write('  sorting words...')
-        pairs = map(self.presort_word, self.code_map.keys())
+        pairs = list(map(self.presort_word, self.code_map.keys()))
         pairs.sort()
-        words = map(lambda pair: pair[1], pairs)
+        words = list(map(lambda pair: pair[1], pairs))
         pairs = None
         if run.verbose:
             sys.stdout.write(' %d of them\n' % len(words))
         count = len(words)
-        singles = (255 * 255 - count) / 254
+        singles = (255 * 255 - count) // 254
         # Transmit a few values for further usage by the C code.
         if run.verbose:
             sys.stdout.write('  sorting names...')
-        ucs2_table = self.charname_map.keys()
+        ucs2_table = list(self.charname_map.keys())
         ucs2_table.sort()
         if run.verbose:
             sys.stdout.write(' %d of them\n' % len(ucs2_table))
@@ -396,7 +395,7 @@ class Charnames(Options):
                     if code < 256:
                         write('\\%0.3o' % code)
                     else:
-                        write('\\%0.3o\\%0.3o' % (code / 256, code % 256))
+                        write('\\%0.3o\\%0.3o' % (code // 256, code % 256))
                 else:
                     sys.stdout.write('??? %s\n' % word)
             write('"},\n')
@@ -666,7 +665,7 @@ class Mnemonics(Options):
               'static const struct entry table[TABLE_LENGTH] =\n'
               '  {\n')
         count = 0
-        indices = self.mnemonic_map.keys()
+        indices = list(self.mnemonic_map.keys())
         indices.sort()
         for ucs2 in indices:
             text = self.mnemonic_map[ucs2]
@@ -680,7 +679,7 @@ class Mnemonics(Options):
               'static const unsigned short inverse[TABLE_LENGTH] =\n'
               '  {')
         count = 0
-        keys = inverse_map.keys()
+        keys = list(inverse_map.keys())
         keys.sort()
         for text in keys:
             if count % 10 == 0:
@@ -1124,7 +1123,7 @@ class Strips(Options):
             write = Output('fr-%s' % self.TEXINFO, noheader=True).write
         else:
             write = Output(self.TEXINFO, noheader=True).write
-        charsets = self.remark_map.keys()
+        charsets = list(self.remark_map.keys())
         charsets.sort()
         for charset in charsets:
             write('\n'
@@ -1160,13 +1159,15 @@ class Input:
 
     def __init__(self, name):
         self.name = name
-        self.input = file(name)
+        self.input = io.open(name, encoding='latin-1')
         self.line_count = 0
         sys.stdout.write("Reading %s\n" % name)
 
     def readline(self):
         self.line = self.input.readline()
         self.line_count += 1
+        if type(self.line) == bytes:
+            self.line = self.line.decode('utf-8')
         return self.line
 
     def warn(self, format, *args):
@@ -1192,7 +1193,7 @@ class Output:
 
     def __init__(self, name, noheader=False):
         self.name = name
-        self.write = file(name, 'w').write
+        self.write = open(name, 'w', encoding='utf-8').write
         sys.stdout.write("Writing %s\n" % name)
         if not noheader:
             self.write("""\
index 29d3df31ebb320a056ca9687d40bf9dd232f668a..2fb0ffbb7da6e69cda7eeb9a75809cc6cfab71c9 100644 (file)
@@ -4,3 +4,4 @@
 /dummy.c
 /unused-parameter.h
 /warn-on-use.h
+/Recode.cpython*
index cda31cb82e7bac7993a6af70b6db0c12bd482f86..68b894196c081ac5a409daa906644e4d45b4c7ee 100644 (file)
@@ -30,6 +30,9 @@ EXTRA_DIST = Recode.c Recode.pyx pytest common.py valgrind-python.supp $(SUITE)
 CLEANFILES = Recode@pyextext@ Recode_d@pyextext@ Recode.body.c
 DISTCLEANFILES = Recode.c
 
+clean-local:
+       rm -f *@pyextext@
+
 check-local: Recode@pyextext@
        if test -n "$(VALGRIND)"; then export VALGRIND='$(VALGRIND) --suppressions=$(srcdir)/valgrind-python.supp'; fi; \
        export LD_LIBRARY_PATH=$(top_builddir)/src/@objdir@; \
@@ -44,6 +47,6 @@ Recode@pyextext@: Recode.c setup.py
 
 Recode.c: Recode.pyx Makefile
        rm -f Recode.c && \
-       $(CYTHON) -o Recode.body.c $(srcdir)/Recode.pyx && \
+       $(CYTHON) -3 -o Recode.body.c $(srcdir)/Recode.pyx && \
        echo '#include "config.h"' > Recode.c && \
        cat Recode.body.c >> Recode.c
index 0b3e0c7719865270e57819bc7d966d7c2dc563cb..a7982a2ce29f2d6de48b26565885f9b896646baa 100644 (file)
@@ -268,7 +268,7 @@ cdef extern from "common.h":
 
     struct strip_data:
         recode_ucs2 *pool
-        short offset[256 / STRIP_SIZE_]
+        short offset[256 // STRIP_SIZE_]
 
     struct ucs2_to_byte:
         recode_ucs2 code
index 2d62009ef366a1b11f26c793386d2031594483aa..6156a9e99576ce2d4e106f5dab8e00824592fd4f 100644 (file)
@@ -24,8 +24,8 @@ run = Run()
 def external(flag):
     run.external = flag
 
-def request(text):
-    run.request = text
+def request(text, encoding='utf-8'):
+    run.request = bytes(text, encoding)
 
 # Functions only meant to be imported into real testing modules, where
 # pytest is meant to find and use them.
@@ -66,34 +66,46 @@ def external_output(command):
         output = e.output
     return output
 
-def recode_output(input):
+def recode_output(input, encoding='utf-8'):
+    if type(input) != bytes:
+        input = bytes(input, encoding)
     if run.external:
-        file(run.work, 'wb').write(input)
+        open(run.work, 'wb').write(input)
         return external_output('$R %s < %s' % (run.request, run.work))
     if outer is None:
         py.test.skip()
     return outer.recode(run.request, input)
 
-def recode_iconv_output(input):
+def recode_iconv_output(input, encoding='utf-8'):
+    if type(input) != bytes:
+        input = bytes(input, encoding)
     if run.external or outer_iconv is None:
         py.test.skip()
     return outer_iconv.recode(run.request, input)
 
-def recode_back_output(input):
-    before, after = run.request.split('..')
+def recode_back_output(input, encoding='utf-8'):
+    if type(input) != bytes:
+        input = bytes(input, encoding)
+    before, after = run.request.split(b'..')
     if run.external:
-        file(run.work, 'wb').write(input)
-        external_output('$R %s %s' % (run.request, run.work))
-        return external_output('$R %s..%s < %s' % (after, before, run.work))
+        open(run.work, 'wb').write(input)
+        external_output(b'$R %s %s' % (run.request, run.work))
+        return external_output(b'$R %s..%s < %s' % (after, before, run.work))
     if outer is None:
         py.test.skip()
     temp = outer.recode(run.request, input)
-    return outer.recode('%s..%s' % (after, before), temp)
+    return outer.recode(b'%s..%s' % (after, before), temp)
 
-def validate(input, expected):
+def validate(input, expected, encoding='utf-8'):
     output = recode_output(input)
+    if type(input) != bytes:
+        output = output.decode(encoding)
+    import sys
+    print(type(input), type(output), type(expected))
     assert_or_diff(output, expected)
 
-def validate_back(input):
+def validate_back(input, encoding='utf-8'):
     output = recode_back_output(input)
+    if type(input) != bytes:
+        output = output.decode(encoding)
     assert_or_diff(output, input)
index 44895924c2707fe2fefdef735cdbd93b10eedd37..44df1c4d6273298da56ce0fd26398b4df3d26fb8 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 # Copyright © 2005 Progiciels Bourbeau-Pinard inc.
 # François Pinard <pinard@iro.umontreal.ca>, 2005.
@@ -41,7 +41,7 @@ least one such failed test, the return status of this program is non-zero.
 
 __metaclass__ = type
 import inspect, os, sys, time, traceback
-from StringIO import StringIO
+from io import StringIO
 
 # How many displayable characters in an output line.
 WIDTH = 79
@@ -143,7 +143,7 @@ class Main:
                                         (self.total_count + 1, file_name,
                                          None, None,
                                          None, None,
-                                         str(tracing.getvalue())))
+                                         tracing.getvalue()))
                             else:
                                 self.handle_module(file_name, module)
                         finally:
@@ -155,7 +155,7 @@ class Main:
                             else:
                                 text = u' ' + text
                             write(text + u'\n')
-            except Exit, exception:
+            except Exit as exception:
                 if not self.verbose:
                     write(u'\n')
                 write(u'\n* %s *\n' % str(exception))
@@ -214,7 +214,7 @@ class Main:
                        % (text, time.time() - start_time))
             write(summary)
         if self.save:
-            write = file(self.save, u'w').write
+            write = open(self.save, u'w').write
             for ordinal in self.failures:
                 write(u'%d\n' % ordinal)
         else:
@@ -263,14 +263,14 @@ class Main:
                 if getattr(object, u'disabled', False):
                     continue
                 minimum = None
-                for _, method in inspect.getmembers(objet, inspect.ismethod):
-                    number = method.im_func.func_code.co_firstlineno
+                for _, func in inspect.getmembers(objet, inspect.isfunction):
+                    number = func.__code__.co_firstlineno
                     if minimum is None or number < minimum:
                         minimum = number
                 if minimum is not None:
                     collection.append((minimum, name, objet, False))
             elif name.startswith(u'test_') and inspect.isfunction(objet):
-                code = objet.func_code
+                code = objet.__code__
                 collection.append((code.co_firstlineno, name, objet,
                                    bool(code.co_flags & 32)))
         if not collection:
@@ -293,11 +293,11 @@ class Main:
 
     def handle_class(self, prefix, classe):
         collection = []
-        for name, method in inspect.getmembers(classe, inspect.ismethod):
+        for name, func in inspect.getmembers(classe, inspect.isfunction):
             if name.startswith(u'test_'):
-                code = method.im_func.func_code
-                collection.append((code.co_firstlineno, name, method,
-                                   bool(code.co_flags & 32)))
+                code = func.__code__
+                collection.append((code.co_firstlineno, name, func,
+                                   bool(code.co_flags & inspect.CO_GENERATOR)))
         if not collection:
             return
         # FIXME: Should likely do module setup here!
@@ -316,7 +316,7 @@ class Main:
             # FIXME: Should likely do class setup here.
             try:
                 for counter, arguments in enumerate(function()):
-                    collection.append((prefix + u'/' + unicode(counter + 1),
+                    collection.append((prefix + u'/' + str(counter + 1),
                                        arguments[0], arguments[1:]))
             except Skipped:
                 return
@@ -383,7 +383,7 @@ class Main:
                     traceback.print_exc(file=tracing)
                     self.failures.append(
                         (self.total_count, prefix, function, arguments,
-                         stdout, stderr, str(tracing.getvalue())))
+                         stdout, stderr, tracing.getvalue()))
             if instance is not None and hasattr(instance, u'teardown_method'):
                 instance.teardown_method(function)
             self.did_tests_in_class = True
@@ -448,7 +448,7 @@ class Friendly_StreamWriter:
 
     def write(self, text):
         if not isinstance(text, unicode):
-            text = unicode(text, 'UTF-8')
+            text = text.encode('UTF-8')
         self.stream.write(text)
 
     def writelines(self, lines):
index a20ac820fe6eab2815fd194e48abcce1519e6efc..c19d27a3282a8d0aa3e4dad1a6d4ab48a7bb27f1 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 import os
@@ -23,8 +23,10 @@ if os.name == 'nt':
 try:
 
     if srcdir != '.':
-        buffer = file(os.path.join(srcdir, 'Recode.c')).read()
-        file('Recode.c', 'w').write(buffer)
+        with open(os.path.join(srcdir, 'Recode.c')) as f:
+            buffer = f.read()
+        with open('Recode.c', 'w') as f:
+            f.write(buffer)
 
     setup(ext_modules=[
         Extension('Recode', ['Recode.c'],
index 056a9b87bb30b7f47ea0c457d47bacfab072804c..28bac23b898f02c22fea387c47fdc9424a4e56a0 100644 (file)
@@ -2,7 +2,7 @@
 import common
 from common import setup_module, teardown_module, Recode, outer, assert_or_diff
 
-input = '''\
+input = b'''\
 Dear =DEorvard=F0ur,
 
 =AB O=F9 qu'il r=E9side, =E0 N=EEmes ou m=EAme Capharna=FCm, tout Fran=E7ai=
@@ -11,7 +11,7 @@ au r=F4le payera son d=FB d=E8s avant No=EBl, qu'il soit na=EFf ou r=E2leur=
 . =BB
 '''
 
-output = '''\
+output = b'''\
 Dear \u00deorvard\u00f0ur,
 
 \u00ab O\u00f9 qu'il r\u00e9side, \u00e0 N\u00eemes ou m\u00eame Capharna\u00fcm, tout Fran\u00e7ais inscrit
@@ -28,7 +28,7 @@ class Test:
     def test_2(self):
         # Block of lines from Java, without requiring BOM for each Unicode character.
         request = Recode.Request(outer)
-        request.scan('java..l1/qp')
+        request.scan(b'java..l1/qp')
         task = Recode.Task(request)
         task.set_byte_order_mark(False)
         task.set_input(output)
index 696bb28b11e8dcb5fd396eed474e444ed73a0e6c..3a949c735de4145945cb6b67cea8ecb87378b0ee 100644 (file)
@@ -5,7 +5,8 @@ from __main__ import py
 
 import os, sys
 input_name = '%s/../COPYING' % os.path.dirname(sys.argv[0])
-input = file(input_name, 'rb').read()
+with open(input_name) as f:
+    input = f.read()
 
 def test_1():
     # No step at all.
@@ -41,19 +42,21 @@ def validate(request):
     command = ('$R --quiet --force < %s %s'
                '| $R --quiet --force %s..%s'
                % (input_name, request, after, before))
-    print command
+    print(command)
     output = common.external_output(command)
     common.assert_or_diff(output, input)
 
     # With an intermediate file
-    file(common.run.work, 'wb').write(input)
+    with open(common.run.work, 'w') as f:
+        f.write(input)
     command1 = ('$R --quiet --force %s %s'
                 % (request, common.run.work))
     command2 = ('$R --quiet --force %s..%s %s'
                 % (after, before, common.run.work))
-    print command1
-    print command2
+    print(command1)
+    print(command2)
     common.external_output(command1)
     common.external_output(command2)
-    output = file(common.run.work, 'rb').read()
+    with open(common.run.work) as f:
+        output = f.read()
     common.assert_or_diff(output, input)
index bd9ca2df05abf2a5986d178adce80c595be94a3c..04b6ac43cf48d86bd7092d8922bf9989e9e7d45d 100644 (file)
@@ -84,8 +84,9 @@ loese(Grad, Vern, Kern, Sich, Schr, Prot) :-
 '''
 
 def test_1():
+    import sys
     common.request('u8..l1')
     output = common.recode_iconv_output(input)
-    expected = ''.join(input.splitlines(True)[-6:])
-    output = ''.join(output.splitlines(True)[-6:])
+    expected = b''.join(input.encode('latin-1').splitlines(True)[-6:])
+    output = b''.join(output.splitlines(True)[-6:])
     common.assert_or_diff(output, expected)
index aa0b2849d9667b31b973fefacccacb9c33b7542d..835e72c13bac252f9d151d5c5ba5bfd032f5f6fb 100644 (file)
@@ -6,18 +6,18 @@ class Test:
 
     def test_1(self): # Ensure correct error code returned for untranslatable input
         request = Recode.Request(outer)
-        request.scan('utf-8..latin1')
+        request.scan(b'utf-8..latin1')
         task = Recode.Task(request)
-        task.set_input("\303\241 \303\247  \316\261 \316\266")
+        task.set_input(b"\303\241 \303\247  \316\261 \316\266")
         task.perform()
         assert(task.get_error() == Recode.UNTRANSLATABLE)
 
     # FIXME: Does not work with iconv for abort_level > UNTRANSLATABLE: Debian bug #348909
     def test_2(self): # Ensure correct error code returned for untranslatable input (with iconv)
         request = Recode.Request(outer_iconv)
-        request.scan('utf-8..latin1')
+        request.scan(b'utf-8..latin1')
         task = Recode.Task(request)
-        task.set_input("\303\241 \303\247  \316\261 \316\266")
+        task.set_input(b"\303\241 \303\247  \316\261 \316\266")
         task.set_abort_level(Recode.UNTRANSLATABLE)
         task.perform()
         assert(task.get_error() == Recode.UNTRANSLATABLE)
index 861cce6db9c6c14b6f9faabe42ae7351d115d29c..4d324cadee0cd43513e776d5640d8c857b1a8c3c 100644 (file)
@@ -32,7 +32,7 @@ from common import py, Recode
 from common import setup_module, teardown_module
 
 class Test:
-    avoid_as_before = 'count-characters', 'dump-with-names', 'flat'
+    avoid_as_before = b'count-characters', b'dump-with-names', b'flat'
 
     def test_1(self):
         if Recode is None:
@@ -57,11 +57,11 @@ class Test:
         # consider as a single test, one "before" against all "after"s.
         # However, without a Recode module, we do not know how many
         # "before"s exist, and the skip count is then rather small.
-        print before
+        print(before)
         for after in self.charsets:
             if after is not before:
                 request = Recode.Request(self.outer)
-                request.scan('%s..%s' % (before, after))
+                request.scan(b'%s..%s' % (before, after))
 
 def main(*arguments):
     recode_options = []
@@ -97,7 +97,7 @@ class Report:
                 line = readline()
                 if line:
                     if len(line[:-lensep].split(':', 1)) != 2:
-                        print '*', line,
+                        print('*', line, end='')
                     type, shrunk_to = line[:-lensep].split(':', 1)
                     if type == 'Shrunk to':
                         steps = self.get_steps(shrunk_to)
index 702176646b494a6578d199e487c6a01cbc028ccd..285d607516fc10017111eca57148e5227d6ad70b 100644 (file)
    fun:_PyObject_DebugMallocApi
 }
 
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:malloc
+   fun:_PyMem_RawMalloc
+   fun:PyMem_Malloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:malloc
+   fun:_PyMem_RawMalloc
+   fun:_PyMem_DebugAlloc
+   fun:_PyMem_DebugMalloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:malloc
+   fun:_PyMem_RawMalloc
+   fun:PyObject_Malloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:malloc
+   fun:_PyMem_RawMalloc
+   fun:PyObject_Realloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:malloc
+   fun:_PyMem_RawMalloc
+   fun:_PyMem_DebugRawAlloc
+   fun:_PyMem_DebugRawMalloc
+   fun:PyMem_RawMalloc
+}
+
 {
    Suppress debugging leaks
    Memcheck:Leak
    fun:_PyObject_DebugReallocApi
 }
 
+{
+   ADDRESS_IN_RANGE/Invalid read of size 4
+   Memcheck:Addr4
+   fun:address_in_range
+   fun:_PyObject_Realloc
+   fun:_PyMem_DebugRawRealloc
+   fun:_PyMem_DebugRealloc
+   fun:PyMem_Realloc
+}
+
+{
+   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
+   Memcheck:Value8
+   fun:address_in_range
+   fun:_PyObject_Realloc
+   fun:_PyMem_DebugRawRealloc
+   fun:_PyMem_DebugRealloc
+   fun:PyMem_Realloc
+}
+
+{
+   ADDRESS_IN_RANGE/Invalid read of size 4
+   Memcheck:Addr4
+   fun:_PyObject_Realloc
+   fun:_PyMem_DebugRealloc
+   fun:PyObject_Realloc
+}
+
+{
+   ADDRESS_IN_RANGE/Conditional jump or move
+   Memcheck:Cond
+   fun:address_in_range
+   fun:_PyObject_Realloc
+   fun:_PyMem_DebugRawRealloc
+   fun:_PyMem_DebugRealloc
+   fun:PyMem_Realloc
+}
+
+{
+   ADDRESS_IN_RANGE/Conditional jump or move
+   Memcheck:Cond
+   fun:address_in_range
+   fun:_PyObject_Free
+   fun:_PyMem_DebugRawFree
+   fun:_PyMem_DebugFree
+   fun:PyMem_Free
+}
+
+{
+   ADDRESS_IN_RANGE/Conditional jump or move
+   Memcheck:Value8
+   fun:address_in_range
+   fun:_PyObject_Free
+   fun:_PyMem_DebugRawFree
+   fun:_PyMem_DebugFree
+   fun:PyObject_Free
+}
+
+{
+   ADDRESS_IN_RANGE/Conditional jump or move
+   Memcheck:Cond
+   fun:address_in_range
+   fun:_PyObject_Free
+   fun:_PyMem_DebugRawFree
+   fun:_PyMem_DebugFree
+   fun:PyObject_Free
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:realloc
+   fun:_PyMem_RawRealloc
+   fun:PyObject_Realloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:realloc
+   fun:_PyMem_RawRealloc
+   fun:_PyMem_DebugRawRealloc
+   fun:PyMem_RawRealloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:realloc
+   fun:_PyMem_RawRealloc
+   fun:_PyMem_DebugRealloc
+   fun:PyMem_Realloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:realloc
+   fun:_PyMem_RawRealloc
+   fun:_PyMem_DebugRealloc
+   fun:PyMem_RawRealloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:malloc
+   fun:_PyMem_RawMalloc
+   fun:_PyMem_DebugAlloc
+   fun:_PyMem_DebugRealloc
+   fun:PyMem_Realloc
+}
+
+{
+   Suppress debugging leaks
+   Memcheck:Leak
+   fun:calloc
+   fun:_PyMem_RawCalloc
+   fun:_PyMem_DebugRawAlloc
+   fun:_PyMem_DebugRawCalloc
+   fun:PyMem_RawCalloc
+}
+
 {
    Suppress leaking the GIL.  Happens once per process, see comment in ceval.c.
    Memcheck:Leak
    fun:PyObject_Free
 }
 
+{
+   ADDRESS_IN_RANGE/Invalid read of size 4
+   Memcheck:Addr4
+   fun:address_in_range
+   fun:_PyObject_Free
+   fun:_PyMem_DebugRawFree
+   fun:_PyMem_DebugFree
+   fun:PyObject_Free
+}
+
+{
+   ADDRESS_IN_RANGE/Invalid read of size 4
+   Memcheck:Addr4
+   fun:_PyObject_Free
+   fun:_PyMem_DebugFree
+   fun:PyObject_Free
+}
+
 {
    ADDRESS_IN_RANGE/Invalid read of size 4
    Memcheck:Value4
 }
 
 {
-   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
+   ADDRESS_IN_RANGE/Invalid read of size 8
    Memcheck:Addr8
    fun:PyObject_Free
 }
 }
 
 {
-   ADDRESS_IN_RANGE/Use of uninitialised value of size 8
+   ADDRESS_IN_RANGE/Invalid read of size 8
    Memcheck:Addr8
    fun:PyObject_Realloc*
 }
    fun:PyUnicode_FSConverter
 }
 
+{
+   internal_utf8_loop_false_positive
+   Memcheck:Cond
+   fun:internal_utf8_loop
+}
+
+{
+   encode_current_locale
+   Memcheck:Cond
+   fun:__wcsnlen_*
+   fun:wcsrtombs
+   fun:wcstombs
+   fun:wcstombs
+   fun:encode_current_locale
+}
+
 {
    wcscmp_false_positive
    Memcheck:Addr8
    Memcheck:Addr4
    fun:PyUnicode_FSConverter
 }
-