[pypy-commit] pypy py3k: Merge with upstream

mgedmin noreply at buildbot.pypy.org
Tue Jun 9 19:01:42 CEST 2015


Author: Marius Gedminas <marius at gedmin.as>
Branch: py3k
Changeset: r77997:404f7178d54f
Date: 2015-06-09 19:45 +0300
http://bitbucket.org/pypy/pypy/changeset/404f7178d54f/

Log:	Merge with upstream

diff too long, truncating to 2000 out of 61469 lines

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -3,11 +3,15 @@
 d8ac7d23d3ec5f9a0fa1264972f74a010dbfd07f release-1.6
 ff4af8f318821f7f5ca998613a60fca09aa137da release-1.7
 07e08e9c885ca67d89bcc304e45a32346daea2fa release-2.0-beta-1
-9b623bc48b5950cf07184462a0e48f2c4df0d720 pypy-2.1-beta1-arm
-9b623bc48b5950cf07184462a0e48f2c4df0d720 pypy-2.1-beta1-arm
 ab0dd631c22015ed88e583d9fdd4c43eebf0be21 pypy-2.1-beta1-arm
 20e51c4389ed4469b66bb9d6289ce0ecfc82c4b9 release-2.3.0
 394146e9bb673514c61f0150ab2013ccf78e8de7 release-2.3
 32f35069a16d819b58c1b6efb17c44e3e53397b2 release-2.2=3.1
 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
diff --git a/.tddium.requirements.txt b/.tddium.requirements.txt
deleted file mode 100644
--- a/.tddium.requirements.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-pytest
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -38,8 +38,8 @@
   Armin Rigo
   Maciej Fijalkowski
   Carl Friedrich Bolz
+  Amaury Forgeot d'Arc
   Antonio Cuni
-  Amaury Forgeot d'Arc
   Samuele Pedroni
   Alex Gaynor
   Brian Kearns
@@ -50,9 +50,9 @@
   Holger Krekel
   Christian Tismer
   Hakan Ardo
-  Benjamin Peterson
   Manuel Jacob
   Ronan Lamy
+  Benjamin Peterson
   Anders Chrigstrom
   Eric van Riet Paap
   Wim Lavrijsen
@@ -63,8 +63,8 @@
   Sven Hager
   Anders Lehmann
   Aurelien Campeas
+  Remi Meier
   Niklaus Haldimann
-  Remi Meier
   Camillo Bruni
   Laura Creighton
   Toon Verwaest
@@ -76,10 +76,10 @@
   David Edelsohn
   Anders Hammarquist
   Jakub Gustak
+  Gregor Wegberg
   Guido Wesdorp
   Lawrence Oluyede
   Bartosz Skowron
-  Gregor Wegberg
   Daniel Roberts
   Niko Matsakis
   Adrien Di Mascio
@@ -87,10 +87,11 @@
   Ludovic Aubry
   Jacob Hallen
   Jason Creighton
+  Richard Plangger
   Alex Martelli
   Michal Bendowski
+  stian
   Jan de Mooij
-  stian
   Tyler Wade
   Michael Foord
   Stephan Diehl
@@ -133,15 +134,15 @@
   Georg Brandl
   Bert Freudenberg
   Stian Andreassen
+  Edd Barrett
   Wanja Saatkamp
   Gerald Klix
   Mike Blume
+  Tobias Pape
   Oscar Nierstrasz
   Stefan H. Muller
-  Edd Barrett
   Jeremy Thurgood
   Rami Chowdhury
-  Tobias Pape
   Eugene Oden
   Henry Mason
   Vasily Kuznetsov
@@ -167,11 +168,13 @@
   Michael Twomey
   Lucian Branescu Mihaila
   Yichao Yu
+  Anton Gulenko
   Gabriel Lavoie
   Olivier Dormond
   Jared Grubb
   Karl Bartel
   Wouter van Heyst
+  Sebastian Pawluś
   Brian Dorsey
   Victor Stinner
   Andrews Medina
@@ -188,6 +191,7 @@
   Neil Shepperd
   Stanislaw Halik
   Mikael Schönenberg
+  Berkin Ilbeyi
   Elmo M?ntynen
   Jonathan David Riehl
   Anders Qvist
@@ -211,11 +215,11 @@
   Carl Meyer
   Karl Ramm
   Pieter Zieschang
-  Sebastian Pawluś
   Gabriel
   Lukas Vacek
   Andrew Dalke
   Sylvain Thenault
+  Jakub Stasiak
   Nathan Taylor
   Vladimir Kryachko
   Jacek Generowicz
@@ -242,6 +246,7 @@
   Tomo Cocoa
   Toni Mattis
   Lucas Stadler
+  Julian Berman
   roberto at goyle
   Yury V. Zaytsev
   Anna Katrina Dominguez
@@ -253,6 +258,8 @@
   Ben Darnell
   Roberto De Ioris
   Juan Francisco Cantero Hurtado
+  Ruochen Huang
+  Jeong YunWon
   Godefroid Chappelle
   Joshua Gilbert
   Dan Colish
@@ -271,6 +278,7 @@
   Christian Muirhead
   Berker Peksag
   James Lan
+  Volodymyr Vladymyrov
   shoma hosaka
   Daniel Neuhäuser
   Ben Mather
@@ -316,6 +324,7 @@
   yasirs
   Michael Chermside
   Anna Ravencroft
+  Andrey Churin
   Dan Crosta
   Julien Phalip
   Roman Podoliaka
@@ -420,3 +429,10 @@
 the terms of the GPL license version 2 or any later version.  Thus the
 _gdbm module, provided in the file lib_pypy/_gdbm.py, is redistributed
 under the terms of the GPL license as well.
+
+License for 'pypy/module/_vmprof/src'
+--------------------------------------
+
+The code is based on gperftools. You may see a copy of the License for it at
+
+    https://code.google.com/p/gperftools/source/browse/COPYING
diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -145,6 +145,34 @@
             name = hostname
     return name
 
+class RefCountingWarning(UserWarning):
+    pass
+
+def _do_reuse_or_drop(socket, methname):
+    try:
+        method = getattr(socket, methname)
+    except (AttributeError, TypeError):
+        warnings.warn("""'%s' object has no _reuse/_drop methods
+{{
+    You make use (or a library you are using makes use) of the internal
+    classes '_socketobject' and '_fileobject' in socket.py, initializing
+    them with custom objects.  On PyPy, these custom objects need two
+    extra methods, _reuse() and _drop(), that maintain an explicit
+    reference counter.  When _drop() has been called as many times as
+    _reuse(), then the object should be freed.
+
+    Without these methods, you get the warning here.  This is to
+    prevent the following situation: if your (or the library's) code
+    relies on reference counting for prompt closing, then on PyPy, the
+    __del__ method will be called later than on CPython.  You can
+    easily end up in a situation where you open and close a lot of
+    (high-level) '_socketobject' or '_fileobject', but the (low-level)
+    custom objects will accumulate before their __del__ are called.
+    You quickly risk running out of file descriptors, for example.
+}}""" % (socket.__class__.__name__,), RefCountingWarning, stacklevel=3)
+    else:
+        method()
+
 
 _socketmethods = (
     'bind', 'connect', 'connect_ex', 'fileno', 'listen',
@@ -182,19 +210,7 @@
         if _sock is None:
             _sock = _realsocket(family, type, proto)
         else:
-            # PyPy note about refcounting: implemented with _reuse()/_drop()
-            # on the class '_socket.socket'.  Python 3 did it differently
-            # with a reference counter on this class 'socket._socketobject'
-            # instead, but it is a less compatible change.
-            
-            # Note that a few libraries (like eventlet) poke at the
-            # private implementation of socket.py, passing custom
-            # objects to _socketobject().  These libraries need the
-            # following fix for use on PyPy: the custom objects need
-            # methods _reuse() and _drop() that maintains an explicit
-            # reference counter, starting at 0.  When it drops back to
-            # zero, close() must be called.
-            _sock._reuse()
+            _do_reuse_or_drop(_sock, '_reuse')
 
         self._sock = _sock
 
@@ -228,13 +244,13 @@
     def close(self):
         s = self._sock
         self._sock = _closedsocket()
-        s._drop()
+        _do_reuse_or_drop(s, '_drop')
     close.__doc__ = _realsocket.close.__doc__
 
     def accept(self):
         sock, addr = self._sock.accept()
         sockobj = _socketobject(_sock=sock)
-        sock._drop()    # already a copy in the _socketobject()
+        _do_reuse_or_drop(sock, '_drop') # already a copy in the _socketobject()
         return sockobj, addr
     accept.__doc__ = _realsocket.accept.__doc__
 
@@ -290,14 +306,7 @@
                  "_close"]
 
     def __init__(self, sock, mode='rb', bufsize=-1, close=False):
-        # Note that a few libraries (like eventlet) poke at the
-        # private implementation of socket.py, passing custom
-        # objects to _fileobject().  These libraries need the
-        # following fix for use on PyPy: the custom objects need
-        # methods _reuse() and _drop() that maintains an explicit
-        # reference counter, starting at 0.  When it drops back to
-        # zero, close() must be called.
-        sock._reuse()
+        _do_reuse_or_drop(sock, '_reuse')
         self._sock = sock
         self.mode = mode # Not actually used in this version
         if bufsize < 0:
@@ -338,7 +347,7 @@
                 if self._close:
                     s.close()
                 else:
-                    s._drop()
+                    _do_reuse_or_drop(s, '_drop')
 
     def __del__(self):
         try:
diff --git a/lib-python/2.7/test/test_urllib2net.py b/lib-python/2.7/test/test_urllib2net.py
--- a/lib-python/2.7/test/test_urllib2net.py
+++ b/lib-python/2.7/test/test_urllib2net.py
@@ -102,11 +102,8 @@
 
     def test_ftp(self):
         urls = [
-            'ftp://ftp.kernel.org/pub/linux/kernel/README',
-            'ftp://ftp.kernel.org/pub/linux/kernel/non-existent-file',
-            #'ftp://ftp.kernel.org/pub/leenox/kernel/test',
-            'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
-                '/research-reports/00README-Legal-Rules-Regs',
+            'ftp://ftp.debian.org/debian/README',
+            'ftp://ftp.debian.org/debian/non-existent-file',
             ]
         self._test_urls(urls, self._extra_handlers())
 
@@ -255,6 +252,7 @@
         with test_support.transient_internet(url, timeout=None):
             u = _urlopen_with_retry(url)
             self.assertIsNone(u.fp._sock.fp._sock.gettimeout())
+            u.close()
 
     def test_http_default_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout())
@@ -266,6 +264,7 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 60)
+            u.close()
 
     def test_http_no_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout())
@@ -277,20 +276,23 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertIsNone(u.fp._sock.fp._sock.gettimeout())
+            u.close()
 
     def test_http_timeout(self):
         url = "http://www.example.com"
         with test_support.transient_internet(url):
             u = _urlopen_with_retry(url, timeout=120)
             self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120)
+            u.close()
 
-    FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/"
+    FTP_HOST = 'ftp://ftp.debian.org/debian/'
 
     def test_ftp_basic(self):
         self.assertIsNone(socket.getdefaulttimeout())
         with test_support.transient_internet(self.FTP_HOST, timeout=None):
             u = _urlopen_with_retry(self.FTP_HOST)
             self.assertIsNone(u.fp.fp._sock.gettimeout())
+            u.close()
 
     def test_ftp_default_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout())
@@ -301,6 +303,7 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
+            u.close()
 
     def test_ftp_no_timeout(self):
         self.assertIsNone(socket.getdefaulttimeout(),)
@@ -311,11 +314,16 @@
             finally:
                 socket.setdefaulttimeout(None)
             self.assertIsNone(u.fp.fp._sock.gettimeout())
+            u.close()
 
     def test_ftp_timeout(self):
         with test_support.transient_internet(self.FTP_HOST):
-            u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
+            try:
+                u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
+            except:
+                raise
             self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
+            u.close()
 
 
 def test_main():
diff --git a/lib-python/3/test/test_curses.py b/lib-python/3/test/test_curses.py
--- a/lib-python/3/test/test_curses.py
+++ b/lib-python/3/test/test_curses.py
@@ -115,8 +115,8 @@
     stdscr.notimeout(1)
     win2.overlay(win)
     win2.overwrite(win)
-    win2.overlay(win, 1, 2, 3, 3, 2, 1)
-    win2.overwrite(win, 1, 2, 3, 3, 2, 1)
+    win2.overlay(win, 1, 2, 2, 1, 3, 3)
+    win2.overwrite(win, 1, 2, 2, 1, 3, 3)
     stdscr.redrawln(1,2)
 
     stdscr.scrollok(1)
diff --git a/lib-python/3/trace.py b/lib-python/3/trace.py
--- a/lib-python/3/trace.py
+++ b/lib-python/3/trace.py
@@ -245,7 +245,12 @@
         we want to have reported.
         """
         return (filename == "<string>" or
-                filename.startswith("<doctest "))
+                filename.startswith("<doctest ") or
+                # XXX PyPy freezes some (pure-Python) modules at
+                # translation-time.  These contain filenames starting with
+                # "<builtin>/" instead of their actual filenames.  Ignore them
+                # for now.
+                filename.startswith("<builtin>/"))
 
     def update(self, other):
         """Merge in the data from another CoverageResults"""
diff --git a/lib_pypy/_audioop_build.py b/lib_pypy/_audioop_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_audioop_build.py
@@ -0,0 +1,621 @@
+from cffi import FFI
+
+ffi = FFI()
+ffi.cdef("""
+typedef short PyInt16;
+
+int ratecv(char* rv, char* cp, size_t len, int size,
+           int nchannels, int inrate, int outrate,
+           int* state_d, int* prev_i, int* cur_i,
+           int weightA, int weightB);
+
+void tostereo(char* rv, char* cp, size_t len, int size,
+              double fac1, double fac2);
+void add(char* rv, char* cp1, char* cp2, size_t len1, int size);
+
+/* 2's complement (14-bit range) */
+unsigned char
+st_14linear2ulaw(PyInt16 pcm_val);
+PyInt16 st_ulaw2linear16(unsigned char);
+
+/* 2's complement (13-bit range) */
+unsigned char
+st_linear2alaw(PyInt16 pcm_val);
+PyInt16 st_alaw2linear16(unsigned char);
+
+
+void lin2adcpm(unsigned char* rv, unsigned char* cp, size_t len,
+               size_t size, int* state);
+void adcpm2lin(unsigned char* rv, unsigned char* cp, size_t len,
+               size_t size, int* state);
+""")
+
+# This code is directly copied from CPython file: Modules/audioop.c
+_AUDIOOP_C_MODULE = r"""
+typedef short PyInt16;
+typedef int Py_Int32;
+
+/* Code shamelessly stolen from sox, 12.17.7, g711.c
+** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
+
+/* From g711.c:
+ *
+ * December 30, 1994:
+ * Functions linear2alaw, linear2ulaw have been updated to correctly
+ * convert unquantized 16 bit values.
+ * Tables for direct u- to A-law and A- to u-law conversions have been
+ * corrected.
+ * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
+ * bli at cpk.auc.dk
+ *
+ */
+#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+#define SIGN_BIT        (0x80)          /* Sign bit for a A-law byte. */
+#define QUANT_MASK      (0xf)           /* Quantization field mask. */
+#define SEG_SHIFT       (4)             /* Left shift for segment number. */
+#define SEG_MASK        (0x70)          /* Segment field mask. */
+
+static PyInt16 seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
+                              0x1FF, 0x3FF, 0x7FF, 0xFFF};
+static PyInt16 seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
+                              0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+
+static PyInt16
+search(PyInt16 val, PyInt16 *table, int size)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        if (val <= *table++)
+            return (i);
+    }
+    return (size);
+}
+#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
+#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
+
+static PyInt16 _st_ulaw2linear16[256] = {
+    -32124,  -31100,  -30076,  -29052,  -28028,  -27004,  -25980,
+    -24956,  -23932,  -22908,  -21884,  -20860,  -19836,  -18812,
+    -17788,  -16764,  -15996,  -15484,  -14972,  -14460,  -13948,
+    -13436,  -12924,  -12412,  -11900,  -11388,  -10876,  -10364,
+     -9852,   -9340,   -8828,   -8316,   -7932,   -7676,   -7420,
+     -7164,   -6908,   -6652,   -6396,   -6140,   -5884,   -5628,
+     -5372,   -5116,   -4860,   -4604,   -4348,   -4092,   -3900,
+     -3772,   -3644,   -3516,   -3388,   -3260,   -3132,   -3004,
+     -2876,   -2748,   -2620,   -2492,   -2364,   -2236,   -2108,
+     -1980,   -1884,   -1820,   -1756,   -1692,   -1628,   -1564,
+     -1500,   -1436,   -1372,   -1308,   -1244,   -1180,   -1116,
+     -1052,    -988,    -924,    -876,    -844,    -812,    -780,
+      -748,    -716,    -684,    -652,    -620,    -588,    -556,
+      -524,    -492,    -460,    -428,    -396,    -372,    -356,
+      -340,    -324,    -308,    -292,    -276,    -260,    -244,
+      -228,    -212,    -196,    -180,    -164,    -148,    -132,
+      -120,    -112,    -104,     -96,     -88,     -80,     -72,
+       -64,     -56,     -48,     -40,     -32,     -24,     -16,
+    -8,       0,   32124,   31100,   30076,   29052,   28028,
+     27004,   25980,   24956,   23932,   22908,   21884,   20860,
+     19836,   18812,   17788,   16764,   15996,   15484,   14972,
+     14460,   13948,   13436,   12924,   12412,   11900,   11388,
+     10876,   10364,    9852,    9340,    8828,    8316,    7932,
+      7676,    7420,    7164,    6908,    6652,    6396,    6140,
+      5884,    5628,    5372,    5116,    4860,    4604,    4348,
+      4092,    3900,    3772,    3644,    3516,    3388,    3260,
+      3132,    3004,    2876,    2748,    2620,    2492,    2364,
+      2236,    2108,    1980,    1884,    1820,    1756,    1692,
+      1628,    1564,    1500,    1436,    1372,    1308,    1244,
+      1180,    1116,    1052,     988,     924,     876,     844,
+       812,     780,     748,     716,     684,     652,     620,
+       588,     556,     524,     492,     460,     428,     396,
+       372,     356,     340,     324,     308,     292,     276,
+       260,     244,     228,     212,     196,     180,     164,
+       148,     132,     120,     112,     104,      96,      88,
+    80,      72,      64,      56,      48,      40,      32,
+    24,      16,       8,       0
+};
+
+/*
+ * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 14-bits.
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ *      Biased Linear Input Code        Compressed Code
+ *      ------------------------        ---------------
+ *      00000001wxyza                   000wxyz
+ *      0000001wxyzab                   001wxyz
+ *      000001wxyzabc                   010wxyz
+ *      00001wxyzabcd                   011wxyz
+ *      0001wxyzabcde                   100wxyz
+ *      001wxyzabcdef                   101wxyz
+ *      01wxyzabcdefg                   110wxyz
+ *      1wxyzabcdefgh                   111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz.  * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static unsigned char
+st_14linear2ulaw(PyInt16 pcm_val)       /* 2's complement (14-bit range) */
+{
+    PyInt16         mask;
+    PyInt16         seg;
+    unsigned char   uval;
+
+    /* The original sox code does this in the calling function, not here */
+    pcm_val = pcm_val >> 2;
+
+    /* u-law inverts all bits */
+    /* Get the sign and the magnitude of the value. */
+    if (pcm_val < 0) {
+        pcm_val = -pcm_val;
+        mask = 0x7F;
+    } else {
+        mask = 0xFF;
+    }
+    if ( pcm_val > CLIP ) pcm_val = CLIP;           /* clip the magnitude */
+    pcm_val += (BIAS >> 2);
+
+    /* Convert the scaled magnitude to segment number. */
+    seg = search(pcm_val, seg_uend, 8);
+
+    /*
+     * Combine the sign, segment, quantization bits;
+     * and complement the code word.
+     */
+    if (seg >= 8)           /* out of range, return maximum value. */
+        return (unsigned char) (0x7F ^ mask);
+    else {
+        uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+        return (uval ^ mask);
+    }
+
+}
+
+static PyInt16 _st_alaw2linear16[256] = {
+     -5504,   -5248,   -6016,   -5760,   -4480,   -4224,   -4992,
+     -4736,   -7552,   -7296,   -8064,   -7808,   -6528,   -6272,
+     -7040,   -6784,   -2752,   -2624,   -3008,   -2880,   -2240,
+     -2112,   -2496,   -2368,   -3776,   -3648,   -4032,   -3904,
+     -3264,   -3136,   -3520,   -3392,  -22016,  -20992,  -24064,
+    -23040,  -17920,  -16896,  -19968,  -18944,  -30208,  -29184,
+    -32256,  -31232,  -26112,  -25088,  -28160,  -27136,  -11008,
+    -10496,  -12032,  -11520,   -8960,   -8448,   -9984,   -9472,
+    -15104,  -14592,  -16128,  -15616,  -13056,  -12544,  -14080,
+    -13568,    -344,    -328,    -376,    -360,    -280,    -264,
+      -312,    -296,    -472,    -456,    -504,    -488,    -408,
+      -392,    -440,    -424,     -88,     -72,    -120,    -104,
+       -24,      -8,     -56,     -40,    -216,    -200,    -248,
+      -232,    -152,    -136,    -184,    -168,   -1376,   -1312,
+     -1504,   -1440,   -1120,   -1056,   -1248,   -1184,   -1888,
+     -1824,   -2016,   -1952,   -1632,   -1568,   -1760,   -1696,
+      -688,    -656,    -752,    -720,    -560,    -528,    -624,
+      -592,    -944,    -912,   -1008,    -976,    -816,    -784,
+      -880,    -848,    5504,    5248,    6016,    5760,    4480,
+      4224,    4992,    4736,    7552,    7296,    8064,    7808,
+      6528,    6272,    7040,    6784,    2752,    2624,    3008,
+      2880,    2240,    2112,    2496,    2368,    3776,    3648,
+      4032,    3904,    3264,    3136,    3520,    3392,   22016,
+     20992,   24064,   23040,   17920,   16896,   19968,   18944,
+     30208,   29184,   32256,   31232,   26112,   25088,   28160,
+     27136,   11008,   10496,   12032,   11520,    8960,    8448,
+      9984,    9472,   15104,   14592,   16128,   15616,   13056,
+     12544,   14080,   13568,     344,     328,     376,     360,
+       280,     264,     312,     296,     472,     456,     504,
+       488,     408,     392,     440,     424,      88,      72,
+       120,     104,      24,       8,      56,      40,     216,
+       200,     248,     232,     152,     136,     184,     168,
+      1376,    1312,    1504,    1440,    1120,    1056,    1248,
+      1184,    1888,    1824,    2016,    1952,    1632,    1568,
+      1760,    1696,     688,     656,     752,     720,     560,
+       528,     624,     592,     944,     912,    1008,     976,
+       816,     784,     880,     848
+};
+
+/*
+ * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 13-bits.
+ *
+ *              Linear Input Code       Compressed Code
+ *      ------------------------        ---------------
+ *      0000000wxyza                    000wxyz
+ *      0000001wxyza                    001wxyz
+ *      000001wxyzab                    010wxyz
+ *      00001wxyzabc                    011wxyz
+ *      0001wxyzabcd                    100wxyz
+ *      001wxyzabcde                    101wxyz
+ *      01wxyzabcdef                    110wxyz
+ *      1wxyzabcdefg                    111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static unsigned char
+st_linear2alaw(PyInt16 pcm_val) /* 2's complement (13-bit range) */
+{
+    PyInt16         mask;
+    short           seg;
+    unsigned char   aval;
+
+    /* The original sox code does this in the calling function, not here */
+    pcm_val = pcm_val >> 3;
+
+    /* A-law using even bit inversion */
+    if (pcm_val >= 0) {
+        mask = 0xD5;            /* sign (7th) bit = 1 */
+    } else {
+        mask = 0x55;            /* sign bit = 0 */
+        pcm_val = -pcm_val - 1;
+    }
+
+    /* Convert the scaled magnitude to segment number. */
+    seg = search(pcm_val, seg_aend, 8);
+
+    /* Combine the sign, segment, and quantization bits. */
+
+    if (seg >= 8)           /* out of range, return maximum value. */
+        return (unsigned char) (0x7F ^ mask);
+    else {
+        aval = (unsigned char) seg << SEG_SHIFT;
+        if (seg < 2)
+            aval |= (pcm_val >> 1) & QUANT_MASK;
+        else
+            aval |= (pcm_val >> seg) & QUANT_MASK;
+        return (aval ^ mask);
+    }
+}
+/* End of code taken from sox */
+
+/* Intel ADPCM step variation table */
+static int indexTable[16] = {
+    -1, -1, -1, -1, 2, 4, 6, 8,
+    -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static int stepsizeTable[89] = {
+    7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+    19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+    50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+    130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+#define CHARP(cp, i) ((signed char *)(cp+i))
+#define SHORTP(cp, i) ((short *)(cp+i))
+#define LONGP(cp, i) ((Py_Int32 *)(cp+i))
+"""
+
+C_SOURCE = _AUDIOOP_C_MODULE + r"""
+#include <math.h>
+
+static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
+/* -1 trick is needed on Windows to support -0x80000000 without a warning */
+static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
+
+static int
+fbound(double val, double minval, double maxval)
+{
+    if (val > maxval)
+        val = maxval;
+    else if (val < minval + 1)
+        val = minval;
+    return val;
+}
+
+static int
+gcd(int a, int b)
+{
+    while (b > 0) {
+        int tmp = a % b;
+        a = b;
+        b = tmp;
+    }
+    return a;
+}
+
+int ratecv(char* rv, char* cp, size_t len, int size,
+           int nchannels, int inrate, int outrate,
+           int* state_d, int* prev_i, int* cur_i,
+           int weightA, int weightB)
+{
+    char *ncp = rv;
+    int d, chan;
+
+    /* divide inrate and outrate by their greatest common divisor */
+    d = gcd(inrate, outrate);
+    inrate /= d;
+    outrate /= d;
+    /* divide weightA and weightB by their greatest common divisor */
+    d = gcd(weightA, weightB);
+    weightA /= d;
+    weightA /= d;
+
+    d = *state_d;
+
+    for (;;) {
+        while (d < 0) {
+            if (len == 0) {
+                *state_d = d;
+                return ncp - rv;
+            }
+            for (chan = 0; chan < nchannels; chan++) {
+                prev_i[chan] = cur_i[chan];
+                if (size == 1)
+                    cur_i[chan] = ((int)*CHARP(cp, 0)) << 24;
+                else if (size == 2)
+                    cur_i[chan] = ((int)*SHORTP(cp, 0)) << 16;
+                else if (size == 4)
+                    cur_i[chan] = (int)*LONGP(cp, 0);
+                cp += size;
+                /* implements a simple digital filter */
+                cur_i[chan] = (int)(
+                    ((double)weightA * (double)cur_i[chan] +
+                     (double)weightB * (double)prev_i[chan]) /
+                    ((double)weightA + (double)weightB));
+            }
+            len--;
+            d += outrate;
+        }
+        while (d >= 0) {
+            for (chan = 0; chan < nchannels; chan++) {
+                int cur_o;
+                cur_o = (int)(((double)prev_i[chan] * (double)d +
+                         (double)cur_i[chan] * (double)(outrate - d)) /
+                    (double)outrate);
+                if (size == 1)
+                    *CHARP(ncp, 0) = (signed char)(cur_o >> 24);
+                else if (size == 2)
+                    *SHORTP(ncp, 0) = (short)(cur_o >> 16);
+                else if (size == 4)
+                    *LONGP(ncp, 0) = (Py_Int32)(cur_o);
+                ncp += size;
+            }
+            d -= inrate;
+        }
+    }
+}
+
+void tostereo(char* rv, char* cp, size_t len, int size,
+              double fac1, double fac2)
+{
+    int val1, val2, val = 0;
+    double fval, maxval, minval;
+    char *ncp = rv;
+    int i;
+
+    maxval = (double) maxvals[size];
+    minval = (double) minvals[size];
+
+    for ( i=0; i < len; i += size ) {
+        if ( size == 1 )      val = (int)*CHARP(cp, i);
+        else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+        else if ( size == 4 ) val = (int)*LONGP(cp, i);
+
+        fval = (double)val*fac1;
+        val1 = (int)floor(fbound(fval, minval, maxval));
+
+        fval = (double)val*fac2;
+        val2 = (int)floor(fbound(fval, minval, maxval));
+
+        if ( size == 1 )      *CHARP(ncp, i*2) = (signed char)val1;
+        else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
+        else if ( size == 4 ) *LONGP(ncp, i*2) = (Py_Int32)val1;
+
+        if ( size == 1 )      *CHARP(ncp, i*2+1) = (signed char)val2;
+        else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
+        else if ( size == 4 ) *LONGP(ncp, i*2+4) = (Py_Int32)val2;
+    }
+}
+
+void add(char* rv, char* cp1, char* cp2, size_t len1, int size)
+{
+    int i;
+    int val1 = 0, val2 = 0, minval, maxval, newval;
+    char* ncp = rv;
+
+    maxval = maxvals[size];
+    minval = minvals[size];
+
+    for ( i=0; i < len1; i += size ) {
+        if ( size == 1 )      val1 = (int)*CHARP(cp1, i);
+        else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
+        else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
+
+        if ( size == 1 )      val2 = (int)*CHARP(cp2, i);
+        else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
+        else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
+
+        if (size < 4) {
+            newval = val1 + val2;
+            /* truncate in case of overflow */
+            if (newval > maxval)
+                newval = maxval;
+            else if (newval < minval)
+                newval = minval;
+        }
+        else {
+            double fval = (double)val1 + (double)val2;
+            /* truncate in case of overflow */
+            newval = (int)floor(fbound(fval, minval, maxval));
+        }
+
+        if ( size == 1 )      *CHARP(ncp, i) = (signed char)newval;
+        else if ( size == 2 ) *SHORTP(ncp, i) = (short)newval;
+        else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)newval;
+    }
+}
+
+void lin2adcpm(unsigned char* ncp, unsigned char* cp, size_t len,
+               size_t size, int* state)
+{
+    int step, outputbuffer = 0, bufferstep;
+    int val = 0;
+    int diff, vpdiff, sign, delta;
+    size_t i;
+    int valpred = state[0];
+    int index = state[1];
+
+    step = stepsizeTable[index];
+    bufferstep = 1;
+
+    for ( i=0; i < len; i += size ) {
+        if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
+        else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+        else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+
+        /* Step 1 - compute difference with previous value */
+        diff = val - valpred;
+        sign = (diff < 0) ? 8 : 0;
+        if ( sign ) diff = (-diff);
+
+        /* Step 2 - Divide and clamp */
+        /* Note:
+        ** This code *approximately* computes:
+        **    delta = diff*4/step;
+        **    vpdiff = (delta+0.5)*step/4;
+        ** but in shift step bits are dropped. The net result of this
+        ** is that even if you have fast mul/div hardware you cannot
+        ** put it to good use since the fixup would be too expensive.
+        */
+        delta = 0;
+        vpdiff = (step >> 3);
+
+        if ( diff >= step ) {
+            delta = 4;
+            diff -= step;
+            vpdiff += step;
+        }
+        step >>= 1;
+        if ( diff >= step  ) {
+            delta |= 2;
+            diff -= step;
+            vpdiff += step;
+        }
+        step >>= 1;
+        if ( diff >= step ) {
+            delta |= 1;
+            vpdiff += step;
+        }
+
+        /* Step 3 - Update previous value */
+        if ( sign )
+            valpred -= vpdiff;
+        else
+            valpred += vpdiff;
+
+        /* Step 4 - Clamp previous value to 16 bits */
+        if ( valpred > 32767 )
+            valpred = 32767;
+        else if ( valpred < -32768 )
+            valpred = -32768;
+
+        /* Step 5 - Assemble value, update index and step values */
+        delta |= sign;
+
+        index += indexTable[delta];
+        if ( index < 0 ) index = 0;
+        if ( index > 88 ) index = 88;
+        step = stepsizeTable[index];
+
+        /* Step 6 - Output value */
+        if ( bufferstep ) {
+            outputbuffer = (delta << 4) & 0xf0;
+        } else {
+            *ncp++ = (delta & 0x0f) | outputbuffer;
+        }
+        bufferstep = !bufferstep;
+    }
+    state[0] = valpred;
+    state[1] = index;
+}
+
+
+void adcpm2lin(unsigned char* ncp, unsigned char* cp, size_t len,
+               size_t size, int* state)
+{
+    int step, inputbuffer = 0, bufferstep;
+    int val = 0;
+    int diff, vpdiff, sign, delta;
+    size_t i;
+    int valpred = state[0];
+    int index = state[1];
+
+    step = stepsizeTable[index];
+    bufferstep = 0;
+
+    for ( i=0; i < len*size*2; i += size ) {
+        /* Step 1 - get the delta value and compute next index */
+        if ( bufferstep ) {
+            delta = inputbuffer & 0xf;
+        } else {
+            inputbuffer = *cp++;
+            delta = (inputbuffer >> 4) & 0xf;
+        }
+
+        bufferstep = !bufferstep;
+
+        /* Step 2 - Find new index value (for later) */
+        index += indexTable[delta];
+        if ( index < 0 ) index = 0;
+        if ( index > 88 ) index = 88;
+
+        /* Step 3 - Separate sign and magnitude */
+        sign = delta & 8;
+        delta = delta & 7;
+
+        /* Step 4 - Compute difference and new predicted value */
+        /*
+        ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+        ** in adpcm_coder.
+        */
+        vpdiff = step >> 3;
+        if ( delta & 4 ) vpdiff += step;
+        if ( delta & 2 ) vpdiff += step>>1;
+        if ( delta & 1 ) vpdiff += step>>2;
+
+        if ( sign )
+            valpred -= vpdiff;
+        else
+            valpred += vpdiff;
+
+        /* Step 5 - clamp output value */
+        if ( valpred > 32767 )
+            valpred = 32767;
+        else if ( valpred < -32768 )
+            valpred = -32768;
+
+        /* Step 6 - Update step value */
+        step = stepsizeTable[index];
+
+        /* Step 6 - Output value */
+        if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
+        else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
+        else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(valpred<<16);
+    }
+    state[0] = valpred;
+    state[1] = index;
+}
+"""
+
+ffi.set_source("_audioop_cffi", C_SOURCE)
+
+if __name__ == "__main__":
+    ffi.compile()
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -275,7 +275,11 @@
             if argtypes:
                 args = [argtype._CData_retval(argtype.from_address(arg)._buffer)
                         for argtype, arg in zip(argtypes, args)]
-            return to_call(*args)
+            try:
+                return to_call(*args)
+            except SystemExit as e:
+                handle_system_exit(e)
+                raise
         return f
 
     def __call__(self, *args, **kwargs):
@@ -304,7 +308,11 @@
             except (UnicodeError, TypeError, ValueError) as e:
                 raise ArgumentError(str(e))
             try:
-                res = self.callable(*newargs)
+                try:
+                    res = self.callable(*newargs)
+                except SystemExit as e:
+                    handle_system_exit(e)
+                    raise
             except:
                 exc_info = sys.exc_info()
                 traceback.print_tb(exc_info[2], file=sys.stderr)
@@ -715,3 +723,22 @@
     make_fastpath_subclass.memo[CFuncPtr] = CFuncPtrFast
     return CFuncPtrFast
 make_fastpath_subclass.memo = {}
+
+
+def handle_system_exit(e):
+    # issue #1194: if we get SystemExit here, then exit the interpreter.
+    # Highly obscure imho but some people seem to depend on it.
+    if sys.flags.inspect:
+        return   # Don't exit if -i flag was given.
+    else:
+        code = e.code
+        if isinstance(code, int):
+            exitcode = code
+        else:
+            f = getattr(sys, 'stderr', None)
+            if f is None:
+                f = sys.__stderr__
+            print >> f, code
+            exitcode = 1
+
+        _rawffi.exit(exitcode)
diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
--- a/lib_pypy/_curses.py
+++ b/lib_pypy/_curses.py
@@ -6,326 +6,7 @@
     raise ImportError('No module named _curses')
 from functools import wraps
 
-from cffi import FFI
-
-ffi = FFI()
-
-ffi.cdef("""
-typedef ... WINDOW;
-typedef ... SCREEN;
-typedef unsigned long mmask_t;
-typedef unsigned char bool;
-typedef unsigned long chtype;
-typedef chtype attr_t;
-
-typedef struct
-{
-    short id;           /* ID to distinguish multiple devices */
-    int x, y, z;        /* event coordinates (character-cell) */
-    mmask_t bstate;     /* button state bits */
-}
-MEVENT;
-
-static const int ERR, OK;
-static const int TRUE, FALSE;
-static const int KEY_MIN, KEY_MAX;
-
-static const int COLOR_BLACK;
-static const int COLOR_RED;
-static const int COLOR_GREEN;
-static const int COLOR_YELLOW;
-static const int COLOR_BLUE;
-static const int COLOR_MAGENTA;
-static const int COLOR_CYAN;
-static const int COLOR_WHITE;
-
-static const chtype A_ATTRIBUTES;
-static const chtype A_NORMAL;
-static const chtype A_STANDOUT;
-static const chtype A_UNDERLINE;
-static const chtype A_REVERSE;
-static const chtype A_BLINK;
-static const chtype A_DIM;
-static const chtype A_BOLD;
-static const chtype A_ALTCHARSET;
-static const chtype A_INVIS;
-static const chtype A_PROTECT;
-static const chtype A_CHARTEXT;
-static const chtype A_COLOR;
-
-static const int BUTTON1_RELEASED;
-static const int BUTTON1_PRESSED;
-static const int BUTTON1_CLICKED;
-static const int BUTTON1_DOUBLE_CLICKED;
-static const int BUTTON1_TRIPLE_CLICKED;
-static const int BUTTON2_RELEASED;
-static const int BUTTON2_PRESSED;
-static const int BUTTON2_CLICKED;
-static const int BUTTON2_DOUBLE_CLICKED;
-static const int BUTTON2_TRIPLE_CLICKED;
-static const int BUTTON3_RELEASED;
-static const int BUTTON3_PRESSED;
-static const int BUTTON3_CLICKED;
-static const int BUTTON3_DOUBLE_CLICKED;
-static const int BUTTON3_TRIPLE_CLICKED;
-static const int BUTTON4_RELEASED;
-static const int BUTTON4_PRESSED;
-static const int BUTTON4_CLICKED;
-static const int BUTTON4_DOUBLE_CLICKED;
-static const int BUTTON4_TRIPLE_CLICKED;
-static const int BUTTON_SHIFT;
-static const int BUTTON_CTRL;
-static const int BUTTON_ALT;
-static const int ALL_MOUSE_EVENTS;
-static const int REPORT_MOUSE_POSITION;
-
-int setupterm(char *, int, int *);
-
-WINDOW *stdscr;
-int COLORS;
-int COLOR_PAIRS;
-int COLS;
-int LINES;
-
-int baudrate(void);
-int beep(void);
-int box(WINDOW *, chtype, chtype);
-bool can_change_color(void);
-int cbreak(void);
-int clearok(WINDOW *, bool);
-int color_content(short, short*, short*, short*);
-int copywin(const WINDOW*, WINDOW*, int, int, int, int, int, int, int);
-int curs_set(int);
-int def_prog_mode(void);
-int def_shell_mode(void);
-int delay_output(int);
-int delwin(WINDOW *);
-WINDOW * derwin(WINDOW *, int, int, int, int);
-int doupdate(void);
-int echo(void);
-int endwin(void);
-char erasechar(void);
-void filter(void);
-int flash(void);
-int flushinp(void);
-chtype getbkgd(WINDOW *);
-WINDOW * getwin(FILE *);
-int halfdelay(int);
-bool has_colors(void);
-bool has_ic(void);
-bool has_il(void);
-void idcok(WINDOW *, bool);
-int idlok(WINDOW *, bool);
-void immedok(WINDOW *, bool);
-WINDOW * initscr(void);
-int init_color(short, short, short, short);
-int init_pair(short, short, short);
-int intrflush(WINDOW *, bool);
-bool isendwin(void);
-bool is_linetouched(WINDOW *, int);
-bool is_wintouched(WINDOW *);
-const char * keyname(int);
-int keypad(WINDOW *, bool);
-char killchar(void);
-int leaveok(WINDOW *, bool);
-char * longname(void);
-int meta(WINDOW *, bool);
-int mvderwin(WINDOW *, int, int);
-int mvwaddch(WINDOW *, int, int, const chtype);
-int mvwaddnstr(WINDOW *, int, int, const char *, int);
-int mvwaddstr(WINDOW *, int, int, const char *);
-int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *);
-int mvwdelch(WINDOW *, int, int);
-int mvwgetch(WINDOW *, int, int);
-int mvwgetnstr(WINDOW *, int, int, char *, int);
-int mvwin(WINDOW *, int, int);
-chtype mvwinch(WINDOW *, int, int);
-int mvwinnstr(WINDOW *, int, int, char *, int);
-int mvwinsch(WINDOW *, int, int, chtype);
-int mvwinsnstr(WINDOW *, int, int, const char *, int);
-int mvwinsstr(WINDOW *, int, int, const char *);
-int napms(int);
-WINDOW * newpad(int, int);
-WINDOW * newwin(int, int, int, int);
-int nl(void);
-int nocbreak(void);
-int nodelay(WINDOW *, bool);
-int noecho(void);
-int nonl(void);
-void noqiflush(void);
-int noraw(void);
-int notimeout(WINDOW *, bool);
-int overlay(const WINDOW*, WINDOW *);
-int overwrite(const WINDOW*, WINDOW *);
-int pair_content(short, short*, short*);
-int pechochar(WINDOW *, const chtype);
-int pnoutrefresh(WINDOW*, int, int, int, int, int, int);
-int prefresh(WINDOW *, int, int, int, int, int, int);
-int putwin(WINDOW *, FILE *);
-void qiflush(void);
-int raw(void);
-int redrawwin(WINDOW *);
-int resetty(void);
-int reset_prog_mode(void);
-int reset_shell_mode(void);
-int savetty(void);
-int scroll(WINDOW *);
-int scrollok(WINDOW *, bool);
-int start_color(void);
-WINDOW * subpad(WINDOW *, int, int, int, int);
-WINDOW * subwin(WINDOW *, int, int, int, int);
-int syncok(WINDOW *, bool);
-chtype termattrs(void);
-char * termname(void);
-int touchline(WINDOW *, int, int);
-int touchwin(WINDOW *);
-int typeahead(int);
-int ungetch(int);
-int untouchwin(WINDOW *);
-void use_env(bool);
-int waddch(WINDOW *, const chtype);
-int waddnstr(WINDOW *, const char *, int);
-int waddstr(WINDOW *, const char *);
-int wattron(WINDOW *, int);
-int wattroff(WINDOW *, int);
-int wattrset(WINDOW *, int);
-int wbkgd(WINDOW *, chtype);
-void wbkgdset(WINDOW *, chtype);
-int wborder(WINDOW *, chtype, chtype, chtype, chtype,
-            chtype, chtype, chtype, chtype);
-int wchgat(WINDOW *, int, attr_t, short, const void *);
-int wclear(WINDOW *);
-int wclrtobot(WINDOW *);
-int wclrtoeol(WINDOW *);
-void wcursyncup(WINDOW *);
-int wdelch(WINDOW *);
-int wdeleteln(WINDOW *);
-int wechochar(WINDOW *, const chtype);
-int werase(WINDOW *);
-int wgetch(WINDOW *);
-int wgetnstr(WINDOW *, char *, int);
-int whline(WINDOW *, chtype, int);
-chtype winch(WINDOW *);
-int winnstr(WINDOW *, char *, int);
-int winsch(WINDOW *, chtype);
-int winsdelln(WINDOW *, int);
-int winsertln(WINDOW *);
-int winsnstr(WINDOW *, const char *, int);
-int winsstr(WINDOW *, const char *);
-int wmove(WINDOW *, int, int);
-int wresize(WINDOW *, int, int);
-int wnoutrefresh(WINDOW *);
-int wredrawln(WINDOW *, int, int);
-int wrefresh(WINDOW *);
-int wscrl(WINDOW *, int);
-int wsetscrreg(WINDOW *, int, int);
-int wstandout(WINDOW *);
-int wstandend(WINDOW *);
-void wsyncdown(WINDOW *);
-void wsyncup(WINDOW *);
-void wtimeout(WINDOW *, int);
-int wtouchln(WINDOW *, int, int, int);
-int wvline(WINDOW *, chtype, int);
-int tigetflag(char *);
-int tigetnum(char *);
-char * tigetstr(char *);
-int putp(const char *);
-char * tparm(const char *, ...);
-int getattrs(const WINDOW *);
-int getcurx(const WINDOW *);
-int getcury(const WINDOW *);
-int getbegx(const WINDOW *);
-int getbegy(const WINDOW *);
-int getmaxx(const WINDOW *);
-int getmaxy(const WINDOW *);
-int getparx(const WINDOW *);
-int getpary(const WINDOW *);
-
-int getmouse(MEVENT *);
-int ungetmouse(MEVENT *);
-mmask_t mousemask(mmask_t, mmask_t *);
-bool wenclose(const WINDOW *, int, int);
-int mouseinterval(int);
-
-void setsyx(int y, int x);
-const char *unctrl(chtype);
-int use_default_colors(void);
-
-int has_key(int);
-bool is_term_resized(int, int);
-
-#define _m_STRICT_SYSV_CURSES ...
-#define _m_NCURSES_MOUSE_VERSION ...
-#define _m_NetBSD ...
-int _m_ispad(WINDOW *);
-
-chtype acs_map[];
-
-// For _curses_panel:
-
-typedef ... PANEL;
-
-WINDOW *panel_window(const PANEL *);
-void update_panels(void);
-int hide_panel(PANEL *);
-int show_panel(PANEL *);
-int del_panel(PANEL *);
-int top_panel(PANEL *);
-int bottom_panel(PANEL *);
-PANEL *new_panel(WINDOW *);
-PANEL *panel_above(const PANEL *);
-PANEL *panel_below(const PANEL *);
-int set_panel_userptr(PANEL *, void *);
-const void *panel_userptr(const PANEL *);
-int move_panel(PANEL *, int, int);
-int replace_panel(PANEL *,WINDOW *);
-int panel_hidden(const PANEL *);
-
-void _m_getsyx(int *yx);
-""")
-
-
-lib = ffi.verify("""
-#ifdef __APPLE__
-/* the following define is necessary for OS X 10.6+; without it, the
-   Apple-supplied ncurses.h sets NCURSES_OPAQUE to 1, and then Python
-   can't get at the WINDOW flags field. */
-#define NCURSES_OPAQUE 0
-#endif
-
-#include <ncurses.h>
-#include <panel.h>
-#include <term.h>
-
-#if defined STRICT_SYSV_CURSES
-#define _m_STRICT_SYSV_CURSES TRUE
-#else
-#define _m_STRICT_SYSV_CURSES FALSE
-#endif
-
-#if defined NCURSES_MOUSE_VERSION
-#define _m_NCURSES_MOUSE_VERSION TRUE
-#else
-#define _m_NCURSES_MOUSE_VERSION FALSE
-#endif
-
-#if defined __NetBSD__
-#define _m_NetBSD TRUE
-#else
-#define _m_NetBSD FALSE
-#endif
-
-int _m_ispad(WINDOW *win) {
-    // <curses.h> may not have _flags (and possibly _ISPAD),
-    // but for now let's assume that <ncurses.h> always has it
-    return (win->_flags & _ISPAD);
-}
-
-void _m_getsyx(int *yx) {
-    getsyx(yx[0], yx[1]);
-}
-""", libraries=['ncursesw', 'panel'])
-
+from _curses_cffi import ffi, lib
 
 def _copy_to_globals(name):
     globals()[name] = getattr(lib, name)
@@ -484,13 +165,13 @@
 def _chtype(ch):
     return int(ffi.cast("chtype", ch))
 
-def _texttype(text):
+def _bytestype(text):
     if isinstance(text, bytes):
         return text
     elif isinstance(text, str):
         return text.encode('utf-8')
     else:
-        raise TypeError("str or bytes expected, got a '%s' object"
+        raise TypeError("bytes or str expected, got a '%s' object"
                         % (type(text).__name__,))
 
 
@@ -606,7 +287,7 @@
 
     @_argspec(1, 1, 2)
     def addstr(self, y, x, text, attr=None):
-        text = _texttype(text)
+        text = _bytestype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -620,7 +301,7 @@
 
     @_argspec(2, 1, 2)
     def addnstr(self, y, x, text, n, attr=None):
-        text = _texttype(text)
+        text = _bytestype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -799,7 +480,7 @@
 
     @_argspec(1, 1, 2)
     def insstr(self, y, x, text, attr=None):
-        text = _texttype(text)
+        text = _bytestype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -813,7 +494,7 @@
 
     @_argspec(2, 1, 2)
     def insnstr(self, y, x, text, n, attr=None):
-        text = _texttype(text)
+        text = _bytestype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -1221,7 +902,7 @@
 
 
 def putp(text):
-    text = _texttype(text)
+    text = _bytestype(text)
     return _check_ERR(lib.putp(text), "putp")
 
 
@@ -1347,23 +1028,17 @@
 
 def tigetflag(capname):
     _ensure_initialised_setupterm()
-    if isinstance(capname, str):
-        capname = capname.encode('utf-8')
-    return lib.tigetflag(capname)
+    return lib.tigetflag(capname.encode())
 
 
 def tigetnum(capname):
     _ensure_initialised_setupterm()
-    if isinstance(capname, str):
-        capname = capname.encode('utf-8')
-    return lib.tigetnum(capname)
+    return lib.tigetnum(capname.encode())
 
 
 def tigetstr(capname):
     _ensure_initialised_setupterm()
-    if isinstance(capname, str):
-        capname = capname.encode('utf-8')
-    val = lib.tigetstr(capname)
+    val = lib.tigetstr(capname.encode())
     if int(ffi.cast("intptr_t", val)) in (0, -1):
         return None
     return ffi.string(val)
diff --git a/lib_pypy/_curses_build.py b/lib_pypy/_curses_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_curses_build.py
@@ -0,0 +1,323 @@
+from cffi import FFI
+
+ffi = FFI()
+
+ffi.set_source("_curses_cffi", """
+#ifdef __APPLE__
+/* the following define is necessary for OS X 10.6+; without it, the
+   Apple-supplied ncurses.h sets NCURSES_OPAQUE to 1, and then Python
+   can't get at the WINDOW flags field. */
+#define NCURSES_OPAQUE 0
+#endif
+
+#include <ncurses.h>
+#include <panel.h>
+#include <term.h>
+
+#if defined STRICT_SYSV_CURSES
+#define _m_STRICT_SYSV_CURSES TRUE
+#else
+#define _m_STRICT_SYSV_CURSES FALSE
+#endif
+
+#if defined NCURSES_MOUSE_VERSION
+#define _m_NCURSES_MOUSE_VERSION TRUE
+#else
+#define _m_NCURSES_MOUSE_VERSION FALSE
+#endif
+
+#if defined __NetBSD__
+#define _m_NetBSD TRUE
+#else
+#define _m_NetBSD FALSE
+#endif
+
+int _m_ispad(WINDOW *win) {
+    // <curses.h> may not have _flags (and possibly _ISPAD),
+    // but for now let's assume that <ncurses.h> always has it
+    return (win->_flags & _ISPAD);
+}
+
+void _m_getsyx(int *yx) {
+    getsyx(yx[0], yx[1]);
+}
+""", libraries=['ncursesw', 'panel'])
+
+
+ffi.cdef("""
+typedef ... WINDOW;
+typedef ... SCREEN;
+typedef unsigned long... mmask_t;
+typedef unsigned char bool;
+typedef unsigned long... chtype;
+typedef chtype attr_t;
+
+typedef struct
+{
+    short id;           /* ID to distinguish multiple devices */
+    int x, y, z;        /* event coordinates (character-cell) */
+    mmask_t bstate;     /* button state bits */
+}
+MEVENT;
+
+static const int ERR, OK;
+static const int TRUE, FALSE;
+static const int KEY_MIN, KEY_MAX;
+
+static const int COLOR_BLACK;
+static const int COLOR_RED;
+static const int COLOR_GREEN;
+static const int COLOR_YELLOW;
+static const int COLOR_BLUE;
+static const int COLOR_MAGENTA;
+static const int COLOR_CYAN;
+static const int COLOR_WHITE;
+
+static const chtype A_ATTRIBUTES;
+static const chtype A_NORMAL;
+static const chtype A_STANDOUT;
+static const chtype A_UNDERLINE;
+static const chtype A_REVERSE;
+static const chtype A_BLINK;
+static const chtype A_DIM;
+static const chtype A_BOLD;
+static const chtype A_ALTCHARSET;
+static const chtype A_INVIS;
+static const chtype A_PROTECT;
+static const chtype A_CHARTEXT;
+static const chtype A_COLOR;
+
+static const int BUTTON1_RELEASED;
+static const int BUTTON1_PRESSED;
+static const int BUTTON1_CLICKED;
+static const int BUTTON1_DOUBLE_CLICKED;
+static const int BUTTON1_TRIPLE_CLICKED;
+static const int BUTTON2_RELEASED;
+static const int BUTTON2_PRESSED;
+static const int BUTTON2_CLICKED;
+static const int BUTTON2_DOUBLE_CLICKED;
+static const int BUTTON2_TRIPLE_CLICKED;
+static const int BUTTON3_RELEASED;
+static const int BUTTON3_PRESSED;
+static const int BUTTON3_CLICKED;
+static const int BUTTON3_DOUBLE_CLICKED;
+static const int BUTTON3_TRIPLE_CLICKED;
+static const int BUTTON4_RELEASED;
+static const int BUTTON4_PRESSED;
+static const int BUTTON4_CLICKED;
+static const int BUTTON4_DOUBLE_CLICKED;
+static const int BUTTON4_TRIPLE_CLICKED;
+static const int BUTTON_SHIFT;
+static const int BUTTON_CTRL;
+static const int BUTTON_ALT;
+static const int ALL_MOUSE_EVENTS;
+static const int REPORT_MOUSE_POSITION;
+
+int setupterm(char *, int, int *);
+
+WINDOW *stdscr;
+int COLORS;
+int COLOR_PAIRS;
+int COLS;
+int LINES;
+
+int baudrate(void);
+int beep(void);
+int box(WINDOW *, chtype, chtype);
+bool can_change_color(void);
+int cbreak(void);
+int clearok(WINDOW *, bool);
+int color_content(short, short*, short*, short*);
+int copywin(const WINDOW*, WINDOW*, int, int, int, int, int, int, int);
+int curs_set(int);
+int def_prog_mode(void);
+int def_shell_mode(void);
+int delay_output(int);
+int delwin(WINDOW *);
+WINDOW * derwin(WINDOW *, int, int, int, int);
+int doupdate(void);
+int echo(void);
+int endwin(void);
+char erasechar(void);
+void filter(void);
+int flash(void);
+int flushinp(void);
+chtype getbkgd(WINDOW *);
+WINDOW * getwin(FILE *);
+int halfdelay(int);
+bool has_colors(void);
+bool has_ic(void);
+bool has_il(void);
+void idcok(WINDOW *, bool);
+int idlok(WINDOW *, bool);
+void immedok(WINDOW *, bool);
+WINDOW * initscr(void);
+int init_color(short, short, short, short);
+int init_pair(short, short, short);
+int intrflush(WINDOW *, bool);
+bool isendwin(void);
+bool is_linetouched(WINDOW *, int);
+bool is_wintouched(WINDOW *);
+const char * keyname(int);
+int keypad(WINDOW *, bool);
+char killchar(void);
+int leaveok(WINDOW *, bool);
+char * longname(void);
+int meta(WINDOW *, bool);
+int mvderwin(WINDOW *, int, int);
+int mvwaddch(WINDOW *, int, int, const chtype);
+int mvwaddnstr(WINDOW *, int, int, const char *, int);
+int mvwaddstr(WINDOW *, int, int, const char *);
+int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *);
+int mvwdelch(WINDOW *, int, int);
+int mvwgetch(WINDOW *, int, int);
+int mvwgetnstr(WINDOW *, int, int, char *, int);
+int mvwin(WINDOW *, int, int);
+chtype mvwinch(WINDOW *, int, int);
+int mvwinnstr(WINDOW *, int, int, char *, int);
+int mvwinsch(WINDOW *, int, int, chtype);
+int mvwinsnstr(WINDOW *, int, int, const char *, int);
+int mvwinsstr(WINDOW *, int, int, const char *);
+int napms(int);
+WINDOW * newpad(int, int);
+WINDOW * newwin(int, int, int, int);
+int nl(void);
+int nocbreak(void);
+int nodelay(WINDOW *, bool);
+int noecho(void);
+int nonl(void);
+void noqiflush(void);
+int noraw(void);
+int notimeout(WINDOW *, bool);
+int overlay(const WINDOW*, WINDOW *);
+int overwrite(const WINDOW*, WINDOW *);
+int pair_content(short, short*, short*);
+int pechochar(WINDOW *, const chtype);
+int pnoutrefresh(WINDOW*, int, int, int, int, int, int);
+int prefresh(WINDOW *, int, int, int, int, int, int);
+int putwin(WINDOW *, FILE *);
+void qiflush(void);
+int raw(void);
+int redrawwin(WINDOW *);
+int resetty(void);
+int reset_prog_mode(void);
+int reset_shell_mode(void);
+int savetty(void);
+int scroll(WINDOW *);
+int scrollok(WINDOW *, bool);
+int start_color(void);
+WINDOW * subpad(WINDOW *, int, int, int, int);
+WINDOW * subwin(WINDOW *, int, int, int, int);
+int syncok(WINDOW *, bool);
+chtype termattrs(void);
+char * termname(void);
+int touchline(WINDOW *, int, int);
+int touchwin(WINDOW *);
+int typeahead(int);
+int ungetch(int);
+int untouchwin(WINDOW *);
+void use_env(bool);
+int waddch(WINDOW *, const chtype);
+int waddnstr(WINDOW *, const char *, int);
+int waddstr(WINDOW *, const char *);
+int wattron(WINDOW *, int);
+int wattroff(WINDOW *, int);
+int wattrset(WINDOW *, int);
+int wbkgd(WINDOW *, chtype);
+void wbkgdset(WINDOW *, chtype);
+int wborder(WINDOW *, chtype, chtype, chtype, chtype,
+            chtype, chtype, chtype, chtype);
+int wchgat(WINDOW *, int, attr_t, short, const void *);
+int wclear(WINDOW *);
+int wclrtobot(WINDOW *);
+int wclrtoeol(WINDOW *);
+void wcursyncup(WINDOW *);
+int wdelch(WINDOW *);
+int wdeleteln(WINDOW *);
+int wechochar(WINDOW *, const chtype);
+int werase(WINDOW *);
+int wgetch(WINDOW *);
+int wgetnstr(WINDOW *, char *, int);
+int whline(WINDOW *, chtype, int);
+chtype winch(WINDOW *);
+int winnstr(WINDOW *, char *, int);
+int winsch(WINDOW *, chtype);
+int winsdelln(WINDOW *, int);
+int winsertln(WINDOW *);
+int winsnstr(WINDOW *, const char *, int);
+int winsstr(WINDOW *, const char *);
+int wmove(WINDOW *, int, int);
+int wresize(WINDOW *, int, int);
+int wnoutrefresh(WINDOW *);
+int wredrawln(WINDOW *, int, int);
+int wrefresh(WINDOW *);
+int wscrl(WINDOW *, int);
+int wsetscrreg(WINDOW *, int, int);
+int wstandout(WINDOW *);
+int wstandend(WINDOW *);
+void wsyncdown(WINDOW *);
+void wsyncup(WINDOW *);
+void wtimeout(WINDOW *, int);
+int wtouchln(WINDOW *, int, int, int);
+int wvline(WINDOW *, chtype, int);
+int tigetflag(char *);
+int tigetnum(char *);
+char * tigetstr(char *);
+int putp(const char *);
+char * tparm(const char *, ...);
+int getattrs(const WINDOW *);
+int getcurx(const WINDOW *);
+int getcury(const WINDOW *);
+int getbegx(const WINDOW *);
+int getbegy(const WINDOW *);
+int getmaxx(const WINDOW *);
+int getmaxy(const WINDOW *);
+int getparx(const WINDOW *);
+int getpary(const WINDOW *);
+
+int getmouse(MEVENT *);
+int ungetmouse(MEVENT *);
+mmask_t mousemask(mmask_t, mmask_t *);
+bool wenclose(const WINDOW *, int, int);
+int mouseinterval(int);
+
+void setsyx(int y, int x);
+const char *unctrl(chtype);
+int use_default_colors(void);
+
+int has_key(int);
+bool is_term_resized(int, int);
+
+#define _m_STRICT_SYSV_CURSES ...
+#define _m_NCURSES_MOUSE_VERSION ...
+#define _m_NetBSD ...
+int _m_ispad(WINDOW *);
+
+chtype acs_map[];
+
+// For _curses_panel:
+
+typedef ... PANEL;
+
+WINDOW *panel_window(const PANEL *);
+void update_panels(void);
+int hide_panel(PANEL *);
+int show_panel(PANEL *);
+int del_panel(PANEL *);
+int top_panel(PANEL *);
+int bottom_panel(PANEL *);
+PANEL *new_panel(WINDOW *);
+PANEL *panel_above(const PANEL *);
+PANEL *panel_below(const PANEL *);
+int set_panel_userptr(PANEL *, void *);
+const void *panel_userptr(const PANEL *);
+int move_panel(PANEL *, int, int);
+int replace_panel(PANEL *,WINDOW *);
+int panel_hidden(const PANEL *);
+
+void _m_getsyx(int *yx);
+""")
+
+
+if __name__ == "__main__":
+    ffi.compile()
diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py
--- a/lib_pypy/_functools.py
+++ b/lib_pypy/_functools.py
@@ -32,16 +32,16 @@
     partial(func, *args, **keywords) - new function with partial application
     of the given arguments and keywords.
     """
-
-    def __init__(self, *args, **keywords):
-        if not args:
-            raise TypeError('__init__() takes at least 2 arguments (1 given)')
-        func, args = args[0], args[1:]
+    def __init__(*args, **keywords):
+        if len(args) < 2:
+            raise TypeError('__init__() takes at least 2 arguments (%d given)'
+                            % len(args))
+        self, func, args = args[0], args[1], args[2:]
         if not callable(func):
             raise TypeError("the first argument must be callable")
         self._func = func
         self._args = args
-        self._keywords = keywords or None
+        self._keywords = keywords
 
     def __delattr__(self, key):
         if key == '__dict__':
@@ -61,9 +61,9 @@
         return self._keywords
 
     def __call__(self, *fargs, **fkeywords):
-        if self.keywords is not None:
-            fkeywords = dict(self.keywords, **fkeywords)
-        return self.func(*(self.args + fargs), **fkeywords)
+        if self._keywords:
+            fkeywords = dict(self._keywords, **fkeywords)
+        return self._func(*(self._args + fargs), **fkeywords)
 
     def __repr__(self):
         cls = type(self)
@@ -84,10 +84,13 @@
                 ('_func', '_args', '_keywords'))
         if len(d) == 0:
             d = None
-        return (type(self), (self.func,),
-                (self.func, self.args, self.keywords, d))
+        return (type(self), (self._func,),
+                (self._func, self._args, self._keywords, d))
 
     def __setstate__(self, state):
-        self._func, self._args, self._keywords, d = state
+        func, args, keywords, d = state
         if d is not None:
             self.__dict__.update(d)
+        self._func = func
+        self._args = args
+        self._keywords = keywords
diff --git a/lib_pypy/_gdbm.py b/lib_pypy/_gdbm.py
--- a/lib_pypy/_gdbm.py
+++ b/lib_pypy/_gdbm.py
@@ -1,72 +1,6 @@
-import cffi, os, sys
-
-ffi = cffi.FFI()
-ffi.cdef('''
-#define GDBM_READER ...
-#define GDBM_WRITER ...
-#define GDBM_WRCREAT ...
-#define GDBM_NEWDB ...
-#define GDBM_FAST ...
-#define GDBM_SYNC ...
-#define GDBM_NOLOCK ...
-#define GDBM_REPLACE ...
-
-void* gdbm_open(char *, int, int, int, void (*)());
-void gdbm_close(void*);
-
-typedef struct {
-    char *dptr;
-    int   dsize;
-} datum;
-
-datum gdbm_fetch(void*, datum);
-datum pygdbm_fetch(void*, char*, int);
-int gdbm_delete(void*, datum);
-int gdbm_store(void*, datum, datum, int);
-int gdbm_exists(void*, datum);
-int pygdbm_exists(void*, char*, int);
-
-int gdbm_reorganize(void*);
-
-datum gdbm_firstkey(void*);
-datum gdbm_nextkey(void*, datum);
-void gdbm_sync(void*);
-
-char* gdbm_strerror(int);
-int gdbm_errno;
-
-void free(void*);
-''')
-
-try:
-    verify_code = '''
-    #include "gdbm.h"
-
-    static datum pygdbm_fetch(GDBM_FILE gdbm_file, char *dptr, int dsize) {
-        datum key = {dptr, dsize};
-        return gdbm_fetch(gdbm_file, key);
-    }
-
-    static int pygdbm_exists(GDBM_FILE gdbm_file, char *dptr, int dsize) {
-        datum key = {dptr, dsize};
-        return gdbm_exists(gdbm_file, key);
-    }
-    
-    '''
-    if sys.platform.startswith('freebsd'):
-        import os.path
-        _localbase = os.environ.get('LOCALBASE', '/usr/local')
-        lib = ffi.verify(verify_code, libraries=['gdbm'],
-             include_dirs=[os.path.join(_localbase, 'include')],
-             library_dirs=[os.path.join(_localbase, 'lib')]
-        )
-    else:
-        lib = ffi.verify(verify_code, libraries=['gdbm'])
-except cffi.VerificationError as e:
-    # distutils does not preserve the actual message,
-    # but the verification is simple enough that the
-    # failure must be due to missing gdbm dev libs
-    raise ImportError('%s: %s' %(e.__class__.__name__, e))
+from _gdbm_cffi import ffi, lib    # generated by _gdbm_build.py
+import sys, os, threading
+_lock = threading.Lock()
 
 class error(IOError):
     pass
@@ -87,59 +21,71 @@
     return {'dptr': ffi.new("char[]", key), 'dsize': len(key)}
 
 class gdbm(object):
-    ll_dbm = None
+    __ll_dbm = None
+
+    # All public methods need to acquire the lock; all private methods
+    # assume the lock is already held.  Thus public methods cannot call
+    # other public methods.
 
     def __init__(self, filename, iflags, mode):
-        res = lib.gdbm_open(filename, 0, iflags, mode, ffi.NULL)
-        self.size = -1
-        if not res:
-            self._raise_from_errno()
-        self.ll_dbm = res
+        with _lock:
+            res = lib.gdbm_open(filename, 0, iflags, mode, ffi.NULL)
+            self.__size = -1
+            if not res:
+                self.__raise_from_errno()
+            self.__ll_dbm = res
 
     def close(self):
-        if self.ll_dbm:
-            lib.gdbm_close(self.ll_dbm)
-            self.ll_dbm = None
+        with _lock:
+            if self.__ll_dbm:
+                lib.gdbm_close(self.__ll_dbm)
+                self.__ll_dbm = None
 
-    def _raise_from_errno(self):
+    def __raise_from_errno(self):
         if ffi.errno:
             raise error(ffi.errno, os.strerror(ffi.errno))
         raise error(lib.gdbm_errno, lib.gdbm_strerror(lib.gdbm_errno))
 
     def __len__(self):
-        if self.size < 0:
-            self.size = len(self.keys())


More information about the pypy-commit mailing list