@@ -0,0 +1,1051 @@
+import re%0A%0Adef unescape(text):%0A    %22%22%22Unescape function based on http://stackoverflow.com/a/15528611.%22%22%22%0A    regex = re.compile(b'%5C%5C%5C%5C(%5C%5C%5C%5C%7C%5B0-7%5D%7B1,3%7D%7Cx.%5B0-9a-f%5D?%7C%5B%5C'%22abfnrt%5D%7C.%7C$)')%0A    def replace(m):%0A        b = m.group(1)%0A        if len(b) == 0:%0A            raise ValueError(%22Invalid character escape: '%5C%5C'.%22)%0A        i = b%5B0%5D%0A        if i == 120:%0A            v = int(b%5B1:%5D, 16)%0A        elif 48 %3C= i %3C= 55:%0A            v = int(b, 8)%0A        elif i == 34: return b'%22'%0A        elif i == 39: return b%22'%22%0A        elif i == 92: return b'%5C%5C'%0A        elif i == 97: return b'%5Ca'%0A        elif i == 98: return b'%5Cb'%0A        elif i == 102: return b'%5Cf'%0A        elif i == 110: return b'%5Cn'%0A        elif i == 114: return b'%5Cr'%0A        elif i == 116: return b'%5Ct'%0A        else:%0A            s = b.decode('ascii')%0A            raise UnicodeDecodeError(%0A                'stringescape', text, m.start(), m.end(), %22Invalid escape: %25r%22 %25 s%0A            )%0A        return bytes((v, ))%0A    result = regex.sub(replace, bytes(text, %22utf-8%22))%0A    return str(result, %22utf-8%22)%0A%0A

move unescape to utils