prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Backwards incompatible change in multistring
  The behavior of the `multistring` class with respect to string comparisons has changed in 1.14-rc1, more specifically when the `autoencode` class was removed in 4f9ee7edfc9. At least this is the case in Python 2.7.
  
  I have experienced this in some custom Pootle code when testing out TTK from master — a multistring with non-ASCII characters was being compared against the empty byte string `''`, and it resulted in a encoding error. I can reproduce this in a test case:
  
  ``` python
  from translate.misc import multistring
  
  def test_cmp():
      t = multistring.multistring
      s1 = t("test")
      assert s1.__cmp__("test") == 0
  
      s2 = t(u"téßt")
      assert s2.__cmp__("test") > 0
  ```
  
  (Note that for 1.13.x the multistring constructor needs an `encoding='UTF-8'` parameter in the test).
  
  I'm not sure if this could be considered a bug, after all my understanding is apps/libraries should internally work with code points and not bytes, however this is a breaking change that might potentially affect existing consumer code so I consider it's worth bringing this up to hear people's thoughts.
  
  
  </issue>
  <code>
  [start of translate/misc/multistring.py]
  1 # -*- coding: utf-8 -*-
  2 #
  3 # Copyright 2006 Zuza Software Foundation
  4 #
  5 # This file is part of translate.
  6 #
  7 # translate is free software; you can redistribute it and/or modify
  8 # it under the terms of the GNU General Public License as published by
  9 # the Free Software Foundation; either version 2 of the License, or
  10 # (at your option) any later version.
  11 #
  12 # translate is distributed in the hope that it will be useful,
  13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 # GNU General Public License for more details.
  16 #
  17 # You should have received a copy of the GNU General Public License
  18 # along with this program; if not, see <http://www.gnu.org/licenses/>.
  19 
  20 """Supports a hybrid Unicode string that can also have a list of alternate
  21 strings in the strings attribute"""
  22 
  23 import six
  24 
  25 
  26 class multistring(six.text_type):
  27 
  28     def __new__(newtype, string=u"", *args, **kwargs):
  29         if isinstance(string, list):
  30             if not string:
  31                 raise ValueError("multistring must contain at least one string")
  32             mainstring = string[0]
  33             newstring = multistring.__new__(newtype, string[0])
  34             newstring.strings = [newstring] + [multistring.__new__(newtype, altstring) for altstring in string[1:]]
  35         else:
  36             newstring = six.text_type.__new__(newtype, string)
  37             newstring.strings = [newstring]
  38         return newstring
  39 
  40     def __init__(self, *args, **kwargs):
  41         super(multistring, self).__init__()
  42         if not hasattr(self, "strings"):
  43             self.strings = []
  44 
  45     def __cmp__(self, otherstring):
  46         def cmp_compat(s1, s2):
  47             # Python 3 compatible cmp() equivalent
  48             return (s1 > s2) - (s1 < s2)
  49         if isinstance(otherstring, multistring):
  50             parentcompare = cmp_compat(six.text_type(self), otherstring)
  51             if parentcompare:
  52                 return parentcompare
  53             else:
  54                 return cmp_compat(self.strings[1:], otherstring.strings[1:])
  55         elif isinstance(otherstring, six.text_type):
  56             return cmp_compat(six.text_type(self), otherstring)
  57         elif isinstance(otherstring, bytes):
  58             return cmp_compat(bytes(self), otherstring)
  59         elif isinstance(otherstring, list) and otherstring:
  60             return cmp_compat(self, multistring(otherstring))
  61         else:
  62             return cmp_compat(str(type(self)), str(type(otherstring)))
  63 
  64     def __hash__(self):
  65         return hash(''.join(self.strings))
  66 
  67     def __ne__(self, otherstring):
  68         return self.__cmp__(otherstring) != 0
  69 
  70     def __eq__(self, otherstring):
  71         return self.__cmp__(otherstring) == 0
  72 
  73     def __repr__(self):
  74         return "multistring([" + ",".join(self.strings) + "])"
  75 
  76     def replace(self, old, new, count=None):
  77         if count is None:
  78             newstr = multistring(super(multistring, self).replace(old, new))
  79         else:
  80             newstr = multistring(super(multistring, self).replace(old, new, count))
  81         for s in self.strings[1:]:
  82             if count is None:
  83                 newstr.strings.append(s.replace(old, new))
  84             else:
  85                 newstr.strings.append(s.replace(old, new, count))
  86         return newstr
  87
  [end of translate/misc/multistring.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/translate/misc/multistring.py b/translate/misc/multistring.py
  --- a/translate/misc/multistring.py
  +++ b/translate/misc/multistring.py
  @@ -55,7 +55,7 @@
           elif isinstance(otherstring, six.text_type):
               return cmp_compat(six.text_type(self), otherstring)
           elif isinstance(otherstring, bytes):
  -            return cmp_compat(bytes(self), otherstring)
  +            return cmp_compat(self.encode('utf-8'), otherstring)
           elif isinstance(otherstring, list) and otherstring:
               return cmp_compat(self, multistring(otherstring))
           else:
  @@ -71,7 +71,8 @@
           return self.__cmp__(otherstring) == 0
   
       def __repr__(self):
  -        return "multistring([" + ",".join(self.strings) + "])"
  +        _repr = "multistring([" + u",".join(self.strings) + "])"
  +        return _repr.encode('utf-8') if six.PY2 else _repr
   
       def replace(self, old, new, count=None):
           if count is None:
  
verification_info: {"golden_diff": "diff --git a/translate/misc/multistring.py b/translate/misc/multistring.py\n--- a/translate/misc/multistring.py\n+++ b/translate/misc/multistring.py\n@@ -55,7 +55,7 @@\n         elif isinstance(otherstring, six.text_type):\n             return cmp_compat(six.text_type(self), otherstring)\n         elif isinstance(otherstring, bytes):\n-            return cmp_compat(bytes(self), otherstring)\n+            return cmp_compat(self.encode('utf-8'), otherstring)\n         elif isinstance(otherstring, list) and otherstring:\n             return cmp_compat(self, multistring(otherstring))\n         else:\n@@ -71,7 +71,8 @@\n         return self.__cmp__(otherstring) == 0\n \n     def __repr__(self):\n-        return \"multistring([\" + \",\".join(self.strings) + \"])\"\n+        _repr = \"multistring([\" + u\",\".join(self.strings) + \"])\"\n+        return _repr.encode('utf-8') if six.PY2 else _repr\n \n     def replace(self, old, new, count=None):\n         if count is None:\n", "issue": "Backwards incompatible change in multistring\nThe behavior of the `multistring` class with respect to string comparisons has changed in 1.14-rc1, more specifically when the `autoencode` class was removed in 4f9ee7edfc9. At least this is the case in Python 2.7.\n\nI have experienced this in some custom Pootle code when testing out TTK from master \u2014 a multistring with non-ASCII characters was being compared against the empty byte string `''`, and it resulted in a encoding error. I can reproduce this in a test case:\n\n``` python\nfrom translate.misc import multistring\n\ndef test_cmp():\n    t = multistring.multistring\n    s1 = t(\"test\")\n    assert s1.__cmp__(\"test\") == 0\n\n    s2 = t(u\"t\u00e9\u00dft\")\n    assert s2.__cmp__(\"test\") > 0\n```\n\n(Note that for 1.13.x the multistring constructor needs an `encoding='UTF-8'` parameter in the test).\n\nI'm not sure if this could be considered a bug, after all my understanding is apps/libraries should internally work with code points and not bytes, however this is a breaking change that might potentially affect existing consumer code so I consider it's worth bringing this up to hear people's thoughts.\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n#\n# Copyright 2006 Zuza Software Foundation\n#\n# This file is part of translate.\n#\n# translate is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# translate is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Supports a hybrid Unicode string that can also have a list of alternate\nstrings in the strings attribute\"\"\"\n\nimport six\n\n\nclass multistring(six.text_type):\n\n    def __new__(newtype, string=u\"\", *args, **kwargs):\n        if isinstance(string, list):\n            if not string:\n                raise ValueError(\"multistring must contain at least one string\")\n            mainstring = string[0]\n            newstring = multistring.__new__(newtype, string[0])\n            newstring.strings = [newstring] + [multistring.__new__(newtype, altstring) for altstring in string[1:]]\n        else:\n            newstring = six.text_type.__new__(newtype, string)\n            newstring.strings = [newstring]\n        return newstring\n\n    def __init__(self, *args, **kwargs):\n        super(multistring, self).__init__()\n        if not hasattr(self, \"strings\"):\n            self.strings = []\n\n    def __cmp__(self, otherstring):\n        def cmp_compat(s1, s2):\n            # Python 3 compatible cmp() equivalent\n            return (s1 > s2) - (s1 < s2)\n        if isinstance(otherstring, multistring):\n            parentcompare = cmp_compat(six.text_type(self), otherstring)\n            if parentcompare:\n                return parentcompare\n            else:\n                return cmp_compat(self.strings[1:], otherstring.strings[1:])\n        elif isinstance(otherstring, six.text_type):\n            return cmp_compat(six.text_type(self), otherstring)\n        elif isinstance(otherstring, bytes):\n            return cmp_compat(bytes(self), otherstring)\n        elif isinstance(otherstring, list) and otherstring:\n            return cmp_compat(self, multistring(otherstring))\n        else:\n            return cmp_compat(str(type(self)), str(type(otherstring)))\n\n    def __hash__(self):\n        return hash(''.join(self.strings))\n\n    def __ne__(self, otherstring):\n        return self.__cmp__(otherstring) != 0\n\n    def __eq__(self, otherstring):\n        return self.__cmp__(otherstring) == 0\n\n    def __repr__(self):\n        return \"multistring([\" + \",\".join(self.strings) + \"])\"\n\n    def replace(self, old, new, count=None):\n        if count is None:\n            newstr = multistring(super(multistring, self).replace(old, new))\n        else:\n            newstr = multistring(super(multistring, self).replace(old, new, count))\n        for s in self.strings[1:]:\n            if count is None:\n                newstr.strings.append(s.replace(old, new))\n            else:\n                newstr.strings.append(s.replace(old, new, count))\n        return newstr\n", "path": "translate/misc/multistring.py"}]}