From 4045ac7c7b940c10904aceffd209ed269cb48268 Mon Sep 17 00:00:00 2001 From: Sérgio M. Basto Date: Jan 25 2022 15:25:37 +0000 Subject: Fix CVE-2021-40839 --- diff --git a/python-rencode.spec b/python-rencode.spec index 1339db2..1f24e7d 100644 --- a/python-rencode.spec +++ b/python-rencode.spec @@ -2,7 +2,7 @@ Name: python-rencode Version: 1.0.6 -Release: 16%{?dist} +Release: 17%{?dist} Summary: Web safe object pickling/unpickling License: GPLv3+ and BSD URL: https://github.com/aresch/rencode @@ -14,6 +14,7 @@ Source0: https://files.pythonhosted.org/packages/source/l/%{srcname}/%{sr # to be updated. # https://github.com/aresch/rencode/issues/22 Source1: https://raw.githubusercontent.com/aresch/rencode/53d72ac53d9df007aad3a980f049a80d81836619/rencode/rencode.pyx +Patch1: https://github.com/aresch/rencode/compare/v1.0.6...572ff74586d9b1daab904c6f7f7009ce0143bb75.diff BuildRequires: gcc @@ -43,12 +44,14 @@ b-encodings. %prep -%autosetup -n rencode-%{version} +%setup -n rencode-%{version} cp -a %{SOURCE1} ./rencode # Make sure we rebuild the module rm -f ./rencode/rencode.c +%patch1 -p1 + %build %py3_build @@ -72,6 +75,9 @@ popd %changelog +* Tue Jan 25 2022 Sérgio Basto - 1.0.6-17 +- Fix CVE-2021-40839 + * Fri Jan 21 2022 Fedora Release Engineering - 1.0.6-16 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild diff --git a/v1.0.6...572ff74586d9b1daab904c6f7f7009ce0143bb75.diff b/v1.0.6...572ff74586d9b1daab904c6f7f7009ce0143bb75.diff new file mode 100644 index 0000000..efe12b8 --- /dev/null +++ b/v1.0.6...572ff74586d9b1daab904c6f7f7009ce0143bb75.diff @@ -0,0 +1,1395 @@ +diff --git a/.travis.yml b/.travis.yml +new file mode 100644 +index 0000000..a894511 +--- /dev/null ++++ b/.travis.yml +@@ -0,0 +1,27 @@ ++language: python ++ ++env: ++ global: ++ - TWINE_USERNAME=andrew.resch ++ ++matrix: ++ include: ++ - sudo: required ++ services: ++ - docker ++ env: PIP=pip ++ - os: osx ++ language: generic ++ env: PIP=pip2 ++ ++install: ++ - $PIP install -r dev-requirements.txt ++ ++script: ++ - $PIP install cibuildwheel==0.10.0 ++ - cibuildwheel --output-dir wheelhouse ++ - | ++ if [[ $TRAVIS_TAG ]]; then ++ $PIP install twine ++ python -m twine upload wheelhouse/*.whl ++ fi +diff --git a/MANIFEST.in b/MANIFEST.in +index c8cedbf..f542827 100644 +--- a/MANIFEST.in ++++ b/MANIFEST.in +@@ -2,3 +2,4 @@ include COPYING + include README.md + include tests/*.py + include rencode/rencode.c ++include rencode/_rencode.pyx +\ No newline at end of file +diff --git a/dev-requirements.txt b/dev-requirements.txt +new file mode 100644 +index 0000000..002d1b9 +--- /dev/null ++++ b/dev-requirements.txt +@@ -0,0 +1 @@ ++Cython +diff --git a/rencode/rencode.pyx b/rencode/_rencode.pyx +similarity index 99% +rename from rencode/rencode.pyx +rename to rencode/_rencode.pyx +index d649c85..3db1180 100644 +--- a/rencode/rencode.pyx ++++ b/rencode/_rencode.pyx +@@ -527,6 +527,8 @@ cdef decode(char *data, unsigned int *pos): + return decode_fixed_dict(data, pos) + elif typecode == CHR_DICT: + return decode_dict(data, pos) ++ else: ++ raise ValueError("Invalid typecode: %d at pos: %d" % (typecode, pos[0])) + + def loads(data, decode_utf8=False): + """ +diff --git a/rencode/rencode_orig.py b/rencode/rencode_orig.py +index 83f0de3..e702692 100644 +--- a/rencode/rencode_orig.py ++++ b/rencode/rencode_orig.py +@@ -64,7 +64,7 @@ + from threading import Lock + + __version__ = ("Python", 1, 0, 6) +-__all__ = ('dumps', 'loads') ++__all__ = ("dumps", "loads") + + py3 = sys.version_info[0] >= 3 + if py3: +@@ -73,10 +73,14 @@ + + def int2byte(c): + return bytes([c]) ++ ++ + else: ++ + def int2byte(c): + return chr(c) + ++ + # Default number of bits for serialized floats, either 32 or 64 (also a parameter for dumps()). + DEFAULT_FLOAT_BITS = 32 + +@@ -127,80 +131,80 @@ def decode_int(x, f): + f += 1 + newf = x.index(CHR_TERM, f) + if newf - f >= MAX_INT_LENGTH: +- raise ValueError('overflow') ++ raise ValueError("overflow") + try: + n = int(x[f:newf]) + except (OverflowError, ValueError): + n = long(x[f:newf]) +- if x[f:f + 1] == '-': +- if x[f + 1:f + 2] == '0': ++ if x[f : f + 1] == "-": ++ if x[f + 1 : f + 2] == "0": + raise ValueError +- elif x[f:f + 1] == '0' and newf != f + 1: ++ elif x[f : f + 1] == "0" and newf != f + 1: + raise ValueError + return (n, newf + 1) + + + def decode_intb(x, f): + f += 1 +- return (struct.unpack('!b', x[f:f + 1])[0], f + 1) ++ return (struct.unpack("!b", x[f : f + 1])[0], f + 1) + + + def decode_inth(x, f): + f += 1 +- return (struct.unpack('!h', x[f:f + 2])[0], f + 2) ++ return (struct.unpack("!h", x[f : f + 2])[0], f + 2) + + + def decode_intl(x, f): + f += 1 + +- return (struct.unpack('!l', x[f:f + 4])[0], f + 4) ++ return (struct.unpack("!l", x[f : f + 4])[0], f + 4) + + + def decode_intq(x, f): + f += 1 +- return (struct.unpack('!q', x[f:f + 8])[0], f + 8) ++ return (struct.unpack("!q", x[f : f + 8])[0], f + 8) + + + def decode_float32(x, f): + f += 1 +- n = struct.unpack('!f', x[f:f + 4])[0] ++ n = struct.unpack("!f", x[f : f + 4])[0] + return (n, f + 4) + + + def decode_float64(x, f): + f += 1 +- n = struct.unpack('!d', x[f:f + 8])[0] ++ n = struct.unpack("!d", x[f : f + 8])[0] + return (n, f + 8) + + + def decode_string(x, f): +- colon = x.index(b':', f) ++ colon = x.index(b":", f) + try: + n = int(x[f:colon]) + except (OverflowError, ValueError): + n = long(x[f:colon]) +- if x[f] == '0' and colon != f + 1: ++ if x[f] == "0" and colon != f + 1: + raise ValueError + colon += 1 +- s = x[colon:colon + n] ++ s = x[colon : colon + n] + if _decode_utf8: +- s = s.decode('utf8') ++ s = s.decode("utf8") + return (s, colon + n) + + + def decode_list(x, f): + r, f = [], f + 1 +- while x[f:f + 1] != CHR_TERM: +- v, f = decode_func[x[f:f + 1]](x, f) ++ while x[f : f + 1] != CHR_TERM: ++ v, f = decode_func[x[f : f + 1]](x, f) + r.append(v) + return (tuple(r), f + 1) + + + def decode_dict(x, f): + r, f = {}, f + 1 +- while x[f:f + 1] != CHR_TERM: +- k, f = decode_func[x[f:f + 1]](x, f) +- r[k], f = decode_func[x[f:f + 1]](x, f) ++ while x[f : f + 1] != CHR_TERM: ++ k, f = decode_func[x[f : f + 1]](x, f) ++ r[k], f = decode_func[x[f : f + 1]](x, f) + return (r, f + 1) + + +@@ -215,17 +219,18 @@ def decode_false(x, f): + def decode_none(x, f): + return (None, f + 1) + ++ + decode_func = {} +-decode_func[b'0'] = decode_string +-decode_func[b'1'] = decode_string +-decode_func[b'2'] = decode_string +-decode_func[b'3'] = decode_string +-decode_func[b'4'] = decode_string +-decode_func[b'5'] = decode_string +-decode_func[b'6'] = decode_string +-decode_func[b'7'] = decode_string +-decode_func[b'8'] = decode_string +-decode_func[b'9'] = decode_string ++decode_func[b"0"] = decode_string ++decode_func[b"1"] = decode_string ++decode_func[b"2"] = decode_string ++decode_func[b"3"] = decode_string ++decode_func[b"4"] = decode_string ++decode_func[b"5"] = decode_string ++decode_func[b"6"] = decode_string ++decode_func[b"7"] = decode_string ++decode_func[b"8"] = decode_string ++decode_func[b"9"] = decode_string + decode_func[CHR_LIST] = decode_list + decode_func[CHR_DICT] = decode_dict + decode_func[CHR_INT] = decode_int +@@ -243,14 +248,17 @@ def decode_none(x, f): + def make_fixed_length_string_decoders(): + def make_decoder(slen): + def f(x, f): +- s = x[f + 1:f + 1 + slen] ++ s = x[f + 1 : f + 1 + slen] + if _decode_utf8: + s = s.decode("utf8") + return (s, f + 1 + slen) ++ + return f ++ + for i in range(STR_FIXED_COUNT): + decode_func[int2byte(STR_FIXED_START + i)] = make_decoder(i) + ++ + make_fixed_length_string_decoders() + + +@@ -259,13 +267,16 @@ def make_decoder(slen): + def f(x, f): + r, f = [], f + 1 + for _ in range(slen): +- v, f = decode_func[x[f:f + 1]](x, f) ++ v, f = decode_func[x[f : f + 1]](x, f) + r.append(v) + return (tuple(r), f) ++ + return f ++ + for i in range(LIST_FIXED_COUNT): + decode_func[int2byte(LIST_FIXED_START + i)] = make_decoder(i) + ++ + make_fixed_length_list_decoders() + + +@@ -273,12 +284,15 @@ def make_fixed_length_int_decoders(): + def make_decoder(j): + def f(x, f): + return (j, f + 1) ++ + return f ++ + for i in range(INT_POS_FIXED_COUNT): + decode_func[int2byte(INT_POS_FIXED_START + i)] = make_decoder(i) + for i in range(INT_NEG_FIXED_COUNT): + decode_func[int2byte(INT_NEG_FIXED_START + i)] = make_decoder(-1 - i) + ++ + make_fixed_length_int_decoders() + + +@@ -287,13 +301,16 @@ def make_decoder(slen): + def f(x, f): + r, f = {}, f + 1 + for _ in range(slen): +- k, f = decode_func[x[f:f + 1]](x, f) +- r[k], f = decode_func[x[f:f + 1]](x, f) ++ k, f = decode_func[x[f : f + 1]](x, f) ++ r[k], f = decode_func[x[f : f + 1]](x, f) + return (r, f) ++ + return f ++ + for i in range(DICT_FIXED_COUNT): + decode_func[int2byte(DICT_FIXED_START + i)] = make_decoder(i) + ++ + make_fixed_length_dict_decoders() + + +@@ -315,29 +332,29 @@ def encode_int(x, r): + elif -INT_NEG_FIXED_COUNT <= x < 0: + r.append(int2byte(INT_NEG_FIXED_START - 1 - x)) + elif -128 <= x < 128: +- r.extend((CHR_INT1, struct.pack('!b', x))) ++ r.extend((CHR_INT1, struct.pack("!b", x))) + elif -32768 <= x < 32768: +- r.extend((CHR_INT2, struct.pack('!h', x))) ++ r.extend((CHR_INT2, struct.pack("!h", x))) + elif -2147483648 <= x < 2147483648: +- r.extend((CHR_INT4, struct.pack('!l', x))) ++ r.extend((CHR_INT4, struct.pack("!l", x))) + elif -9223372036854775808 <= x < 9223372036854775808: +- r.extend((CHR_INT8, struct.pack('!q', x))) ++ r.extend((CHR_INT8, struct.pack("!q", x))) + else: + s = str(x) + if py3: + s = bytes(s, "ascii") + + if len(s) >= MAX_INT_LENGTH: +- raise ValueError('overflow') ++ raise ValueError("overflow") + r.extend((CHR_INT, s, CHR_TERM)) + + + def encode_float32(x, r): +- r.extend((CHR_FLOAT32, struct.pack('!f', x))) ++ r.extend((CHR_FLOAT32, struct.pack("!f", x))) + + + def encode_float64(x, r): +- r.extend((CHR_FLOAT64, struct.pack('!d', x))) ++ r.extend((CHR_FLOAT64, struct.pack("!d", x))) + + + def encode_bool(x, r): +@@ -355,7 +372,7 @@ def encode_string(x, r): + s = str(len(x)) + if py3: + s = bytes(s, "ascii") +- r.extend((s, b':', x)) ++ r.extend((s, b":", x)) + + + def encode_unicode(x, r): +@@ -387,6 +404,7 @@ def encode_dict(x, r): + encode_func[type(v)](v, r) + r.append(CHR_TERM) + ++ + encode_func = {} + encode_func[int] = encode_int + encode_func[long] = encode_int +@@ -413,35 +431,67 @@ def dumps(x, float_bits=DEFAULT_FLOAT_BITS): + elif float_bits == 64: + encode_func[float] = encode_float64 + else: +- raise ValueError('Float bits (%d) is not 32 or 64' % float_bits) ++ raise ValueError("Float bits (%d) is not 32 or 64" % float_bits) + r = [] + encode_func[type(x)](x, r) +- return b''.join(r) ++ return b"".join(r) + + + def test(): +- f1 = struct.unpack('!f', struct.pack('!f', 25.5))[0] +- f2 = struct.unpack('!f', struct.pack('!f', 29.3))[0] +- f3 = struct.unpack('!f', struct.pack('!f', -0.6))[0] +- ld = (({b'a': 15, b'bb': f1, b'ccc': f2, b'': (f3, (), False, True, b'')}, (b'a', 10**20), +- tuple(range(-100000, 100000)), b'b' * 31, b'b' * 62, b'b' * 64, 2**30, 2**33, 2**62, +- 2**64, 2**30, 2**33, 2**62, 2**64, False, False, True, -1, 2, 0),) ++ f1 = struct.unpack("!f", struct.pack("!f", 25.5))[0] ++ f2 = struct.unpack("!f", struct.pack("!f", 29.3))[0] ++ f3 = struct.unpack("!f", struct.pack("!f", -0.6))[0] ++ ld = ( ++ ( ++ {b"a": 15, b"bb": f1, b"ccc": f2, b"": (f3, (), False, True, b"")}, ++ (b"a", 10 ** 20), ++ tuple(range(-100000, 100000)), ++ b"b" * 31, ++ b"b" * 62, ++ b"b" * 64, ++ 2 ** 30, ++ 2 ** 33, ++ 2 ** 62, ++ 2 ** 64, ++ 2 ** 30, ++ 2 ** 33, ++ 2 ** 62, ++ 2 ** 64, ++ False, ++ False, ++ True, ++ -1, ++ 2, ++ 0, ++ ), ++ ) + assert loads(dumps(ld)) == ld + d = dict(zip(range(-100000, 100000), range(-100000, 100000))) +- d.update({b'a': 20, 20: 40, 40: 41, f1: f2, f2: f3, f3: False, False: True, True: False}) +- ld = (d, {}, {5: 6}, {7: 7, True: 8}, {9: 10, 22: 39, 49: 50, 44: b''}) ++ d.update( ++ {b"a": 20, 20: 40, 40: 41, f1: f2, f2: f3, f3: False, False: True, True: False} ++ ) ++ ld = (d, {}, {5: 6}, {7: 7, True: 8}, {9: 10, 22: 39, 49: 50, 44: b""}) + assert loads(dumps(ld)) == ld +- ld = (b'', b'a' * 10, b'a' * 100, b'a' * 1000, b'a' * 10000, b'a' * 100000, b'a' * 1000000, b'a' * 10000000) ++ ld = ( ++ b"", ++ b"a" * 10, ++ b"a" * 100, ++ b"a" * 1000, ++ b"a" * 10000, ++ b"a" * 100000, ++ b"a" * 1000000, ++ b"a" * 10000000, ++ ) + assert loads(dumps(ld)) == ld +- ld = tuple([dict(zip(range(n), range(n))) for n in range(100)]) + (b'b',) ++ ld = tuple([dict(zip(range(n), range(n))) for n in range(100)]) + (b"b",) + assert loads(dumps(ld)) == ld +- ld = tuple([dict(zip(range(n), range(-n, 0))) for n in range(100)]) + (b'b',) ++ ld = tuple([dict(zip(range(n), range(-n, 0))) for n in range(100)]) + (b"b",) + assert loads(dumps(ld)) == ld +- ld = tuple([tuple(range(n)) for n in range(100)]) + (b'b',) ++ ld = tuple([tuple(range(n)) for n in range(100)]) + (b"b",) + assert loads(dumps(ld)) == ld +- ld = tuple([b'a' * n for n in range(1000)]) + (b'b',) ++ ld = tuple([b"a" * n for n in range(1000)]) + (b"b",) + assert loads(dumps(ld)) == ld +- ld = tuple([b'a' * n for n in range(1000)]) + (None, True, None) ++ ld = tuple([b"a" * n for n in range(1000)]) + (None, True, None) + assert loads(dumps(ld)) == ld + assert loads(dumps(None)) is None + assert loads(dumps({None: None})) == {None: None} +@@ -449,13 +499,16 @@ def test(): + assert 1e-10 < abs(loads(dumps(1.1, 32)) - 1.1) < 1e-6 + assert abs(loads(dumps(1.1, 64)) - 1.1) < 1e-12 + assert loads(dumps("Hello World!!"), decode_utf8=True) ++ ++ + try: + import psyco ++ + psyco.bind(dumps) + psyco.bind(loads) + except ImportError: + pass + + +-if __name__ == '__main__': ++if __name__ == "__main__": + test() +diff --git a/setup.py b/setup.py +index dcbd5dc..88e7275 100644 +--- a/setup.py ++++ b/setup.py +@@ -34,6 +34,7 @@ + from Cython.Build import cythonize + except ImportError as ex: + from setuptools.command.build_ext import build_ext ++ + cythonize = False + + source_ext = ".pyx" if cythonize else ".c" +@@ -42,16 +43,17 @@ + Extension( + "rencode._rencode", + extra_compile_args=["-O3"], +- sources=["rencode/rencode" + source_ext], ++ sources=["rencode/_rencode" + source_ext], + ), + ] + +-if 'sdist' in sys.argv and not cythonize: +- exit('Error: sdist requires cython module to generate `.c` file.') ++if "sdist" in sys.argv and not cythonize: ++ exit("Error: sdist requires cython module to generate `.c` file.") + + if cythonize: + ext_modules = cythonize(ext_modules) + ++ + class optional_build_ext(build_ext): + # This class allows C extension building to fail. + def run(self): +@@ -71,26 +73,28 @@ def build_extension(self, ext): + self._unavailable(e) + + def _unavailable(self, exc): +- print('*' * 70) +- print("""WARNING: ++ print("*" * 70) ++ print( ++ """WARNING: + The C extension could not be compiled, speedups will not be +-available.""") +- print('*' * 70) ++available.""" ++ ) ++ print("*" * 70) + print(exc) + + + setup( +- name="rencode", +- version="1.0.6", +- packages=["rencode"], +- description="Web safe object pickling/unpickling", +- long_description=open("README.md").read(), +- long_description_content_type="text/markdown", +- license='GPLv3', +- author="Andrew Resch", +- author_email="andrewresch@gmail.com", +- url="https://github.com/aresch/rencode", +- cmdclass={'build_ext': optional_build_ext}, +- ext_modules=ext_modules, +- setup_requires=['setuptools', 'wheel'], ++ name="rencode", ++ version="1.0.6", ++ packages=["rencode"], ++ description="Web safe object pickling/unpickling", ++ long_description=open("README.md").read(), ++ long_description_content_type="text/markdown", ++ license="GPLv3", ++ author="Andrew Resch", ++ author_email="andrewresch@gmail.com", ++ url="https://github.com/aresch/rencode", ++ cmdclass={"build_ext": optional_build_ext}, ++ ext_modules=ext_modules, ++ setup_requires=["setuptools"], + ) +diff --git a/tests/test_rencode.py b/tests/test_rencode.py +index 35b2dc0..74737eb 100644 +--- a/tests/test_rencode.py ++++ b/tests/test_rencode.py +@@ -31,12 +31,16 @@ + + + # Hack to deal with python 2 and 3 differences with unicode literals. +-if sys.version < '3': ++if sys.version < "3": + import codecs ++ + def u(x): + return codecs.unicode_escape_decode(x)[0] ++ ++ + else: + unicode = str ++ + def u(x): + return x + +@@ -63,13 +67,18 @@ def test_encode_int_int_size(self): + self.assertEqual(rencode.dumps(-7483648), rencode_orig.dumps(-7483648)) + + def test_encode_int_long_long_size(self): +- self.assertEqual(rencode.dumps(8223372036854775808), rencode_orig.dumps(8223372036854775808)) +- self.assertEqual(rencode.dumps(-8223372036854775808), rencode_orig.dumps(-8223372036854775808)) ++ self.assertEqual( ++ rencode.dumps(8223372036854775808), rencode_orig.dumps(8223372036854775808) ++ ) ++ self.assertEqual( ++ rencode.dumps(-8223372036854775808), ++ rencode_orig.dumps(-8223372036854775808), ++ ) + + def test_encode_int_big_number(self): +- n = int("9"*62) ++ n = int("9" * 62) + self.assertEqual(rencode.dumps(n), rencode_orig.dumps(n)) +- self.assertRaises(ValueError, rencode.dumps, int("9"*65)) ++ self.assertRaises(ValueError, rencode.dumps, int("9" * 65)) + + def test_encode_float_32bit(self): + self.assertEqual(rencode.dumps(1234.56), rencode_orig.dumps(1234.56)) +@@ -84,7 +93,7 @@ def test_encode_fixed_str(self): + self.assertEqual(rencode.dumps(b"foobarbaz"), rencode_orig.dumps(b"foobarbaz")) + + def test_encode_str(self): +- self.assertEqual(rencode.dumps(b"f"*255), rencode_orig.dumps(b"f"*255)) ++ self.assertEqual(rencode.dumps(b"f" * 255), rencode_orig.dumps(b"f" * 255)) + self.assertEqual(rencode.dumps(b"\0"), rencode_orig.dumps(b"\0")) + + def test_encode_unicode(self): +@@ -98,21 +107,21 @@ def test_encode_bool(self): + self.assertEqual(rencode.dumps(False), rencode_orig.dumps(False)) + + def test_encode_fixed_list(self): +- l = [100, -234.01, b"foobar", u("bäz")]*4 ++ l = [100, -234.01, b"foobar", u("bäz")] * 4 + self.assertEqual(rencode.dumps(l), rencode_orig.dumps(l)) + + def test_encode_list(self): +- l = [100, -234.01, b"foobar", u("bäz")]*80 ++ l = [100, -234.01, b"foobar", u("bäz")] * 80 + self.assertEqual(rencode.dumps(l), rencode_orig.dumps(l)) + + def test_encode_fixed_dict(self): + s = b"abcdefghijk" +- d = dict(zip(s, [1234]*len(s))) ++ d = dict(zip(s, [1234] * len(s))) + self.assertEqual(rencode.dumps(d), rencode_orig.dumps(d)) + + def test_encode_dict(self): + s = b"abcdefghijklmnopqrstuvwxyz1234567890" +- d = dict(zip(s, [1234]*len(s))) ++ d = dict(zip(s, [1234] * len(s))) + self.assertEqual(rencode.dumps(d), rencode_orig.dumps(d)) + + def test_decode_fixed_pos_int(self): +@@ -137,13 +146,17 @@ def test_decode_int(self): + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([64]))) + + def test_decode_long_long(self): +- self.assertEqual(rencode.loads(rencode.dumps(8223372036854775808)), 8223372036854775808) +- self.assertEqual(rencode.loads(rencode.dumps(-8223372036854775808)), -8223372036854775808) ++ self.assertEqual( ++ rencode.loads(rencode.dumps(8223372036854775808)), 8223372036854775808 ++ ) ++ self.assertEqual( ++ rencode.loads(rencode.dumps(-8223372036854775808)), -8223372036854775808 ++ ) + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([65]))) + + def test_decode_int_big_number(self): +- n = int(b"9"*62) +- toobig = '={x}\x7f'.format(x='9'*65).encode() ++ n = int(b"9" * 62) ++ toobig = "={x}\x7f".format(x="9" * 65).encode() + self.assertEqual(rencode.loads(rencode.dumps(n)), n) + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([61]))) + self.assertRaises(ValueError, rencode.loads, toobig) +@@ -163,11 +176,13 @@ def test_decode_fixed_str(self): + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([130]))) + + def test_decode_str(self): +- self.assertEqual(rencode.loads(rencode.dumps(b"f"*255)), b"f"*255) ++ self.assertEqual(rencode.loads(rencode.dumps(b"f" * 255)), b"f" * 255) + self.assertRaises(IndexError, rencode.loads, b"50") + + def test_decode_unicode(self): +- self.assertEqual(rencode.loads(rencode.dumps(u("fööbar"))), u("fööbar").encode("utf8")) ++ self.assertEqual( ++ rencode.loads(rencode.dumps(u("fööbar"))), u("fööbar").encode("utf8") ++ ) + + def test_decode_none(self): + self.assertEqual(rencode.loads(rencode.dumps(None)), None) +@@ -177,24 +192,24 @@ def test_decode_bool(self): + self.assertEqual(rencode.loads(rencode.dumps(False)), False) + + def test_decode_fixed_list(self): +- l = [100, False, b"foobar", u("bäz").encode("utf8")]*4 ++ l = [100, False, b"foobar", u("bäz").encode("utf8")] * 4 + self.assertEqual(rencode.loads(rencode.dumps(l)), tuple(l)) + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([194]))) + + def test_decode_list(self): +- l = [100, False, b"foobar", u("bäz").encode("utf8")]*80 ++ l = [100, False, b"foobar", u("bäz").encode("utf8")] * 80 + self.assertEqual(rencode.loads(rencode.dumps(l)), tuple(l)) + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([59]))) + + def test_decode_fixed_dict(self): + s = b"abcdefghijk" +- d = dict(zip(s, [1234]*len(s))) ++ d = dict(zip(s, [1234] * len(s))) + self.assertEqual(rencode.loads(rencode.dumps(d)), d) + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([104]))) + + def test_decode_dict(self): + s = b"abcdefghijklmnopqrstuvwxyz1234567890" +- d = dict(zip(s, [b"foo"*120]*len(s))) ++ d = dict(zip(s, [b"foo" * 120] * len(s))) + d2 = {b"foo": d, b"bar": d, b"baz": d} + self.assertEqual(rencode.loads(rencode.dumps(d2)), d2) + self.assertRaises(IndexError, rencode.loads, bytes(bytearray([60]))) +@@ -205,23 +220,192 @@ def test_decode_str_bytes(self): + self.assertEqual(rencode.loads(rencode.dumps(d)), d) + + def test_decode_str_nullbytes(self): +- b = (202, 132, 100, 114, 97, 119, 1, 0, 0, 63, 1, 242, 63, 1, 60, 132, 120, 50, 54, 52, 49, 51, 48, 58, 0, 0, 0, 1, 65, 154, 35, 215, 48, 204, 4, 35, 242, 3, 122, 218, 67, 192, 127, 40, 241, 127, 2, 86, 240, 63, 135, 177, 23, 119, 63, 31, 226, 248, 19, 13, 192, 111, 74, 126, 2, 15, 240, 31, 239, 48, 85, 238, 159, 155, 197, 241, 23, 119, 63, 2, 23, 245, 63, 24, 240, 86, 36, 176, 15, 187, 185, 248, 242, 255, 0, 126, 123, 141, 206, 60, 188, 1, 27, 254, 141, 169, 132, 93, 220, 252, 121, 184, 8, 31, 224, 63, 244, 226, 75, 224, 119, 135, 229, 248, 3, 243, 248, 220, 227, 203, 193, 3, 224, 127, 47, 134, 59, 5, 99, 249, 254, 35, 196, 127, 17, 252, 71, 136, 254, 35, 196, 112, 4, 177, 3, 63, 5, 220) ++ b = ( ++ 202, ++ 132, ++ 100, ++ 114, ++ 97, ++ 119, ++ 1, ++ 0, ++ 0, ++ 63, ++ 1, ++ 242, ++ 63, ++ 1, ++ 60, ++ 132, ++ 120, ++ 50, ++ 54, ++ 52, ++ 49, ++ 51, ++ 48, ++ 58, ++ 0, ++ 0, ++ 0, ++ 1, ++ 65, ++ 154, ++ 35, ++ 215, ++ 48, ++ 204, ++ 4, ++ 35, ++ 242, ++ 3, ++ 122, ++ 218, ++ 67, ++ 192, ++ 127, ++ 40, ++ 241, ++ 127, ++ 2, ++ 86, ++ 240, ++ 63, ++ 135, ++ 177, ++ 23, ++ 119, ++ 63, ++ 31, ++ 226, ++ 248, ++ 19, ++ 13, ++ 192, ++ 111, ++ 74, ++ 126, ++ 2, ++ 15, ++ 240, ++ 31, ++ 239, ++ 48, ++ 85, ++ 238, ++ 159, ++ 155, ++ 197, ++ 241, ++ 23, ++ 119, ++ 63, ++ 2, ++ 23, ++ 245, ++ 63, ++ 24, ++ 240, ++ 86, ++ 36, ++ 176, ++ 15, ++ 187, ++ 185, ++ 248, ++ 242, ++ 255, ++ 0, ++ 126, ++ 123, ++ 141, ++ 206, ++ 60, ++ 188, ++ 1, ++ 27, ++ 254, ++ 141, ++ 169, ++ 132, ++ 93, ++ 220, ++ 252, ++ 121, ++ 184, ++ 8, ++ 31, ++ 224, ++ 63, ++ 244, ++ 226, ++ 75, ++ 224, ++ 119, ++ 135, ++ 229, ++ 248, ++ 3, ++ 243, ++ 248, ++ 220, ++ 227, ++ 203, ++ 193, ++ 3, ++ 224, ++ 127, ++ 47, ++ 134, ++ 59, ++ 5, ++ 99, ++ 249, ++ 254, ++ 35, ++ 196, ++ 127, ++ 17, ++ 252, ++ 71, ++ 136, ++ 254, ++ 35, ++ 196, ++ 112, ++ 4, ++ 177, ++ 3, ++ 63, ++ 5, ++ 220, ++ ) + d = bytes(bytearray(b)) + self.assertEqual(rencode.loads(rencode.dumps(d)), d) + + def test_decode_utf8(self): + s = b"foobarbaz" +- #no assertIsInstance with python2.6 ++ # no assertIsInstance with python2.6 + d = rencode.loads(rencode.dumps(s), decode_utf8=True) + if not isinstance(d, unicode): +- self.fail('%s is not an instance of %r' % (repr(d), unicode)) ++ self.fail("%s is not an instance of %r" % (repr(d), unicode)) + s = rencode.dumps(b"\x56\xe4foo\xc3") + self.assertRaises(UnicodeDecodeError, rencode.loads, s, decode_utf8=True) + + def test_version_exposed(self): + assert rencode.__version__ + assert rencode_orig.__version__ +- self.assertEqual(rencode.__version__[1:], rencode_orig.__version__[1:], "version number does not match") ++ self.assertEqual( ++ rencode.__version__[1:], ++ rencode_orig.__version__[1:], ++ "version number does not match", ++ ) ++ ++ def test_invalid_typecode(self): ++ s = b";\x2f\x7f" ++ with self.assertRaises(ValueError): ++ rencode.loads(s) ++ + +-if __name__ == '__main__': ++if __name__ == "__main__": + unittest.main() +diff --git a/tests/timetest.py b/tests/timetest.py +index 0d98ffb..06a0456 100644 +--- a/tests/timetest.py ++++ b/tests/timetest.py +@@ -27,257 +27,363 @@ + from rencode import rencode_orig + + import sys ++ + # Hack to deal with python 2 and 3 differences with unicode literals. +-if sys.version < '3': ++if sys.version < "3": + import codecs ++ + def u(x): + return codecs.unicode_escape_decode(x)[0] ++ ++ + else: + unicode = str ++ + def u(x): + return x +- ++ ++ + # Encode functions + ++ + def test_encode_fixed_pos_int(): + rencode.dumps(40) + ++ + def test_encode_fixed_pos_int_orig(): + rencode_orig.dumps(40) + ++ + def test_encode_fixed_neg_int(): + rencode.dumps(-29) + ++ + def test_encode_fixed_neg_int_orig(): + rencode_orig.dumps(-29) + ++ + def test_encode_int_char_size(): + rencode.dumps(100) + rencode.dumps(-100) + ++ + def test_encode_int_char_size_orig(): + rencode_orig.dumps(100) + rencode_orig.dumps(-100) + ++ + def test_encode_int_short_size(): + rencode.dumps(27123) + rencode.dumps(-27123) + ++ + def test_encode_int_short_size_orig(): + rencode_orig.dumps(27123) + rencode_orig.dumps(-27123) + ++ + def test_encode_int_int_size(): + rencode.dumps(7483648) + rencode.dumps(-7483648) + ++ + def test_encode_int_int_size_orig(): + rencode_orig.dumps(7483648) + rencode_orig.dumps(-7483648) + ++ + def test_encode_int_long_long_size(): + rencode.dumps(8223372036854775808) + rencode.dumps(-8223372036854775808) + ++ + def test_encode_int_long_long_size_orig(): + rencode_orig.dumps(8223372036854775808) + rencode_orig.dumps(-8223372036854775808) + +-bn = int("9"*62) ++ ++bn = int("9" * 62) ++ ++ + def test_encode_int_big_number(): + rencode.dumps(bn) + ++ + def test_encode_int_big_number_orig(): + rencode_orig.dumps(bn) + ++ + def test_encode_float_32bit(): + rencode.dumps(1234.56) + ++ + def test_encode_float_32bit_orig(): + rencode_orig.dumps(1234.56) + ++ + def test_encode_float_64bit(): + rencode.dumps(1234.56, 64) + ++ + def test_encode_float_64bit_orig(): + rencode_orig.dumps(1234.56, 64) + ++ + def test_encode_fixed_str(): + rencode.dumps(b"foobarbaz") + ++ + def test_encode_fixed_str_orig(): + rencode_orig.dumps(b"foobarbaz") + +-s = b"f"*255 ++ ++s = b"f" * 255 ++ ++ + def test_encode_str(): + rencode.dumps(s) + ++ + def test_encode_str_orig(): + rencode_orig.dumps(s) + ++ + def test_encode_none(): + rencode.dumps(None) + ++ + def test_encode_none_orig(): + rencode_orig.dumps(None) + ++ + def test_encode_bool(): + rencode.dumps(True) + ++ + def test_encode_bool_orig(): + rencode_orig.dumps(True) + ++ + l = [None, None, None, None] ++ ++ + def test_encode_fixed_list(): + rencode.dumps(l) + ++ + def test_encode_fixed_list_orig(): + rencode_orig.dumps(l) + +-ll = [None]*80 ++ ++ll = [None] * 80 ++ ++ + def test_encode_list(): + rencode.dumps(ll) + ++ + def test_encode_list_orig(): + rencode_orig.dumps(ll) + ++ + keys = b"abcdefghijk" +-d = dict(zip(keys, [None]*len(keys))) ++d = dict(zip(keys, [None] * len(keys))) ++ + + def test_encode_fixed_dict(): + rencode.dumps(d) + ++ + def test_encode_fixed_dict_orig(): + rencode_orig.dumps(d) + ++ + keys2 = b"abcdefghijklmnopqrstuvwxyz1234567890" +-d2 = dict(zip(keys2, [None]*len(keys2))) ++d2 = dict(zip(keys2, [None] * len(keys2))) ++ + + def test_encode_dict(): + rencode.dumps(d2) + ++ + def test_encode_dict_orig(): + rencode_orig.dumps(d2) + + + # Decode functions + ++ + def test_decode_fixed_pos_int(): +- rencode.loads(b'(') ++ rencode.loads(b"(") ++ + + def test_decode_fixed_pos_int_orig(): +- rencode_orig.loads(b'(') ++ rencode_orig.loads(b"(") ++ + + def test_decode_fixed_neg_int(): +- rencode.loads(b'b') ++ rencode.loads(b"b") ++ + + def test_decode_fixed_neg_int_orig(): +- rencode_orig.loads(b'b') ++ rencode_orig.loads(b"b") ++ + + def test_decode_int_char_size(): +- rencode.loads(b'>d') +- rencode.loads(b'>\x9c') ++ rencode.loads(b">d") ++ rencode.loads(b">\x9c") ++ + + def test_decode_int_char_size_orig(): +- rencode_orig.loads(b'>d') +- rencode_orig.loads(b'>\x9c') ++ rencode_orig.loads(b">d") ++ rencode_orig.loads(b">\x9c") ++ + + def test_decode_int_short_size(): +- rencode.loads(b'?i\xf3') +- rencode.loads(b'?\x96\r') ++ rencode.loads(b"?i\xf3") ++ rencode.loads(b"?\x96\r") ++ + + def test_decode_int_short_size_orig(): +- rencode_orig.loads(b'?i\xf3') +- rencode_orig.loads(b'?\x96\r') ++ rencode_orig.loads(b"?i\xf3") ++ rencode_orig.loads(b"?\x96\r") ++ + + def test_decode_int_int_size(): +- rencode.loads(b'@\x00r1\x00') +- rencode.loads(b'@\xff\x8d\xcf\x00') ++ rencode.loads(b"@\x00r1\x00") ++ rencode.loads(b"@\xff\x8d\xcf\x00") ++ + + def test_decode_int_int_size_orig(): +- rencode_orig.loads(b'@\x00r1\x00') +- rencode_orig.loads(b'@\xff\x8d\xcf\x00') ++ rencode_orig.loads(b"@\x00r1\x00") ++ rencode_orig.loads(b"@\xff\x8d\xcf\x00") ++ + + def test_decode_int_long_long_size(): +- rencode.loads(b'Ar\x1fILX\x9c\x00\x00') +- rencode.loads(b'A\x8d\xe0\xb6\xb3\xa7d\x00\x00') ++ rencode.loads(b"Ar\x1fILX\x9c\x00\x00") ++ rencode.loads(b"A\x8d\xe0\xb6\xb3\xa7d\x00\x00") ++ + + def test_decode_int_long_long_size_orig(): +- rencode_orig.loads(b'Ar\x1fILX\x9c\x00\x00') +- rencode_orig.loads(b'A\x8d\xe0\xb6\xb3\xa7d\x00\x00') ++ rencode_orig.loads(b"Ar\x1fILX\x9c\x00\x00") ++ rencode_orig.loads(b"A\x8d\xe0\xb6\xb3\xa7d\x00\x00") ++ + + def test_decode_int_big_number(): +- rencode.loads(b'=99999999999999999999999999999999999999999999999999999999999999\x7f') ++ rencode.loads( ++ b"=99999999999999999999999999999999999999999999999999999999999999\x7f" ++ ) ++ + + def test_decode_int_big_number_orig(): +- rencode_orig.loads(b'=99999999999999999999999999999999999999999999999999999999999999\x7f') ++ rencode_orig.loads( ++ b"=99999999999999999999999999999999999999999999999999999999999999\x7f" ++ ) ++ + + def test_decode_float_32bit(): +- rencode.loads(b'BD\x9aQ\xec') ++ rencode.loads(b"BD\x9aQ\xec") ++ + + def test_decode_float_32bit_orig(): +- rencode_orig.loads(b'BD\x9aQ\xec') ++ rencode_orig.loads(b"BD\x9aQ\xec") ++ + + def test_decode_float_64bit(): +- rencode.loads(b',@\x93J=p\xa3\xd7\n') ++ rencode.loads(b",@\x93J=p\xa3\xd7\n") ++ + + def test_decode_float_64bit_orig(): +- rencode_orig.loads(b',@\x93J=p\xa3\xd7\n') ++ rencode_orig.loads(b",@\x93J=p\xa3\xd7\n") ++ + + def test_decode_fixed_str(): +- rencode.loads(b'\x89foobarbaz') ++ rencode.loads(b"\x89foobarbaz") ++ + + def test_decode_fixed_str_orig(): +- rencode_orig.loads(b'\x89foobarbaz') ++ rencode_orig.loads(b"\x89foobarbaz") ++ + + def test_decode_str(): +- rencode.loads(b'255:fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') ++ rencode.loads( ++ b"255:fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ++ ) ++ + + def test_decode_str_orig(): +- rencode_orig.loads(b'255:fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') ++ rencode_orig.loads( ++ b"255:fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ++ ) ++ + + def test_decode_none(): +- rencode.loads(b'E') ++ rencode.loads(b"E") ++ + + def test_decode_none_orig(): +- rencode_orig.loads(b'E') ++ rencode_orig.loads(b"E") ++ + + def test_decode_bool(): +- rencode.loads(b'C') ++ rencode.loads(b"C") ++ + + def test_decode_bool_orig(): +- rencode_orig.loads(b'C') ++ rencode_orig.loads(b"C") ++ + + def test_decode_fixed_list(): +- rencode.loads(b'\xc4EEEE') ++ rencode.loads(b"\xc4EEEE") ++ + + def test_decode_fixed_list_orig(): +- rencode_orig.loads(b'\xc4EEEE') ++ rencode_orig.loads(b"\xc4EEEE") ++ + + def test_decode_list(): +- rencode.loads(b';EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\x7f') ++ rencode.loads( ++ b";EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\x7f" ++ ) ++ + + def test_decode_list_orig(): +- rencode_orig.loads(b';EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\x7f') ++ rencode_orig.loads( ++ b";EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\x7f" ++ ) ++ + + def test_decode_fixed_dict(): +- rencode.loads(b'q\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE') ++ rencode.loads( ++ b"q\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE" ++ ) ++ + + def test_decode_fixed_dict_orig(): +- rencode_orig.loads(b'q\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE') ++ rencode_orig.loads( ++ b"q\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE" ++ ) ++ + + def test_decode_dict(): +- rencode.loads(b'<\x811E\x810E\x813E\x812E\x815E\x814E\x817E\x816E\x819E\x818E\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE\x81mE\x81lE\x81oE\x81nE\x81qE\x81pE\x81sE\x81rE\x81uE\x81tE\x81wE\x81vE\x81yE\x81xE\x81zE\x7f') ++ rencode.loads( ++ b"<\x811E\x810E\x813E\x812E\x815E\x814E\x817E\x816E\x819E\x818E\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE\x81mE\x81lE\x81oE\x81nE\x81qE\x81pE\x81sE\x81rE\x81uE\x81tE\x81wE\x81vE\x81yE\x81xE\x81zE\x7f" ++ ) ++ + + def test_decode_dict_orig(): +- rencode_orig.loads(b'<\x811E\x810E\x813E\x812E\x815E\x814E\x817E\x816E\x819E\x818E\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE\x81mE\x81lE\x81oE\x81nE\x81qE\x81pE\x81sE\x81rE\x81uE\x81tE\x81wE\x81vE\x81yE\x81xE\x81zE\x7f') ++ rencode_orig.loads( ++ b"<\x811E\x810E\x813E\x812E\x815E\x814E\x817E\x816E\x819E\x818E\x81aE\x81cE\x81bE\x81eE\x81dE\x81gE\x81fE\x81iE\x81hE\x81kE\x81jE\x81mE\x81lE\x81oE\x81nE\x81qE\x81pE\x81sE\x81rE\x81uE\x81tE\x81wE\x81vE\x81yE\x81xE\x81zE\x7f" ++ ) + + + overall = [ + b"5ce750f0954ce1537676c7a5fe38b0de30ba7eb65ce750f0954ce1537676c7a5fe38b0de30ba7eb6", + b"fixedlength", + u("unicodestring"), +- u("5ce750f0954ce1537676c7a5fe38b0de30ba7eb65ce750f0954ce1537676c7a5fe38b0de30ba7eb6"), ++ u( ++ "5ce750f0954ce1537676c7a5fe38b0de30ba7eb65ce750f0954ce1537676c7a5fe38b0de30ba7eb6" ++ ), + -10, + 10, + 120, +@@ -287,23 +393,28 @@ def test_decode_dict_orig(): + -7483648, + 8223372036854775808, + -8223372036854775808, +- int("9"*62), ++ int("9" * 62), + 1227688834.643409, + None, +- True ++ True, + ] + ++ + def test_overall_encode(): + rencode.dumps(overall) + ++ + def test_overall_encode_orig(): + rencode_orig.dumps(overall) + ++ + overall_decode_str = rencode_orig.dumps(overall) + ++ + def test_overall_decode(): + rencode.loads(overall_decode_str) + ++ + def test_overall_decode_orig(): + rencode_orig.loads(overall_decode_str) + +@@ -313,18 +424,36 @@ def test_overall_decode_orig(): + + iterations = 10000 + # ANSI escape codes +- CSI="\x1B[" +- reset=CSI+"m" ++ CSI = "\x1B[" ++ reset = CSI + "m" + + def do_test(func): + print("%s:" % func) +- new_time = timeit.Timer("%s()" % func, "from __main__ import %s" % func).timeit(iterations) +- orig_time = timeit.Timer("%s_orig()" % func, "from __main__ import %s_orig" % func).timeit(iterations) ++ new_time = timeit.Timer("%s()" % func, "from __main__ import %s" % func).timeit( ++ iterations ++ ) ++ orig_time = timeit.Timer( ++ "%s_orig()" % func, "from __main__ import %s_orig" % func ++ ).timeit(iterations) + if new_time > orig_time: + new = CSI + "31m%.3fs%s" % (new_time, reset) +- orig = CSI + "32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % (orig_time, reset, CSI, new_time-orig_time, reset, (new_time/orig_time)*100) ++ orig = CSI + "32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % ( ++ orig_time, ++ reset, ++ CSI, ++ new_time - orig_time, ++ reset, ++ (new_time / orig_time) * 100, ++ ) + else: +- new = CSI + "32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % (new_time, reset, CSI, orig_time-new_time, reset, (orig_time/new_time)*100) ++ new = CSI + "32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % ( ++ new_time, ++ reset, ++ CSI, ++ orig_time - new_time, ++ reset, ++ (orig_time / new_time) * 100, ++ ) + orig = CSI + "31m%.3fs%s" % (orig_time, reset) + + print("\trencode.pyx: %s" % new) +@@ -352,9 +481,25 @@ def do_test(func): + print("%s functions totals:" % (t.title())) + if total_new > total_orig: + new = CSI + "31m%.3fs%s" % (total_new, reset) +- orig = "%s32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % (CSI, total_orig, reset, CSI, total_new-total_orig, reset, (total_new/total_orig)*100) ++ orig = "%s32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % ( ++ CSI, ++ total_orig, ++ reset, ++ CSI, ++ total_new - total_orig, ++ reset, ++ (total_new / total_orig) * 100, ++ ) + else: +- new = "%s32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % (CSI, total_new, reset, CSI, total_orig-total_new, reset, (total_orig/total_new)*100) ++ new = "%s32m%.3fs%s (%s34m+%.3fs%s) %.2f%%" % ( ++ CSI, ++ total_new, ++ reset, ++ CSI, ++ total_orig - total_new, ++ reset, ++ (total_orig / total_new) * 100, ++ ) + orig = CSI + "31m%.3fs%s" % (total_orig, reset) + + print("\trencode.pyx: %s" % new)