[pypy-commit] pypy stdlib-2.7.13: Give up, revert and skip the cpython test, and document in
arigo
pypy.commits at gmail.com
Sun Dec 18 15:28:07 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: stdlib-2.7.13
Changeset: r89163:803a7b9b59bf
Date: 2016-12-18 21:27 +0100
http://bitbucket.org/pypy/pypy/changeset/803a7b9b59bf/
Log: Give up, revert and skip the cpython test, and document in
cpython_differences.rst
diff --git a/lib-python/2.7/test/test_format.py b/lib-python/2.7/test/test_format.py
--- a/lib-python/2.7/test/test_format.py
+++ b/lib-python/2.7/test/test_format.py
@@ -337,8 +337,10 @@
except exc:
pass
else:
- self.fail('%s not raised for %r format of %r' %
- (exc.__name__, fmt, result))
+ if test_support.check_impl_detail():
+ self.fail('%s not raised for %r format of %r' %
+ (exc.__name__, fmt, result))
+ #else (PyPy): at least it didn't explode, good enough
def test_main():
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -478,6 +478,16 @@
from the Makefile used to build the interpreter. PyPy should bake the values
in during compilation, but does not do that yet.
+* ``"%d" % x`` and ``"%x" % x`` and similar constructs, where ``x`` is
+ an instance of a subclass of ``long`` that overrides the special
+ methods ``__str__`` or ``__hex__`` or ``__oct__``: PyPy doesn't call
+ the special methods; CPython does---but only if it is a subclass of
+ ``long``, not ``int``. CPython's behavior is really messy: e.g. for
+ ``%x`` it calls ``__hex__()``, which is supposed to return a string
+ like ``-0x123L``; then the ``0x`` and the final ``L`` are removed, and
+ the rest is kept. If you return an unexpected string from
+ ``__hex__()`` you get an exception (or a crash before CPython 2.7.13).
+
.. _`is ignored in PyPy`: http://bugs.python.org/issue14621
.. _`little point`: http://events.ccc.de/congress/2012/Fahrplan/events/5152.en.html
.. _`#2072`: https://bitbucket.org/pypy/pypy/issue/2072/
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -547,7 +547,7 @@
# make sure that w_value is a wrapped float
return space.float(w_value)
-def format_num_helper_generator(fmt, digits, method, remove_prefix=''):
+def format_num_helper_generator(fmt, digits):
def format_num_helper(space, w_value):
if (not space.isinstance_w(w_value, space.w_int) and
not space.isinstance_w(w_value, space.w_long)):
@@ -563,27 +563,17 @@
"%s format: a number is required, not %T", fmt, w_value)
else:
raise
- if space.isinstance_w(w_value, space.w_long):
- text = space.str_w(space.call_method(w_value, method))
- skip_left = 0
- skip_right = len(text)
- if remove_prefix:
- if not text.startswith(remove_prefix):
- raise oefmt(space.w_ValueError,
- "%s format: invalid result of %s (type=%T)",
- fmt, method, w_value)
- skip_left = len(remove_prefix)
- if text.endswith('L'):
- skip_right = len(text) - 1
- assert skip_right >= 0
- return text[skip_left : skip_right]
- else:
+ try:
value = space.int_w(w_value)
return fmt % (value,)
+ except OperationError as operr:
+ if not operr.match(space, space.w_OverflowError):
+ raise
+ num = space.bigint_w(w_value)
+ return num.format(digits)
return func_with_new_name(format_num_helper,
'base%d_num_helper' % len(digits))
-int_num_helper = format_num_helper_generator('%d', '0123456789', '__str__')
-oct_num_helper = format_num_helper_generator('%o', '01234567', '__oct__', '0')
-hex_num_helper = format_num_helper_generator('%x', '0123456789abcdef',
- '__hex__', '0x')
+int_num_helper = format_num_helper_generator('%d', '0123456789')
+oct_num_helper = format_num_helper_generator('%o', '01234567')
+hex_num_helper = format_num_helper_generator('%x', '0123456789abcdef')
diff --git a/pypy/objspace/std/test/test_stringformat.py b/pypy/objspace/std/test/test_stringformat.py
--- a/pypy/objspace/std/test/test_stringformat.py
+++ b/pypy/objspace/std/test/test_stringformat.py
@@ -138,11 +138,6 @@
assert '%d' % sl == '4800000000'
def test_format_subclass_with_str(self):
- import sys
- if sys.version_info < (2, 7, 13):
- skip("CPython gives SystemError before 2.7.13")
- #...and behaves inconsistently in 2.7.13, but we reproduce that
-
class SubInt2(int):
def __str__(self):
assert False, "not called"
@@ -162,6 +157,12 @@
assert '%X' % sl == '7B'
assert '%o' % sl == '173'
+ skip("the rest of this test is serious nonsense imho, changed "
+ "only on 2.7.13, and is different on 3.x anyway. We could "
+ "reproduce it by writing lengthy logic, then get again the "
+ "reasonable performance by special-casing the exact type "
+ "'long'. And all for 2.7.13 only. Let's give up.")
+
class SubLong2(long):
def __str__(self):
return extra_stuff + 'Xx'
More information about the pypy-commit
mailing list