Author: Armin Rigo <[email protected]>
Branch:
Changeset: r81579:af91853285d1
Date: 2016-01-05 13:52 +0100
http://bitbucket.org/pypy/pypy/changeset/af91853285d1/
Log: Add __pypy__.decode_long(), an app-level interface to
rbigint.frombytes(). Use it in the pickle.py module.
diff --git a/lib-python/2.7/pickle.py b/lib-python/2.7/pickle.py
--- a/lib-python/2.7/pickle.py
+++ b/lib-python/2.7/pickle.py
@@ -1376,6 +1376,7 @@
def decode_long(data):
r"""Decode a long from a two's complement little-endian binary string.
+ This is overriden on PyPy by a RPython version that has linear complexity.
>>> decode_long('')
0L
@@ -1402,6 +1403,11 @@
n -= 1L << (nbytes * 8)
return n
+try:
+ from __pypy__ import decode_long
+except ImportError:
+ pass
+
# Shorthands
try:
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -89,6 +89,7 @@
'set_code_callback' : 'interp_magic.set_code_callback',
'save_module_content_for_future_reload':
'interp_magic.save_module_content_for_future_reload',
+ 'decode_long' : 'interp_magic.decode_long',
}
if sys.platform == 'win32':
interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp'
diff --git a/pypy/module/__pypy__/interp_magic.py
b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -1,4 +1,4 @@
-from pypy.interpreter.error import OperationError, wrap_oserror
+from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.pycode import CodeHookCache
from pypy.interpreter.pyframe import PyFrame
@@ -158,4 +158,13 @@
if space.is_none(w_callable):
cache._code_hook = None
else:
- cache._code_hook = w_callable
\ No newline at end of file
+ cache._code_hook = w_callable
+
+@unwrap_spec(string=str, byteorder=str, signed=int)
+def decode_long(space, string, byteorder='little', signed=1):
+ from rpython.rlib.rbigint import rbigint, InvalidEndiannessError
+ try:
+ result = rbigint.frombytes(string, byteorder, bool(signed))
+ except InvalidEndiannessError:
+ raise oefmt(space.w_ValueError, "invalid byteorder argument")
+ return space.newlong_from_rbigint(result)
diff --git a/pypy/module/__pypy__/test/test_magic.py
b/pypy/module/__pypy__/test/test_magic.py
--- a/pypy/module/__pypy__/test/test_magic.py
+++ b/pypy/module/__pypy__/test/test_magic.py
@@ -30,4 +30,20 @@
""" in d
finally:
__pypy__.set_code_callback(None)
- assert d['f'].__code__ in l
\ No newline at end of file
+ assert d['f'].__code__ in l
+
+ def test_decode_long(self):
+ from __pypy__ import decode_long
+ assert decode_long('') == 0
+ assert decode_long('\xff\x00') == 255
+ assert decode_long('\xff\x7f') == 32767
+ assert decode_long('\x00\xff') == -256
+ assert decode_long('\x00\x80') == -32768
+ assert decode_long('\x80') == -128
+ assert decode_long('\x7f') == 127
+ assert decode_long('\x55' * 97) == (1 << (97 * 8)) // 3
+ assert decode_long('\x00\x80', 'big') == 128
+ assert decode_long('\xff\x7f', 'little', False) == 32767
+ assert decode_long('\x00\x80', 'little', False) == 32768
+ assert decode_long('\x00\x80', 'little', True) == -32768
+ raises(ValueError, decode_long, '', 'foo')
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit