[pypy-commit] pypy optimizeopt-cleanup: hg merge default

rlamy pypy.commits at gmail.com
Sat Apr 27 11:25:00 EDT 2019


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: optimizeopt-cleanup
Changeset: r96544:5ae00718c328
Date: 2019-04-27 16:23 +0100
http://bitbucket.org/pypy/pypy/changeset/5ae00718c328/

Log:	hg merge default

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -10,10 +10,6 @@
 32f35069a16d819b58c1b6efb17c44e3e53397b2 release-2.3.1
 10f1b29a2bd21f837090286174a9ca030b8680b2 release-2.5.0
 9c4588d731b7fe0b08669bd732c2b676cb0a8233 release-2.5.1
-fcdb941565156385cbac04cfb891f8f4c7a92ef6 release-2.6.0
-fcdb941565156385cbac04cfb891f8f4c7a92ef6 release-2.6.0
-e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0
-e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0
 295ee98b69288471b0fcf2e0ede82ce5209eb90b release-2.6.0
 f3ad1e1e1d6215e20d34bb65ab85ff9188c9f559 release-2.6.1
 850edf14b2c75573720f59e95767335fb1affe55 release-4.0.0
@@ -24,17 +20,10 @@
 b0a649e90b6642251fb4a765fe5b27a97b1319a9 release-5.1.1
 80ef432a32d9baa4b3c5a54c215e8ebe499f6374 release-5.1.2
 40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
-40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
 c09c19272c990a0611b17569a0085ad1ab00c8ff release-pypy2.7-v5.3
 7e8df3df96417c16c2d55b41352ec82c9c69c978 release-pypy2.7-v5.3.1
-68bb3510d8212ae9efb687e12e58c09d29e74f87 release-pypy2.7-v5.4.0
-68bb3510d8212ae9efb687e12e58c09d29e74f87 release-pypy2.7-v5.4.0
 77392ad263504df011ccfcabf6a62e21d04086d0 release-pypy2.7-v5.4.0
-050d84dd78997f021acf0e133934275d63547cc0 release-pypy2.7-v5.4.1
-050d84dd78997f021acf0e133934275d63547cc0 release-pypy2.7-v5.4.1
 0e2d9a73f5a1818d0245d75daccdbe21b2d5c3ef release-pypy2.7-v5.4.1
-4909c06daf41ce88f87dc01c57959cadad4df4a8 RevDB-pypy2.7-v5.4.1
-4909c06daf41ce88f87dc01c57959cadad4df4a8 RevDB-pypy2.7-v5.4.1
 d7724c0a5700b895a47de44074cdf5fd659a988f RevDB-pypy2.7-v5.4.1
 aff251e543859ce4508159dd9f1a82a2f553de00 release-pypy2.7-v5.6.0
 e90317857d27917bf840caf675832292ee070510 RevDB-pypy2.7-v5.6.1
@@ -45,33 +34,20 @@
 2875f328eae2216a87f3d6f335092832eb031f56 release-pypy3.5-v5.7.1
 c925e73810367cd960a32592dd7f728f436c125c release-pypy2.7-v5.8.0
 a37ecfe5f142bc971a86d17305cc5d1d70abec64 release-pypy3.5-v5.8.0
-03d614975835870da65ff0481e1edad68ebbcb8d release-pypy2.7-v5.9.0
 d72f9800a42b46a8056951b1da2426d2c2d8d502 release-pypy3.5-v5.9.0
-03d614975835870da65ff0481e1edad68ebbcb8d release-pypy2.7-v5.9.0
 84a2f3e6a7f88f2fe698e473998755b3bd1a12e2 release-pypy2.7-v5.9.0
 0e7ea4fe15e82d5124e805e2e4a37cae1a402d4b release-pypy2.7-v5.10.0
-a91df6163fb76df245091f741dbf6a23ddc72374 release-pypy3.5-v5.10.0
-a91df6163fb76df245091f741dbf6a23ddc72374 release-pypy3.5-v5.10.0
-0000000000000000000000000000000000000000 release-pypy3.5-v5.10.0
-0000000000000000000000000000000000000000 release-pypy3.5-v5.10.0
 09f9160b643e3f02ccb8c843b2fbb4e5cbf54082 release-pypy3.5-v5.10.0
 3f6eaa010fce78cc7973bdc1dfdb95970f08fed2 release-pypy3.5-v5.10.1
 ab0b9caf307db6592905a80b8faffd69b39005b8 release-pypy2.7-v6.0.0
 fdd60ed87e941677e8ea11acf9f1819466521bf2 release-pypy3.5-v6.0.0
 9112c8071614108b1042bfef0713915107004d62 release-pypy2.7-v7.0.0
 1f86f25937b6ae6c8b25236c35228fac587678bf release-pypy3.5-v7.0.0
-dab365a465140aa79a5f3ba4db784c4af4d5c195 release-pypy3.6-v7.0.0
-9112c8071614108b1042bfef0713915107004d62 release-pypy2.7-v7.0.0
 c8805ee6d7846ca2722b106eeaa2f128c699aba3 release-pypy2.7-v7.0.0
-1f86f25937b6ae6c8b25236c35228fac587678bf release-pypy3.5-v7.0.0
 928a4f70d3de7d17449456946154c5da6e600162 release-pypy3.5-v7.0.0
-dab365a465140aa79a5f3ba4db784c4af4d5c195 release-pypy3.6-v7.0.0
 fb40f7a5524c77b80e6c468e087d621610137261 release-pypy3.6-v7.0.0
 990cef41fe11e5d46b019a46aa956ff46ea1a234 release-pypy2.7-v7.1.0
-bb0d05b190b9c579f0c889a368636e14f6205bab release-pypy3.6-v7.1.0
-bb0d05b190b9c579f0c889a368636e14f6205bab release-pypy3.6-v7.1.0
-6fd188f8f903b7555920adf7d5e7fe21db1bd593 release-pypy3.6-v7.1.0
-6fd188f8f903b7555920adf7d5e7fe21db1bd593 release-pypy3.6-v7.1.0
-7a2e437acfceafe2665b23b1394dc6c66add3b89 release-pypy3.6-v7.1.0
-7a2e437acfceafe2665b23b1394dc6c66add3b89 release-pypy3.6-v7.1.0
 de061d87e39c7df4e436974096d7982c676a859d release-pypy3.6-v7.1.0
+784b254d669919c872a505b807db8462b6140973 release-pypy3.6-v7.1.1
+8cdda8b8cdb8ff29d9e620cccd6c5edd2f2a23ec release-pypy2.7-v7.1.1
+
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -110,6 +110,7 @@
   Devin Jeanpierre
   Bob Ippolito
   Bruno Gola
+  Andrew Lawrence
   David Malcolm
   Squeaky
   Edd Barrett
@@ -125,7 +126,6 @@
   John Witulski
   Stefan Beyer
   Jeremy Thurgood
-  Andrew Lawrence
   Greg Price
   Ivan Sichmann Freitas
   Dario Bertini
@@ -254,6 +254,7 @@
   Omer Katz
   Jacek Generowicz
   Tomasz Dziopa
+  Lin Cheng
   Sylvain Thenault
   Jakub Stasiak
   Andrew Dalke
@@ -403,6 +404,7 @@
   Niclas Olofsson
   Chris Pressey
   Tobias Diaz
+  Paul Graydon
   Nikolaos-Digenis Karagiannis
   Kurt Griffiths
   Ben Mather
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -290,7 +290,11 @@
         else:
             bo = byteorder[sys.byteorder]
         flds = []
+        cum_size = 0
         for name, obj in typ._fields_:
+            padding = typ._ffistruct_.fieldoffset(name) - cum_size
+            if padding:
+                flds.append('%dx' % padding)
             # Trim off the leading '<' or '>'
             ch = get_format_str(obj)[1:]
             if (ch) == 'B':
@@ -301,6 +305,7 @@
             flds.append(':')
             flds.append(name)
             flds.append(':')
+            cum_size += typ._ffistruct_.fieldsize(name)
         return 'T{' + ''.join(flds) + '}'
     elif hasattr(typ, '_type_'):
         ch = typ._type_
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.12.2
+Version: 1.12.3
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -5,8 +5,8 @@
 from .error import CDefError, FFIError, VerificationError, VerificationMissing
 from .error import PkgConfigError
 
-__version__ = "1.12.2"
-__version_info__ = (1, 12, 2)
+__version__ = "1.12.3"
+__version_info__ = (1, 12, 3)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -223,7 +223,7 @@
 
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.12.2"
+                               "\ncompiled with cffi version: 1.12.3"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -77,6 +77,7 @@
   Devin Jeanpierre
   Bob Ippolito
   Bruno Gola
+  Andrew Lawrence
   David Malcolm
   Squeaky
   Edd Barrett
@@ -92,7 +93,6 @@
   John Witulski
   Stefan Beyer
   Jeremy Thurgood
-  Andrew Lawrence
   Greg Price
   Ivan Sichmann Freitas
   Dario Bertini
@@ -221,6 +221,7 @@
   Omer Katz
   Jacek Generowicz
   Tomasz Dziopa
+  Lin Cheng
   Sylvain Thenault
   Jakub Stasiak
   Andrew Dalke
@@ -370,6 +371,7 @@
   Niclas Olofsson
   Chris Pressey
   Tobias Diaz
+  Paul Graydon
   Nikolaos-Digenis Karagiannis
   Kurt Griffiths
   Ben Mather
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
@@ -88,7 +88,9 @@
 There are a few extra implications from the difference in the GC.  Most
 notably, if an object has a ``__del__``, the ``__del__`` is never called more
 than once in PyPy; but CPython will call the same ``__del__`` several times
-if the object is resurrected and dies again.  The ``__del__`` methods are
+if the object is resurrected and dies again (at least it is reliably so in
+older CPythons; newer CPythons try to call destructors not more than once,
+but there are counter-examples).  The ``__del__`` methods are
 called in "the right" order if they are on objects pointing to each
 other, as in CPython, but unlike CPython, if there is a dead cycle of
 objects referencing each other, their ``__del__`` methods are called anyway;
diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
 
 .. toctree::
 
+   release-v7.1.1.rst
    release-v7.1.0.rst
    release-v7.0.0.rst
    release-v6.0.0.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
 .. toctree::
 
    whatsnew-head.rst
+   whatsnew-pypy2-7.1.0.rst
    whatsnew-pypy2-7.0.0.rst
    whatsnew-pypy2-6.0.0.rst
    whatsnew-pypy2-5.10.0.rst
diff --git a/pypy/doc/release-v7.1.1.rst b/pypy/doc/release-v7.1.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v7.1.1.rst
@@ -0,0 +1,105 @@
+=========================================
+PyPy v7.1.1: release of 2.7, and 3.6-beta
+=========================================
+
+The PyPy team is proud to release a bug-fix release version 7.1.1 of PyPy, which
+includes two different interpreters:
+
+  - PyPy2.7, which is an interpreter supporting the syntax and the features of
+    Python 2.7
+
+  - PyPy3.6-beta: this is the second official release of PyPy to support 3.6
+    features, although it is still considered beta quality.
+    
+The interpreters are based on much the same codebase, thus the double
+release.
+
+As always, this release is 100% compatible with the previous one and fixed
+several issues and bugs raised by the growing community of PyPy users.
+We strongly recommend updating.
+
+The PyPy3.6 release is still not production quality so your mileage may vary.
+There are open issues with incomplete compatibility and c-extension support.
+
+You can download the v7.1.1 releases here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project. If PyPy is not quite good enough for your needs, we are available for
+direct consulting work.
+
+We would also like to thank our contributors and encourage new people to join
+the project. PyPy has many layers and we need help with all of them: `PyPy`_
+and `RPython`_ documentation improvements, tweaking popular modules to run
+on pypy, or general `help`_ with making RPython's JIT even better.
+
+.. _`PyPy`: index.html
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`help`: project-ideas.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7, 3.6. It's fast (`PyPy and CPython 2.7.x`_ performance
+comparison) due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+This PyPy release supports:
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+Unfortunately at the moment of writing our ARM buildbots are out of service,
+so for now we are **not** releasing any binary for the ARM architecture,
+although PyPy does support ARM 32 bit processors.
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
+
+
+Changelog
+=========
+
+Changes shared across versions:
+
+* Improve performance of ``u''.append``
+
+* Prevent a crash in ``zlib`` when flushing a closed stream
+
+* Fix a few corner cases when encountering unicode values above 0x110000
+
+* Teach the JIT how to handle very large constant lists, sets, or dicts
+* Fix building on ARM32 (issue 2984_)
+* Fix a bug in register assignment in ARM32
+* Package windows DLLs needed by cffi modules next to the cffi c-extensions
+  (issue 2988_)
+* Cleanup and refactor JIT code to remove ``rpython.jit.metainterp.typesystem``
+* Fix memoryviews of ctype structures with padding, (cpython issue 32780_)
+* CFFI updated to as-yet-unreleased 1.12.3
+
+Python 3.6 only:
+
+* Override some ``errno.E*`` values that were added to MSVC in v2010
+  so that ``errno.E* == errno.WSAE*`` as in CPython
+* Do the same optimization that CPython does for ``(1, 2, 3, *a)`` (but at the
+  AST level)
+* ``str.maketrans`` was broken (issue 2991_)
+* Raise a ``TypeError`` when using buffers and unicode such as ``''.strip(buffer)``
+  and ``'a' < buffer``
+* Support ``_overlapped`` and asyncio on win32
+* Fix an issue where ``''.join(list_of_strings)`` would rarely confuse utf8 and
+  bytes (issue 2997_)
+
+.. _2984: https://bitbucket.org/pypy/pypy/issues/2984
+.. _2991: https://bitbucket.org/pypy/pypy/issues/2991
+.. _2988: https://bitbucket.org/pypy/pypy/issues/2988
+.. _2997: https://bitbucket.org/pypy/pypy/issues/2997
+.. _32780: https://bugs.python.org/issue32780
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -12,3 +12,7 @@
 .. branch: jit-cleanup
 
 Remove rpython.jit.metainterp.typesystem and clean up related code in rpython/jit/
+
+.. branch: datetime_api_27
+
+Add ``DateTime_FromTimestamp`` and ``Date_FromTimestamp``
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.12.2"
+VERSION = "1.12.3"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.12.2", ("This test_c.py file is for testing a version"
+assert __version__ == "1.12.3", ("This test_c.py file is for testing a version"
                                  " of cffi that differs from the one that we"
                                  " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -74,8 +74,8 @@
     lgt = min(arr1.len, arr2.len)
     for i in range(lgt):
         arr_eq_driver.jit_merge_point(comp_func=comp_op)
-        w_elem1 = arr1.w_getitem(space, i)
-        w_elem2 = arr2.w_getitem(space, i)
+        w_elem1 = arr1.w_getitem(space, i, integer_instead_of_char=True)
+        w_elem2 = arr2.w_getitem(space, i, integer_instead_of_char=True)
         if comp_op == EQ:
             res = space.eq_w(w_elem1, w_elem2)
             if not res:
@@ -1036,10 +1036,11 @@
             else:
                 self.fromsequence(w_iterable)
 
-        def w_getitem(self, space, idx):
+        def w_getitem(self, space, idx, integer_instead_of_char=False):
             item = self.get_buffer()[idx]
             keepalive_until_here(self)
-            if mytype.typecode in 'bBhHil':
+            if mytype.typecode in 'bBhHil' or (
+                    integer_instead_of_char and mytype.typecode in 'cu'):
                 item = rffi.cast(lltype.Signed, item)
                 return space.newint(item)
             if mytype.typecode in 'IL':
@@ -1053,21 +1054,17 @@
                 code = r_uint(ord(item))
                 # cpython will allow values > sys.maxunicode
                 # while silently truncating the top bits
-                if code <= r_uint(0x7F):
-                    # Encode ASCII
-                    item = chr(code)
-                elif code <= r_uint(0x07FF):
-                    item = (chr((0xc0 | (code >> 6))) + 
-                            chr((0x80 | (code & 0x3f))))
-                elif code <= r_uint(0xFFFF):
-                    item = (chr((0xe0 | (code >> 12))) +
-                            chr((0x80 | ((code >> 6) & 0x3f))) +
-                            chr((0x80 | (code & 0x3f))))
-                else:
-                    item = (chr((0xf0 | (code >> 18)) & 0xff) +
-                            chr((0x80 | ((code >> 12) & 0x3f))) +
-                            chr((0x80 | ((code >> 6) & 0x3f))) +
-                            chr((0x80 | (code & 0x3f))))
+                # For now I (arigo) am going to ignore that and
+                # raise a ValueError always here, instead of getting
+                # some invalid utf8-encoded string which makes things
+                # potentially explode left and right.
+                try:
+                    item = rutf8.unichr_as_utf8(code)
+                except rutf8.OutOfRange:
+                    raise oefmt(space.w_ValueError,
+                        "cannot operate on this array('u') because it contains"
+                        " character %s not in range [U+0000; U+10ffff]"
+                        " at index %d", 'U+%x' % code, idx)
                 return space.newutf8(item, 1)
             assert 0, "unreachable"
 
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -846,12 +846,25 @@
         assert repr(mya('i', [1, 2, 3])) == "array('i', [1, 2, 3])"
         assert repr(mya('i', (1, 2, 3))) == "array('i', [1, 2, 3])"
 
+    def test_array_of_chars_equality(self):
+        input_bytes = '\x01\x63a\x00!'
+        a = self.array('c', input_bytes)
+        b = self.array('c', input_bytes)
+        b.byteswap()
+        assert a == b
+
     def test_unicode_outofrange(self):
         input_unicode = u'\x01\u263a\x00\ufeff'
         a = self.array('u', input_unicode)
         b = self.array('u', input_unicode)
         b.byteswap()
+        assert b[2] == u'\u0000'
         assert a != b
+        e = raises(ValueError, "b[0]")        # doesn't work
+        assert str(e.value) == (
+            "cannot operate on this array('u') because it contains"
+            " character U+1000000 not in range [U+0000; U+10ffff]"
+            " at index 0")
         assert str(a) == "array('u', %r)" % (input_unicode,)
         assert str(b) == ("array('u', <character U+1000000 is not in"
                           " range [U+0000; U+10ffff]>)")
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -67,6 +67,14 @@
         _PyDelta_FromDelta.api_func.functype,
         _PyDelta_FromDelta.api_func.get_wrapper(space))
 
+    datetimeAPI.c_DateTime_FromTimestamp = llhelper(
+        _PyDateTime_FromTimestamp.api_func.functype,
+        _PyDateTime_FromTimestamp.api_func.get_wrapper(space))
+
+    datetimeAPI.c_Date_FromTimestamp = llhelper(
+        _PyDate_FromTimestamp.api_func.functype,
+        _PyDate_FromTimestamp.api_func.get_wrapper(space))
+
     state.datetimeAPI.append(datetimeAPI)
     return state.datetimeAPI[0]
 
@@ -243,8 +251,16 @@
     """
     w_datetime = PyImport_Import(space, space.newtext("datetime"))
     w_type = space.getattr(w_datetime, space.newtext("datetime"))
+    return _PyDateTime_FromTimestamp(space, w_type, w_args, None)
+
+ at cpython_api([PyObject, PyObject, PyObject], PyObject)
+def _PyDateTime_FromTimestamp(space, w_type, w_args, w_kwds):
+    """Implementation of datetime.fromtimestamp that matches the signature for
+    PyDateTimeCAPI.DateTime_FromTimestamp
+    """
     w_method = space.getattr(w_type, space.newtext("fromtimestamp"))
-    return space.call(w_method, w_args)
+
+    return space.call(w_method, w_args, w_kwds=w_kwds)
 
 @cpython_api([PyObject], PyObject)
 def PyDate_FromTimestamp(space, w_args):
@@ -253,6 +269,12 @@
     """
     w_datetime = PyImport_Import(space, space.newtext("datetime"))
     w_type = space.getattr(w_datetime, space.newtext("date"))
+    return _PyDate_FromTimestamp(space, w_type, w_args)
+
+ at cpython_api([PyObject, PyObject], PyObject)
+def _PyDate_FromTimestamp(space, w_type, w_args):
+    """Implementation of date.fromtimestamp that matches the signature for
+    PyDateTimeCAPI.Date_FromTimestamp"""
     w_method = space.getattr(w_type, space.newtext("fromtimestamp"))
     return space.call(w_method, w_args)
 
diff --git a/pypy/module/cpyext/parse/cpyext_datetime.h b/pypy/module/cpyext/parse/cpyext_datetime.h
--- a/pypy/module/cpyext/parse/cpyext_datetime.h
+++ b/pypy/module/cpyext/parse/cpyext_datetime.h
@@ -13,6 +13,10 @@
         PyObject*, PyTypeObject*);
     PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*);
     PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*);
+
+    /* constructors for the DB API */
+    PyObject *(*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*);
+    PyObject *(*Date_FromTimestamp)(PyObject*, PyObject*);
 } PyDateTime_CAPI;
 
 typedef struct
diff --git a/pypy/module/cpyext/test/test_datetime.py b/pypy/module/cpyext/test/test_datetime.py
--- a/pypy/module/cpyext/test/test_datetime.py
+++ b/pypy/module/cpyext/test/test_datetime.py
@@ -146,6 +146,41 @@
                     2000, 6, 6, 6, 6, 6, 6, Py_None,
                     PyDateTimeAPI->DateTimeType);
              """),
+            ("new_datetime_fromtimestamp", "METH_NOARGS",
+             """ PyDateTime_IMPORT;
+                 PyObject *ts = PyFloat_FromDouble(200000.0);
+                 Py_INCREF(Py_None);
+                 PyObject *tsargs = PyTuple_Pack(2, ts, Py_None);
+                 PyObject *rv = PyDateTimeAPI->DateTime_FromTimestamp(
+                    (PyObject *)PyDateTimeAPI->DateTimeType, tsargs, NULL);
+                 Py_DECREF(tsargs);
+                 return rv;
+             """),
+            ("new_dt_fromts_tzinfo", "METH_O",
+             """ PyDateTime_IMPORT;
+                 PyObject *ts = PyFloat_FromDouble(200000.0);
+                 PyObject *tsargs = PyTuple_Pack(1, ts);
+                 PyObject *tskwargs = PyDict_New();
+
+                 Py_INCREF(args);
+                 PyDict_SetItemString(tskwargs, "tz", args);
+                 PyObject *rv = PyDateTimeAPI->DateTime_FromTimestamp(
+                    (PyObject *)PyDateTimeAPI->DateTimeType, tsargs, tskwargs);
+                 Py_DECREF(tsargs);
+                 Py_DECREF(tskwargs);
+                 return rv;
+             """),
+            ("new_date_fromtimestamp", "METH_NOARGS",
+             """ PyDateTime_IMPORT;
+                 PyObject *ts = PyFloat_FromDouble(1430366400.0);
+                 Py_INCREF(Py_None);
+                 PyObject *tsargs = PyTuple_Pack(1, ts);
+                 PyObject *rv = PyDateTimeAPI->Date_FromTimestamp(
+                    (PyObject *)PyDateTimeAPI->DateType, tsargs);
+                 Py_DECREF(tsargs);
+                 return rv;
+             """),
+
         ], prologue='#include "datetime.h"\n')
         import datetime
         assert module.new_date() == datetime.date(2000, 6, 6)
@@ -153,6 +188,28 @@
         assert module.new_datetime() == datetime.datetime(
             2000, 6, 6, 6, 6, 6, 6)
 
+        class UTC(datetime.tzinfo):
+            def utcoffset(self, dt):
+                return datetime.timedelta(hours=0)
+
+            def dst(self, dt):
+                return datetime.timedelta(0)
+
+            def tzname(self, dt):
+                return "UTC"
+
+        utc = UTC()
+
+        # .fromtimestamp tests
+        assert (module.new_datetime_fromtimestamp() ==
+                datetime.datetime.fromtimestamp(200000.0))
+
+        assert (module.new_dt_fromts_tzinfo(utc) ==
+                datetime.datetime.fromtimestamp(200000.0, tz=utc))
+
+        assert (module.new_date_fromtimestamp() ==
+                datetime.date.fromtimestamp(1430366400.0))
+
     def test_macros(self):
         module = self.import_extension('foo', [
             ("test_date_macros", "METH_NOARGS",
@@ -305,16 +362,18 @@
              """),
         ], prologue='#include "datetime.h"\n')
         from datetime import tzinfo, datetime, timedelta, time
+
         # copied from datetime documentation
         class GMT1(tzinfo):
             def __del__(self):
-                print 'deleting GMT1'
+                print('deleting GMT1')
             def utcoffset(self, dt):
                 return timedelta(hours=1) + self.dst(dt)
             def dst(self, dt):
                 return timedelta(0)
             def tzname(self,dt):
                 return "GMT +1"
+
         gmt1 = GMT1()
         dt1 = module.time_with_tzinfo(gmt1)
         assert dt1 == time(6, 6, 6, 6, gmt1)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -43,9 +43,9 @@
             guard_no_exception(descr=...)
             i100 = int_lt(i98, 0)
             guard_true(i100, descr=...)
-            i102 = call_i(ConstClass(_ll_4_str_eq_slice_char__rpy_stringPtr_Signed_Signed_Char), p55, i83, 1, i89, descr=<Calli . riii EF=0 OS=27>)
+            i102 = call_i(ConstClass(_ll_4_str_eq_slice_char__rpy_stringPtr_Signed_Signed_Char), p13, i83, 1, i89, descr=<Calli . riii EF=0 OS=27>)
             guard_true(i102, descr=...)
-            i104 = int_add(i74, 1)
+            i104 = int_add(i6, 1)
             --TICK--
             jump(..., descr=...)
         """ % (-sys.maxint-1,))
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -352,8 +352,7 @@
                 raise oefmt(space.w_ValueError,
                             "length must be greater than zero")
         if not self.stream:
-            raise zlib_error(space,
-                             "compressor object already flushed")
+            return space.newbytes('')
         data = self.unconsumed_tail
         try:
             self.lock()
diff --git a/pypy/module/zlib/test/test_zlib.py b/pypy/module/zlib/test/test_zlib.py
--- a/pypy/module/zlib/test/test_zlib.py
+++ b/pypy/module/zlib/test/test_zlib.py
@@ -363,4 +363,5 @@
         dco = zlib.decompressobj()
         dco.decompress(x)
         dco.flush()
-        raises(self.zlib.error, dco.flush)
+        # multiple flush calls should not raise
+        dco.flush()
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -711,6 +711,7 @@
 
         raises(TypeError, u'hello'.translate)
         raises(TypeError, u'abababc'.translate, {ord('a'):''})
+        raises(TypeError, u'x'.translate, {ord('x'):0x110000})
 
     def test_unicode_from_encoded_object(self):
         assert unicode('x', 'utf-8') == u'x'
@@ -1278,4 +1279,4 @@
         assert str(e.value) == 'decoding Unicode is not supported'
 
     def test_newlist_utf8_non_ascii(self):
-        'ä'.split("\n")[0] # does not crash
\ No newline at end of file
+        'ä'.split("\n")[0] # does not crash
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -42,13 +42,10 @@
         self._length = length
         self._index_storage = rutf8.null_storage()
         if not we_are_translated():
-            try:
-                # best effort, too expensive to handle surrogates
-                ulength = rutf8.codepoints_in_utf(utf8str)
-            except:
-                ulength = length 
-            assert ulength == length
-
+            # utf8str must always be a valid utf8 string, except maybe with
+            # explicit surrogate characters---which .decode('utf-8') doesn't
+            # special-case in Python 2, which is exactly what we want here
+            assert length == len(utf8str.decode('utf-8'))
 
 
     @staticmethod
@@ -385,7 +382,7 @@
                                 "or unicode")
             try:
                 builder.append_code(codepoint)
-            except ValueError:
+            except rutf8.OutOfRange:
                 raise oefmt(space.w_TypeError,
                             "character mapping must be in range(0x110000)")
         return self.from_utf8builder(builder)
diff --git a/pypy/tool/release/force-builds.py b/pypy/tool/release/force-builds.py
--- a/pypy/tool/release/force-builds.py
+++ b/pypy/tool/release/force-builds.py
@@ -8,8 +8,13 @@
 
 modified by PyPy team
 """
+from __future__ import absolute_import, division, print_function
 
-import os, sys, urllib, subprocess
+import os, sys, subprocess
+try:
+    from urllib2 import quote
+except ImportError:
+    from urllib.request import quote
 
 from twisted.internet import reactor, defer
 from twisted.python import log
@@ -29,10 +34,10 @@
     'pypy-c-jit-macosx-x86-64',
     'pypy-c-jit-win-x86-32',
     'pypy-c-jit-linux-s390x',
-    'build-pypy-c-jit-linux-armhf-raspbian',
-    'build-pypy-c-jit-linux-armel',
+#    'build-pypy-c-jit-linux-armhf-raspbian',
+#    'build-pypy-c-jit-linux-armel',
     'rpython-linux-x86-32',
-    'rpython-linux-x86-64'
+    'rpython-linux-x86-64',
     'rpython-win-x86-32'
 ]
 
@@ -54,7 +59,7 @@
         log.err(err, "Build force failure")
 
     for builder in BUILDERS:
-        print 'Forcing', builder, '...'
+        print('Forcing', builder, '...')
         url = "http://" + server + "/builders/" + builder + "/force"
         args = [
             ('username', user),
@@ -63,15 +68,15 @@
             ('submit', 'Force Build'),
             ('branch', branch),
             ('comments', "Forced by command line script")]
-        url = url + '?' + '&'.join([k + '=' + urllib.quote(v) for (k, v) in args])
+        url = url + '?' + '&'.join([k + '=' + quote(v) for (k, v) in args])
         requests.append(
-            lock.run(client.getPage, url, followRedirect=False).addErrback(ebList))
+            lock.run(client.getPage, url.encode('utf-8'), followRedirect=False).addErrback(ebList))
 
     d = defer.gatherResults(requests)
     d.addErrback(log.err)
     d.addCallback(lambda ign: reactor.stop())
     reactor.run()
-    print 'See http://buildbot.pypy.org/summary after a while'
+    print('See http://buildbot.pypy.org/summary after a while')
 
 if __name__ == '__main__':
     log.startLogging(sys.stdout)
@@ -86,6 +91,6 @@
     try:
         subprocess.check_call(['hg','id','-r', options.branch])
     except subprocess.CalledProcessError:
-        print 'branch',  options.branch, 'could not be found in local repository'
+        print('branch',  options.branch, 'could not be found in local repository')
         sys.exit(-1) 
     main(options.branch, options.server, user=options.user)
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -109,9 +109,6 @@
             wchar_t const* file,
             unsigned int line,
             uintptr_t pReserved) {
-                wprintf(L"Invalid parameter detected in function %s."
-                            L" File: %s Line: %d\\n", function, file, line);
-                wprintf(L"Expression: %s\\n", expression);
         }
 
         RPY_EXTERN void* enter_suppress_iph(void)
@@ -1265,16 +1262,16 @@
 @replace_os_function('rename')
 @specialize.argtype(0, 1)
 def rename(path1, path2):
-    if not _WIN32:
-        handle_posix_error('rename',
-                           c_rename(_as_bytes0(path1), _as_bytes0(path2)))
-    else:
+    if _WIN32:
         traits = _preferred_traits2(path1, path2)
         win32traits = make_win32_traits(traits)
         path1 = traits.as_str0(path1)
         path2 = traits.as_str0(path2)
         if not win32traits.MoveFileEx(path1, path2, 0):
             raise rwin32.lastSavedWindowsError()
+    else:
+        handle_posix_error('rename',
+                           c_rename(_as_bytes0(path1), _as_bytes0(path2)))
 
 @specialize.argtype(0, 1)
 def replace(path1, path2):


More information about the pypy-commit mailing list