We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
plain_str not consistent between Py2 and Py3
**Python 2 (expected result)**
```python
>>> plain_str(b'\x3e\xb4\xef\x2c\x11')
'>\xb4\xef,\x11'
```

**Python 3 (unexpected result)**
```python
>>> plain_str(b'\x3e\xb4\xef\x2c\x11')                                                                                                                                             
'>,\x11'
```

**Cause** is `errors="ignore"`
```python
def plain_str(x):                          
    """Convert basic byte objects to str"""
    if isinstance(x, bytes):               
        return x.decode(errors="ignore")   
    return str(x)       
```

It just ignores values that are not in a valid range for the codec.

**Possible fix**
```python
def plain_str(x):                          
    """Convert basic byte objects to str"""
    if isinstance(x, bytes):               
        return x.decode(errors="backslashreplace")   
    return str(x)       
```        
But this breaks compatibility for Python 3.4



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scapy/compat.py`
Content:
```
1 # This file is part of Scapy
2 # See http://www.secdev.org/projects/scapy for more information
3 # Copyright (C) Philippe Biondi <phil@secdev.org>
4 # Copyright (C) Gabriel Potter <gabriel@potter.fr>
5 # This program is published under a GPLv2 license
6 
7 """
8 Python 2 and 3 link classes.
9 """
10 
11 from __future__ import absolute_import
12 import base64
13 import binascii
14 import gzip
15 import struct
16 
17 import scapy.modules.six as six
18 
19 ###########
20 # Python3 #
21 ###########
22 
23 
24 def lambda_tuple_converter(func):
25     """
26     Converts a Python 2 function as
27       lambda (x,y): x + y
28     In the Python 3 format:
29       lambda x,y : x + y
30     """
31     if func is not None and func.__code__.co_argcount == 1:
32         return lambda *args: func(args[0] if len(args) == 1 else args)
33     else:
34         return func
35 
36 
37 if six.PY2:
38     bytes_encode = plain_str = str
39     chb = lambda x: x if isinstance(x, str) else chr(x)
40     orb = ord
41 
42     def raw(x):
43         """Builds a packet and returns its bytes representation.
44         This function is and always be cross-version compatible"""
45         if hasattr(x, "__bytes__"):
46             return x.__bytes__()
47         return bytes(x)
48 else:
49     def raw(x):
50         """Builds a packet and returns its bytes representation.
51         This function is and always be cross-version compatible"""
52         return bytes(x)
53 
54     def bytes_encode(x):
55         """Ensure that the given object is bytes.
56         If the parameter is a packet, raw() should be preferred.
57         """
58         if isinstance(x, str):
59             return x.encode()
60         return bytes(x)
61 
62     def plain_str(x):
63         """Convert basic byte objects to str"""
64         if isinstance(x, bytes):
65             return x.decode(errors="ignore")
66         return str(x)
67 
68     def chb(x):
69         """Same than chr() but encode as bytes."""
70         return struct.pack("!B", x)
71 
72     def orb(x):
73         """Return ord(x) when not already an int."""
74         if isinstance(x, int):
75             return x
76         return ord(x)
77 
78 
79 def bytes_hex(x):
80     """Hexify a str or a bytes object"""
81     return binascii.b2a_hex(bytes_encode(x))
82 
83 
84 def hex_bytes(x):
85     """De-hexify a str or a byte object"""
86     return binascii.a2b_hex(bytes_encode(x))
87 
88 
89 def base64_bytes(x):
90     """Turn base64 into bytes"""
91     if six.PY2:
92         return base64.decodestring(x)
93     return base64.decodebytes(bytes_encode(x))
94 
95 
96 def bytes_base64(x):
97     """Turn bytes into base64"""
98     if six.PY2:
99         return base64.encodestring(x).replace('\n', '')
100     return base64.encodebytes(bytes_encode(x)).replace(b'\n', b'')
101 
102 
103 if six.PY2:
104     from StringIO import StringIO
105 
106     def gzip_decompress(x):
107         """Decompress using gzip"""
108         with gzip.GzipFile(fileobj=StringIO(x), mode='rb') as fdesc:
109             return fdesc.read()
110 
111     def gzip_compress(x):
112         """Compress using gzip"""
113         buf = StringIO()
114         with gzip.GzipFile(fileobj=buf, mode='wb') as fdesc:
115             fdesc.write(x)
116         return buf.getvalue()
117 else:
118     gzip_decompress = gzip.decompress
119     gzip_compress = gzip.compress
120 
121 # Typing compatibility
122 
123 try:
124     # Only required if using mypy-lang for static typing
125     from typing import Optional, List, Union, Callable, Any, AnyStr, Tuple, \
126         Sized, Dict, Pattern, cast
127 except ImportError:
128     # Let's make some fake ones.
129 
130     def cast(_type, obj):
131         return obj
132 
133     class _FakeType(object):
134         # make the objects subscriptable indefinetly
135         def __getitem__(self, item):
136             return _FakeType()
137 
138     Optional = _FakeType()
139     Union = _FakeType()
140     Callable = _FakeType()
141     List = _FakeType()
142     Dict = _FakeType()
143     Any = _FakeType()
144     AnyStr = _FakeType()
145     Tuple = _FakeType()
146     Pattern = _FakeType()
147 
148     class Sized(object):
149         pass
150
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scapy/compat.py b/scapy/compat.py
--- a/scapy/compat.py
+++ b/scapy/compat.py
@@ -59,11 +59,19 @@
             return x.encode()
         return bytes(x)
 
-    def plain_str(x):
-        """Convert basic byte objects to str"""
-        if isinstance(x, bytes):
-            return x.decode(errors="ignore")
-        return str(x)
+    if six.PY34:
+        def plain_str(x):
+            """Convert basic byte objects to str"""
+            if isinstance(x, bytes):
+                return x.decode(errors="ignore")
+            return str(x)
+    else:
+        # Python 3.5+
+        def plain_str(x):
+            """Convert basic byte objects to str"""
+            if isinstance(x, bytes):
+                return x.decode(errors="backslashreplace")
+            return str(x)
 
     def chb(x):
         """Same than chr() but encode as bytes."""

{"golden_diff": "diff --git a/scapy/compat.py b/scapy/compat.py\n--- a/scapy/compat.py\n+++ b/scapy/compat.py\n@@ -59,11 +59,19 @@\n             return x.encode()\n         return bytes(x)\n \n-    def plain_str(x):\n-        \"\"\"Convert basic byte objects to str\"\"\"\n-        if isinstance(x, bytes):\n-            return x.decode(errors=\"ignore\")\n-        return str(x)\n+    if six.PY34:\n+        def plain_str(x):\n+            \"\"\"Convert basic byte objects to str\"\"\"\n+            if isinstance(x, bytes):\n+                return x.decode(errors=\"ignore\")\n+            return str(x)\n+    else:\n+        # Python 3.5+\n+        def plain_str(x):\n+            \"\"\"Convert basic byte objects to str\"\"\"\n+            if isinstance(x, bytes):\n+                return x.decode(errors=\"backslashreplace\")\n+            return str(x)\n \n     def chb(x):\n         \"\"\"Same than chr() but encode as bytes.\"\"\"\n", "issue": "plain_str not consistent between Py2 and Py3\n**Python 2 (expected result)**\r\n```python\r\n>>> plain_str(b'\\x3e\\xb4\\xef\\x2c\\x11')\r\n'>\\xb4\\xef,\\x11'\r\n```\r\n\r\n**Python 3 (unexpected result)**\r\n```python\r\n>>> plain_str(b'\\x3e\\xb4\\xef\\x2c\\x11')                                                                                                                                             \r\n'>,\\x11'\r\n```\r\n\r\n**Cause** is `errors=\"ignore\"`\r\n```python\r\ndef plain_str(x):                          \r\n    \"\"\"Convert basic byte objects to str\"\"\"\r\n    if isinstance(x, bytes):               \r\n        return x.decode(errors=\"ignore\")   \r\n    return str(x)       \r\n```\r\n\r\nIt just ignores values that are not in a valid range for the codec.\r\n\r\n**Possible fix**\r\n```python\r\ndef plain_str(x):                          \r\n    \"\"\"Convert basic byte objects to str\"\"\"\r\n    if isinstance(x, bytes):               \r\n        return x.decode(errors=\"backslashreplace\")   \r\n    return str(x)       \r\n```        \r\nBut this breaks compatibility for Python 3.4\r\n\r\n\n", "before_files": [{"content": "# This file is part of Scapy\n# See http://www.secdev.org/projects/scapy for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Gabriel Potter <gabriel@potter.fr>\n# This program is published under a GPLv2 license\n\n\"\"\"\nPython 2 and 3 link classes.\n\"\"\"\n\nfrom __future__ import absolute_import\nimport base64\nimport binascii\nimport gzip\nimport struct\n\nimport scapy.modules.six as six\n\n###########\n# Python3 #\n###########\n\n\ndef lambda_tuple_converter(func):\n    \"\"\"\n    Converts a Python 2 function as\n      lambda (x,y): x + y\n    In the Python 3 format:\n      lambda x,y : x + y\n    \"\"\"\n    if func is not None and func.__code__.co_argcount == 1:\n        return lambda *args: func(args[0] if len(args) == 1 else args)\n    else:\n        return func\n\n\nif six.PY2:\n    bytes_encode = plain_str = str\n    chb = lambda x: x if isinstance(x, str) else chr(x)\n    orb = ord\n\n    def raw(x):\n        \"\"\"Builds a packet and returns its bytes representation.\n        This function is and always be cross-version compatible\"\"\"\n        if hasattr(x, \"__bytes__\"):\n            return x.__bytes__()\n        return bytes(x)\nelse:\n    def raw(x):\n        \"\"\"Builds a packet and returns its bytes representation.\n        This function is and always be cross-version compatible\"\"\"\n        return bytes(x)\n\n    def bytes_encode(x):\n        \"\"\"Ensure that the given object is bytes.\n        If the parameter is a packet, raw() should be preferred.\n        \"\"\"\n        if isinstance(x, str):\n            return x.encode()\n        return bytes(x)\n\n    def plain_str(x):\n        \"\"\"Convert basic byte objects to str\"\"\"\n        if isinstance(x, bytes):\n            return x.decode(errors=\"ignore\")\n        return str(x)\n\n    def chb(x):\n        \"\"\"Same than chr() but encode as bytes.\"\"\"\n        return struct.pack(\"!B\", x)\n\n    def orb(x):\n        \"\"\"Return ord(x) when not already an int.\"\"\"\n        if isinstance(x, int):\n            return x\n        return ord(x)\n\n\ndef bytes_hex(x):\n    \"\"\"Hexify a str or a bytes object\"\"\"\n    return binascii.b2a_hex(bytes_encode(x))\n\n\ndef hex_bytes(x):\n    \"\"\"De-hexify a str or a byte object\"\"\"\n    return binascii.a2b_hex(bytes_encode(x))\n\n\ndef base64_bytes(x):\n    \"\"\"Turn base64 into bytes\"\"\"\n    if six.PY2:\n        return base64.decodestring(x)\n    return base64.decodebytes(bytes_encode(x))\n\n\ndef bytes_base64(x):\n    \"\"\"Turn bytes into base64\"\"\"\n    if six.PY2:\n        return base64.encodestring(x).replace('\\n', '')\n    return base64.encodebytes(bytes_encode(x)).replace(b'\\n', b'')\n\n\nif six.PY2:\n    from StringIO import StringIO\n\n    def gzip_decompress(x):\n        \"\"\"Decompress using gzip\"\"\"\n        with gzip.GzipFile(fileobj=StringIO(x), mode='rb') as fdesc:\n            return fdesc.read()\n\n    def gzip_compress(x):\n        \"\"\"Compress using gzip\"\"\"\n        buf = StringIO()\n        with gzip.GzipFile(fileobj=buf, mode='wb') as fdesc:\n            fdesc.write(x)\n        return buf.getvalue()\nelse:\n    gzip_decompress = gzip.decompress\n    gzip_compress = gzip.compress\n\n# Typing compatibility\n\ntry:\n    # Only required if using mypy-lang for static typing\n    from typing import Optional, List, Union, Callable, Any, AnyStr, Tuple, \\\n        Sized, Dict, Pattern, cast\nexcept ImportError:\n    # Let's make some fake ones.\n\n    def cast(_type, obj):\n        return obj\n\n    class _FakeType(object):\n        # make the objects subscriptable indefinetly\n        def __getitem__(self, item):\n            return _FakeType()\n\n    Optional = _FakeType()\n    Union = _FakeType()\n    Callable = _FakeType()\n    List = _FakeType()\n    Dict = _FakeType()\n    Any = _FakeType()\n    AnyStr = _FakeType()\n    Tuple = _FakeType()\n    Pattern = _FakeType()\n\n    class Sized(object):\n        pass\n", "path": "scapy/compat.py"}], "after_files": [{"content": "# This file is part of Scapy\n# See http://www.secdev.org/projects/scapy for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Gabriel Potter <gabriel@potter.fr>\n# This program is published under a GPLv2 license\n\n\"\"\"\nPython 2 and 3 link classes.\n\"\"\"\n\nfrom __future__ import absolute_import\nimport base64\nimport binascii\nimport gzip\nimport struct\n\nimport scapy.modules.six as six\n\n###########\n# Python3 #\n###########\n\n\ndef lambda_tuple_converter(func):\n    \"\"\"\n    Converts a Python 2 function as\n      lambda (x,y): x + y\n    In the Python 3 format:\n      lambda x,y : x + y\n    \"\"\"\n    if func is not None and func.__code__.co_argcount == 1:\n        return lambda *args: func(args[0] if len(args) == 1 else args)\n    else:\n        return func\n\n\nif six.PY2:\n    bytes_encode = plain_str = str\n    chb = lambda x: x if isinstance(x, str) else chr(x)\n    orb = ord\n\n    def raw(x):\n        \"\"\"Builds a packet and returns its bytes representation.\n        This function is and always be cross-version compatible\"\"\"\n        if hasattr(x, \"__bytes__\"):\n            return x.__bytes__()\n        return bytes(x)\nelse:\n    def raw(x):\n        \"\"\"Builds a packet and returns its bytes representation.\n        This function is and always be cross-version compatible\"\"\"\n        return bytes(x)\n\n    def bytes_encode(x):\n        \"\"\"Ensure that the given object is bytes.\n        If the parameter is a packet, raw() should be preferred.\n        \"\"\"\n        if isinstance(x, str):\n            return x.encode()\n        return bytes(x)\n\n    if six.PY34:\n        def plain_str(x):\n            \"\"\"Convert basic byte objects to str\"\"\"\n            if isinstance(x, bytes):\n                return x.decode(errors=\"ignore\")\n            return str(x)\n    else:\n        # Python 3.5+\n        def plain_str(x):\n            \"\"\"Convert basic byte objects to str\"\"\"\n            if isinstance(x, bytes):\n                return x.decode(errors=\"backslashreplace\")\n            return str(x)\n\n    def chb(x):\n        \"\"\"Same than chr() but encode as bytes.\"\"\"\n        return struct.pack(\"!B\", x)\n\n    def orb(x):\n        \"\"\"Return ord(x) when not already an int.\"\"\"\n        if isinstance(x, int):\n            return x\n        return ord(x)\n\n\ndef bytes_hex(x):\n    \"\"\"Hexify a str or a bytes object\"\"\"\n    return binascii.b2a_hex(bytes_encode(x))\n\n\ndef hex_bytes(x):\n    \"\"\"De-hexify a str or a byte object\"\"\"\n    return binascii.a2b_hex(bytes_encode(x))\n\n\ndef base64_bytes(x):\n    \"\"\"Turn base64 into bytes\"\"\"\n    if six.PY2:\n        return base64.decodestring(x)\n    return base64.decodebytes(bytes_encode(x))\n\n\ndef bytes_base64(x):\n    \"\"\"Turn bytes into base64\"\"\"\n    if six.PY2:\n        return base64.encodestring(x).replace('\\n', '')\n    return base64.encodebytes(bytes_encode(x)).replace(b'\\n', b'')\n\n\nif six.PY2:\n    from StringIO import StringIO\n\n    def gzip_decompress(x):\n        \"\"\"Decompress using gzip\"\"\"\n        with gzip.GzipFile(fileobj=StringIO(x), mode='rb') as fdesc:\n            return fdesc.read()\n\n    def gzip_compress(x):\n        \"\"\"Compress using gzip\"\"\"\n        buf = StringIO()\n        with gzip.GzipFile(fileobj=buf, mode='wb') as fdesc:\n            fdesc.write(x)\n        return buf.getvalue()\nelse:\n    gzip_decompress = gzip.decompress\n    gzip_compress = gzip.compress\n\n# Typing compatibility\n\ntry:\n    # Only required if using mypy-lang for static typing\n    from typing import Optional, List, Union, Callable, Any, AnyStr, Tuple, \\\n        Sized, Dict, Pattern, cast\nexcept ImportError:\n    # Let's make some fake ones.\n\n    def cast(_type, obj):\n        return obj\n\n    class _FakeType(object):\n        # make the objects subscriptable indefinetly\n        def __getitem__(self, item):\n            return _FakeType()\n\n    Optional = _FakeType()\n    Union = _FakeType()\n    Callable = _FakeType()\n    List = _FakeType()\n    Dict = _FakeType()\n    Any = _FakeType()\n    AnyStr = _FakeType()\n    Tuple = _FakeType()\n    Pattern = _FakeType()\n\n    class Sized(object):\n        pass\n", "path": "scapy/compat.py"}]}