diff --git twisted/python/compat.py twisted/python/compat.py
index 7a56f86..cf4ffdd 100644
--- twisted/python/compat.py
+++ twisted/python/compat.py
@@ -357,6 +357,56 @@ integer.
 """
 
 
+
+if _PY3:
+    def chr_(i):
+        if isinstance(i, int):
+            if i > 255:
+                raise ValueError("chr() arg not in range(256)")
+            return chr(i).encode("latin1")
+        else:
+            raise TypeError("an integer is required")
+else:
+    # We need to emulate 2.x? THIS. IS. 2.X!
+    def chr_(i):
+        return chr(i)
+
+chr_.__doc__ = """
+Duplicate the behavior of 2x chr in 3x.
+
+The Python 2.x built-in chr converted integers in [0, 255] to the
+one-character byte strings containing the character with that ASCII encoded
+value.
+
+The Python 3.x chr instead takes integers in the range [0, 1114111], and
+converts them to one-character Unicode strings containing the character
+with that code-point.
+
+The chr_ in this function duplicates 2.x behavior on both 2.x and 3.x.
+
+See these extracts from the Python manual for details.
+
+Python 2.x
+----------
+chr:
+"Return a string of one character whose ASCII code is the integer i. For
+example, chr(97) returns the string 'a'. This is the inverse of ord(). The
+argument must be in the range [0..255], inclusive; ValueError will be raised if
+i is outside that range. See also unichr()."
+http://docs.python.org/library/functions.html#chr
+
+Python 3.x
+----------
+chr:
+"Return the string representing a character whose Unicode codepoint is the
+integer i. For example, chr(97) returns the string 'a'. This is the inverse of
+ord(). The valid range for the argument is from 0 through 1,114,111 (0x10FFFF
+in base 16). ValueError will be raised if i is outside that range."
+http://docs.python.org/py3k/library/functions.html#chr
+"""
+
+
+
 __all__ = [
     "reraise",
     "execfile",
@@ -370,4 +420,5 @@ __all__ = [
     "unicode",
     "iterbytes",
     "intToBytes",
+    "chr_"
     ]
diff --git twisted/test/test_compat.py twisted/test/test_compat.py
index b408153..3121b3c 100644
--- twisted/test/test_compat.py
+++ twisted/test/test_compat.py
@@ -16,6 +16,7 @@ from twisted.python.compat import set, frozenset, reduce, execfile, _PY3
 from twisted.python.compat import comparable, cmp, nativeString
 from twisted.python.compat import unicode as unicodeCompat
 from twisted.python.compat import reraise, NativeStringIO, iterbytes, intToBytes
+from twisted.python.compat import chr_
 from twisted.python.filepath import FilePath
 
 
@@ -538,3 +539,90 @@ class Python3BytesTests(unittest.SynchronousTestCase):
         ASCII-encoded string representation of the number.
         """
         self.assertEqual(intToBytes(213), b"213")
+
+
+
+class chr_Tests(unittest.SynchronousTestCase):
+    """
+    Tests for L{compat.chr_}.
+
+    L{compat.chr_} should emulate the Python 2.x built-in chr which had
+    these key characteristics:
+        -Accepted an integer in [0, 255].
+        -Returned a bytestring containing the character encoded to that
+         integer under ASCII.
+        -Raised a ValueError in response to any integer outside that range.
+        -Raised a TypeError in response to any other input.
+    """
+    # A sampling of ASCII characters, which chr_ should accept.
+    _ASCIIEncodedValues = [0, 1, 103, 104, 126, 127, 128, 254, 255]
+    _ASCIICharacters = [b"\x00", b"\x01", b"g", b"h", b"~", b"\x7f", b"\x80", b"\xfe", b"\xff"]
+    # And here is a sampling of things that chr_ should NOT accept.
+    _negativeIntegers = [-10, -1]
+    _integersOver255 = [256, 257, 500, 1000, 10000, 60000, 65534, 65535]
+    _integersOver65535 = [65536, 65537, 100000]
+    _bytestringASCIICharacters = [b"a", b"\x15"]
+    _UnicodeCharacters = [u"b", u"\xeff", u"\xfffe", u"\xffff"]
+    _UnicodeCharactersOver65535 = [u"\x10000", u"\x10001"]
+    _nonIntegersNotCharacters = [2.3, dict()]
+
+    def test_chr_Accepts(self):
+        """
+        L{compat.chr_} accepts integers in [0, 255] and returns the
+        corresponding character in an ASCII-encoded bytestring.
+        """
+        for (encodedValue, bytestringCharacter) in zip(
+                self._ASCIIEncodedValues, self._ASCIICharacters):
+            # Deliberately leak any exceptions; failing the test with ERROR.
+            ret = chr_(encodedValue)
+            self.assertIsInstance(ret, bytes)
+            self.assertEqual(ret, bytestringCharacter)
+
+    def _assert_chr_Rejects(self, invalidInput, exceptionToRejectWith):
+        """Convenience function. map assertRaises across invalidInput."""
+        for x in invalidInput:
+            self.assertRaises(exceptionToRejectWith, chr_, x)
+
+    def test_chr_RejectsNegativeIntegers(self):
+        """
+        L{compat.chr_} rejects negative integers with ValueError.
+        """
+        self._assert_chr_Rejects(self._negativeIntegers, ValueError)
+
+    def test_chr_RejectsIntegersOver255(self):
+        """
+        L{compat.chr_} rejects integers over 255 with ValueError.
+        """
+        self._assert_chr_Rejects(self._integersOver255, ValueError)
+
+    def test_chr_RejectsIntegersOver65535(self):
+        """
+        L{compat.chr_} rejects integers over 65535 with ValueError.
+        """
+        self._assert_chr_Rejects(self._integersOver65535, ValueError)
+
+    def test_chr_RejectsBytestringASCIICharacters(self):
+        """
+        L{compat.chr_} rejects ASCII-encoded bytestrings with TypeError.
+        """
+        self._assert_chr_Rejects(self._bytestringASCIICharacters, TypeError)
+
+    def test_chr_RejectsUnicodeCharacters(self):
+        """
+        L{compat.chr_} rejects Unicode strings with TypeError.
+        """
+        self._assert_chr_Rejects(self._UnicodeCharacters, TypeError)
+
+    def test_chr_RejectsUnicodeCharactersOver65535(self):
+        """
+        L{compat.chr_} rejects Unicode strings with codepoints over 65535 with
+        TypeError.
+        """
+        self._assert_chr_Rejects(self._UnicodeCharactersOver65535, TypeError)
+
+    def test_chr_RejectsNonIntegersNonCharacters(self):
+        """
+        L{compat.chr_} rejects any other odd thing you give it, like a dict,
+        with TypeError.
+        """
+        self._assert_chr_Rejects(self._nonIntegersNotCharacters, TypeError)
diff --git twisted/topfiles/6070.misc twisted/topfiles/6070.misc
new file mode 100644
index 0000000..e69de29
