[pypy-commit] pypy reflex-support: o) merge default into branch

wlav noreply at buildbot.pypy.org
Thu Aug 25 01:03:21 CEST 2011


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r46762:eac18d3045db
Date: 2011-08-24 14:37 -0700
http://bitbucket.org/pypy/pypy/changeset/eac18d3045db/

Log:	o) merge default into branch o) keep private date members private
	o) offset calculations for method calls o) (coding) convention
	fixes

diff --git a/ctypes_configure/configure.py b/ctypes_configure/configure.py
--- a/ctypes_configure/configure.py
+++ b/ctypes_configure/configure.py
@@ -559,7 +559,9 @@
 C_HEADER = """
 #include <stdio.h>
 #include <stddef.h>   /* for offsetof() */
-#include <stdint.h>   /* FreeBSD: for uint64_t */
+#ifndef _WIN32
+#  include <stdint.h>   /* FreeBSD: for uint64_t */
+#endif
 
 void dump(char* key, int value) {
     printf("%s: %d\\n", key, value);
diff --git a/lib-python/modified-2.7/distutils/unixccompiler.py b/lib-python/modified-2.7/distutils/unixccompiler.py
--- a/lib-python/modified-2.7/distutils/unixccompiler.py
+++ b/lib-python/modified-2.7/distutils/unixccompiler.py
@@ -324,7 +324,7 @@
             # On OSX users can specify an alternate SDK using
             # '-isysroot', calculate the SDK root if it is specified
             # (and use it further on)
-            cflags = sysconfig.get_config_var('CFLAGS')
+            cflags = sysconfig.get_config_var('CFLAGS') or ''
             m = re.search(r'-isysroot\s+(\S+)', cflags)
             if m is None:
                 sysroot = '/'
diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py
--- a/lib_pypy/_subprocess.py
+++ b/lib_pypy/_subprocess.py
@@ -35,7 +35,7 @@
 _DuplicateHandle.restype = ctypes.c_int
     
 _WaitForSingleObject = _kernel32.WaitForSingleObject
-_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_int]
+_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_uint]
 _WaitForSingleObject.restype = ctypes.c_int
 
 _GetExitCodeProcess = _kernel32.GetExitCodeProcess
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -33,7 +33,7 @@
 from pyrepl.unix_console import UnixConsole, _error
 
 
-ENCODING = 'latin1'     # XXX hard-coded
+ENCODING = sys.getfilesystemencoding() or 'latin1'     # XXX review
 
 __all__ = ['add_history',
            'clear_history',
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
@@ -287,7 +287,14 @@
   never a dictionary as it sometimes is in CPython. Assigning to
   ``__builtins__`` has no effect.
 
-* object identity of immutable keys in dictionaries is not necessarily preserved.
-  Never compare immutable objects with ``is``.
+* Do not compare immutable objects with ``is``.  For example on CPython
+  it is true that ``x is 0`` works, i.e. does the same as ``type(x) is
+  int and x == 0``, but it is so by accident.  If you do instead
+  ``x is 1000``, then it stops working, because 1000 is too large and
+  doesn't come from the internal cache.  In PyPy it fails to work in
+  both cases, because we have no need for a cache at all.
+
+* Also, object identity of immutable keys in dictionaries is not necessarily
+  preserved.
 
 .. include:: _ref.txt
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -73,7 +73,7 @@
 
     $ curl -O http://python-distribute.org/distribute_setup.py
 
-    $ curl -O https://github.com/pypa/pip/raw/master/contrib/get-pip.py
+    $ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
 
     $ ./pypy-1.6/bin/pypy distribute_setup.py
 
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -571,6 +571,7 @@
                 pure = '_pure'
         else:
             pure = ''
+        self.check_field_access(v_inst.concretetype.TO)
         argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
@@ -604,6 +605,7 @@
             return [SpaceOperation('-live-', [], None),
                     SpaceOperation('setfield_vable_%s' % kind,
                                    [v_inst, descr, v_value], None)]
+        self.check_field_access(v_inst.concretetype.TO)
         argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
@@ -616,6 +618,22 @@
         return (op.args[1].value == 'typeptr' and
                 op.args[0].concretetype.TO._hints.get('typeptr'))
 
+    def check_field_access(self, STRUCT):
+        # check against a GcStruct with a nested GcStruct as a first argument
+        # but which is not an object at all; see metainterp/test/test_loop,
+        # test_regular_pointers_in_short_preamble.
+        if not isinstance(STRUCT, lltype.GcStruct):
+            return
+        if STRUCT._first_struct() == (None, None):
+            return
+        PARENT = STRUCT
+        while not PARENT._hints.get('typeptr'):
+            _, PARENT = PARENT._first_struct()
+            if PARENT is None:
+                raise NotImplementedError("%r is a GcStruct using nesting but "
+                                          "not inheriting from object" %
+                                          (STRUCT,))
+
     def get_vinfo(self, v_virtualizable):
         if self.callcontrol is None:      # for tests
             return None
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -38,9 +38,9 @@
     return a.typeannotation(t)
 
 def annotate(func, values, inline=None, backendoptimize=True,
-             type_system="lltype", listcomp=False):
+             type_system="lltype"):
     # build the normal ll graphs for ll_function
-    t = TranslationContext(list_comprehension_operations=listcomp)
+    t = TranslationContext()
     annpolicy = AnnotatorPolicy()
     annpolicy.allow_someobjects = False
     a = t.buildannotator(policy=annpolicy)
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1014,3 +1014,13 @@
         assert op1.opname == 'jit_force_quasi_immutable'
         assert op1.args[0] == v_x
         assert op1.args[1] == ('fielddescr', STRUCT, 'mutate_x')
+
+def test_no_gcstruct_nesting_outside_of_OBJECT():
+    PARENT = lltype.GcStruct('parent')
+    STRUCT = lltype.GcStruct('struct', ('parent', PARENT),
+                                       ('x', lltype.Signed))
+    v_x = varoftype(lltype.Ptr(STRUCT))
+    op = SpaceOperation('getfield', [v_x, Constant('x', lltype.Void)],
+                        varoftype(lltype.Signed))
+    tr = Transformer(None, None)
+    raises(NotImplementedError, tr.rewrite_operation, op)
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -42,7 +42,7 @@
         enable_opts = ALL_OPTS_DICT
 
     func._jit_unroll_safe_ = True
-    rtyper = support.annotate(func, values, type_system=type_system, listcomp=kwds.get("listcomp", False))
+    rtyper = support.annotate(func, values, type_system=type_system)
     graphs = rtyper.annotator.translator.graphs
     testself.all_graphs = graphs
     result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
diff --git a/pypy/jit/metainterp/test/test_loop.py b/pypy/jit/metainterp/test/test_loop.py
--- a/pypy/jit/metainterp/test/test_loop.py
+++ b/pypy/jit/metainterp/test/test_loop.py
@@ -801,8 +801,6 @@
         res = self.meta_interp(f, [200])        
 
     def test_regular_pointers_in_short_preamble(self):
-        # XXX do we really care about this case?  If not, we should
-        # at least detect it and complain during codewriter/jtransform
         from pypy.rpython.lltypesystem import lltype
         BASE = lltype.GcStruct('BASE')
         A = lltype.GcStruct('A', ('parent', BASE), ('val', lltype.Signed))
@@ -829,9 +827,8 @@
                 assert n>0 and m>0
                 i += j
             return sa
-        expected = f(20, 10, 1)
-        res = self.meta_interp(f, [20, 10, 1])
-        assert res == expected
+        # This is detected as invalid by the codewriter, for now
+        py.test.raises(NotImplementedError, self.meta_interp, f, [20, 10, 1])
 
     def test_unerased_pointers_in_short_preamble(self):
         from pypy.rlib.rerased import new_erasing_pair
diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -37,14 +37,14 @@
 set_opt_level(config, level='jit')
 config.objspace.allworkingmodules = False
 config.objspace.usemodules.pypyjit = True
-config.objspace.usemodules.array = True
+config.objspace.usemodules.array = False
 config.objspace.usemodules._weakref = True
 config.objspace.usemodules._sre = False
 config.objspace.usemodules._lsprof = True
 #
 config.objspace.usemodules._ffi = True
 config.objspace.usemodules.cppyy = True
-config.objspace.usemodules.micronumpy = True
+config.objspace.usemodules.micronumpy = False
 #
 set_pypy_opt_level(config, level='jit')
 
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -91,7 +91,7 @@
 
 def unpack_simple_shape(space, w_shape):
     # 'w_shape' must be either a letter or a tuple (struct, 1).
-    if space.isinstance_w(w_shape, space.w_str):
+    if space.is_true(space.isinstance(w_shape, space.w_str)):
         letter = space.str_w(w_shape)
         return letter2tp(space, letter)
     else:
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ b/pypy/module/cppyy/capi/reflex_capi.py
@@ -206,6 +206,11 @@
     [C_TYPEHANDLE, rffi.INT], rffi.SIZE_T,
     compilation_info=eci)
 
+c_is_publicdata = rffi.llexternal(
+    "cppyy_is_publicdata",
+    [C_TYPEHANDLE, rffi.INT], rffi.INT,
+    compilation_info=eci)
+
 c_is_staticdata = rffi.llexternal(
     "cppyy_is_staticdata",
     [C_TYPEHANDLE, rffi.INT], rffi.INT,
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -20,7 +20,7 @@
         return cppinstance.rawobject
     return lltype.nullptr(rffi.VOIDP.TO)
 
-def _direct_ptradd(ptr, offset):
+def _direct_ptradd(ptr, offset):        # TODO: factor out with interp_cppyy.py
     address = rffi.cast(rffi.CCHARP, ptr)
     return rffi.cast(rffi.CCHARP, lltype.direct_ptradd(address, offset))
 
diff --git a/pypy/module/cppyy/include/capi.h b/pypy/module/cppyy/include/capi.h
--- a/pypy/module/cppyy/include/capi.h
+++ b/pypy/module/cppyy/include/capi.h
@@ -67,6 +67,7 @@
     size_t cppyy_data_member_offset(cppyy_typehandle_t handle, int data_member_index);
 
     /* data member properties */
+    int cppyy_is_publicdata(cppyy_typehandle_t handle, int data_member_index);
     int cppyy_is_staticdata(cppyy_typehandle_t handle, int data_member_index);
 
     /* misc helper */
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -17,6 +17,10 @@
 
 NULL_VOIDP  = lltype.nullptr(rffi.VOIDP.TO)
 
+def _direct_ptradd(ptr, offset):        # TODO: factor out with convert.py
+    address = rffi.cast(rffi.CCHARP, ptr)
+    return rffi.cast(rffi.VOIDP, lltype.direct_ptradd(address, offset))
+
 @unwrap_spec(name=str)
 def load_dictionary(space, name):
     try:
@@ -104,6 +108,7 @@
         self.methgetter = methgetter
         self._libffifunc_cache = {}
 
+    @jit.unroll_safe
     def call(self, cppthis, w_type, args_w):
         assert lltype.typeOf(cppthis) == rffi.VOIDP
         if self.executor is None:
@@ -225,10 +230,12 @@
 
 
 class W_CPPOverload(Wrappable):
-    _immutable_fields_ = ["func_name", "functions[*]"]
+    _immutable_fields_ = ["scope_handle", "func_name", "functions[*]"]
 
-    def __init__(self, space, func_name, functions):
+    def __init__(self, space, scope_handle, func_name, functions):
         self.space = space
+        assert lltype.typeOf(scope_handle) == rffi.VOIDP
+        self.scope_handle = scope_handle
         self.func_name = func_name
         self.functions = debug.make_sure_not_resized(functions)
 
@@ -243,7 +250,9 @@
         cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=True)
         if cppinstance is not None:
             cppinstance._nullcheck()
-            cppthis = cppinstance.rawobject
+            offset = capi.c_base_offset(
+                cppinstance.cppclass.handle, self.scope_handle, cppinstance.rawobject)
+            cppthis = _direct_ptradd(cppinstance.rawobject, offset)
         else:
             cppthis = NULL_VOIDP
         assert lltype.typeOf(cppthis) == rffi.VOIDP
@@ -283,9 +292,10 @@
 class W_CPPDataMember(Wrappable):
     _immutable_fields_ = ["scope_handle", "converter", "offset", "_is_static"]
 
-    def __init__(self, space, scope, type_name, offset, is_static):
+    def __init__(self, space, scope_handle, type_name, offset, is_static):
         self.space = space
-        self.scope_handle = scope.handle
+        assert lltype.typeOf(scope_handle) == rffi.VOIDP
+        self.scope_handle = scope_handle
         self.converter = converter.get_converter(self.space, type_name)
         self.offset = offset
         self._is_static = is_static
@@ -354,7 +364,7 @@
                 overload = args_temp.setdefault(pymethod_name, [])
                 overload.append(cppfunction)
         for name, functions in args_temp.iteritems():
-            overload = W_CPPOverload(self.space, name, functions[:])
+            overload = W_CPPOverload(self.space, self.handle, name, functions[:])
             self.methods[name] = overload
 
     def get_method_names(self):
@@ -404,11 +414,13 @@
     def _find_data_members(self):
         num_data_members = capi.c_num_data_members(self.handle)
         for i in range(num_data_members):
+            if not capi.c_is_publicdata(self.handle, i):
+                continue
             data_member_name = capi.charp2str_free(capi.c_data_member_name(self.handle, i))
             if not data_member_name in self.data_members:
                 type_name = capi.charp2str_free(capi.c_data_member_type(self.handle, i))
                 offset = capi.c_data_member_offset(self.handle, i)
-                data_member = W_CPPDataMember(self.space, self, type_name, offset, True)
+                data_member = W_CPPDataMember(self.space, self.handle, type_name, offset, True)
                 self.data_members[data_member_name] = data_member
 
     def update(self):
@@ -454,11 +466,13 @@
     def _find_data_members(self):
         num_data_members = capi.c_num_data_members(self.handle)
         for i in range(num_data_members):
+            if not capi.c_is_publicdata(self.handle, i):
+                continue
             data_member_name = capi.charp2str_free(capi.c_data_member_name(self.handle, i))
             type_name = capi.charp2str_free(capi.c_data_member_type(self.handle, i))
             offset = capi.c_data_member_offset(self.handle, i)
             is_static = bool(capi.c_is_staticdata(self.handle, i))
-            data_member = W_CPPDataMember(self.space, self, type_name, offset, is_static)
+            data_member = W_CPPDataMember(self.space, self.handle, type_name, offset, is_static)
             self.data_members[data_member_name] = data_member
 
     def is_namespace(self):
diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
--- a/pypy/module/cppyy/src/reflexcwrapper.cxx
+++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
@@ -61,7 +61,7 @@
                     size_t offset = ibase->first.Offset(o.Address());
                     return offset;
                 } else
-                    return ibase->first.Offset(0);
+                    return ibase->first.Offset(address);
             }
         }
 
@@ -350,6 +350,12 @@
 }
 
 
+int cppyy_is_publicdata(cppyy_typehandle_t handle, int data_member_index) {
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.DataMemberAt(data_member_index);
+    return m.IsPublic();
+}
+
 int cppyy_is_staticdata(cppyy_typehandle_t handle, int data_member_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.DataMemberAt(data_member_index);
diff --git a/pypy/module/cppyy/test/advancedcpp.cxx b/pypy/module/cppyy/test/advancedcpp.cxx
--- a/pypy/module/cppyy/test/advancedcpp.cxx
+++ b/pypy/module/cppyy/test/advancedcpp.cxx
@@ -62,3 +62,9 @@
 
 // for life-line testing
 int some_class_with_data::some_data::s_num_data = 0;
+
+
+// for testing multiple inheritance
+multi1::~multi1() {}
+multi2::~multi2() {}
+multi::~multi() {}
diff --git a/pypy/module/cppyy/test/advancedcpp.h b/pypy/module/cppyy/test/advancedcpp.h
--- a/pypy/module/cppyy/test/advancedcpp.h
+++ b/pypy/module/cppyy/test/advancedcpp.h
@@ -280,7 +280,7 @@
 
 
 //===========================================================================
-class pointer_pass {             // for testing passing of void*'s
+class pointer_pass {               // for testing passing of void*'s
 public:
     long gime_address_ptr(void* obj) {
         return (long)obj;
@@ -294,3 +294,36 @@
         return (long)obj;
     }
 };
+
+
+//===========================================================================
+class multi1 {                     // for testing multiple inheritance
+public:
+    multi1(int val) : m_int(val) {}
+    virtual ~multi1();
+    int get_multi1_int() { return m_int; }
+
+private:
+    int m_int;
+};
+
+class multi2 {
+public:
+    multi2(int val) : m_int(val) {}
+    virtual ~multi2();
+    int get_multi2_int() { return m_int; }
+
+private:
+    int m_int;
+};
+
+class multi : public multi1, public multi2 {
+public:
+    multi(int val1, int val2, int val3) :
+        multi1(val1), multi2(val2), m_int(val3) {}
+    virtual ~multi();
+    int get_my_own_int() { return m_int; }
+
+private:
+    int m_int;
+};
diff --git a/pypy/module/cppyy/test/advancedcpp.xml b/pypy/module/cppyy/test/advancedcpp.xml
--- a/pypy/module/cppyy/test/advancedcpp.xml
+++ b/pypy/module/cppyy/test/advancedcpp.xml
@@ -29,4 +29,6 @@
 
   <class name="pointer_pass" />
 
+  <class pattern="multi*" />
+
 </lcgdict>
diff --git a/pypy/module/cppyy/test/test_advancedcpp.py b/pypy/module/cppyy/test/test_advancedcpp.py
--- a/pypy/module/cppyy/test/test_advancedcpp.py
+++ b/pypy/module/cppyy/test/test_advancedcpp.py
@@ -322,7 +322,7 @@
         assert gbl.get_d(d) == 44
         d.destruct()
 
-    def test08_void_pointer_passing( self ):
+    def test08_void_pointer_passing(self):
         """Test passing of variants of void pointer arguments"""
 
         import cppyy
@@ -336,7 +336,7 @@
         assert cppyy.addressof(o) == pp.gime_address_ptr_ptr(o)
         assert cppyy.addressof(o) == pp.gime_address_ptr_ref(o)
 
-    def test09_opaque_pointer_assing( self ):
+    def test09_opaque_pointer_assing(self):
         """Test passing around of opaque pointers"""
 
         import cppyy
@@ -356,3 +356,22 @@
         assert o == cppyy.bind_object(addr, type(o))
         assert o == cppyy.bind_object(addr, o.__class__)
         #assert o == cppyy.bind_object(addr, "some_concrete_class")
+
+    def test10_multi_methods(self):
+        """Test calling of methods from multiple inheritance"""
+
+        import cppyy
+        multi = cppyy.gbl.multi
+
+        assert cppyy.gbl.multi1 is multi.__bases__[0]
+        assert cppyy.gbl.multi2 is multi.__bases__[1]
+
+        dict_keys = multi.__dict__.keys()
+        assert dict_keys.count('get_my_own_int') == 1
+        assert dict_keys.count('get_multi1_int') == 0
+        assert dict_keys.count('get_multi2_int') == 0
+
+        m = multi(1, 2, 3)
+        assert m.get_multi1_int() == 1
+        assert m.get_multi2_int() == 2
+        assert m.get_my_own_int() == 3
diff --git a/pypy/module/cppyy/test/test_datatypes.py b/pypy/module/cppyy/test/test_datatypes.py
--- a/pypy/module/cppyy/test/test_datatypes.py
+++ b/pypy/module/cppyy/test/test_datatypes.py
@@ -24,13 +24,13 @@
             import cppyy
             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
-    def test0_load_reflection_cache(self):
+    def test01_load_reflection_cache(self):
         """Test whether loading a refl. info twice results in the same object."""
         import cppyy
         lib2 = cppyy.load_reflection_info(self.test_dct)
         assert self.datatypes is lib2
 
-    def test1_instance_data_read_access(self):
+    def test02_instance_data_read_access(self):
         """Test read access to instance public data and verify values"""
 
         import cppyy, sys
@@ -104,7 +104,7 @@
 
         c.destruct()
 
-    def test2_instance_data_write_access(self):
+    def test03_instance_data_write_access(self):
         """Test write access to instance public data and verify values"""
 
         import cppyy, sys
@@ -185,7 +185,20 @@
 
         c.destruct()
 
-    def test3_class_read_access(self):
+    def test04_respect_privacy(self):
+        """Test that privacy settings are respected"""
+
+        import cppyy
+        cppyy_test_data = cppyy.gbl.cppyy_test_data
+
+        c = cppyy_test_data()
+        assert isinstance(c, cppyy_test_data)
+
+        raises(AttributeError, getattr, c, 'm_owns_arrays')
+
+        c.destruct()
+
+    def test05_class_read_access(self):
         """Test read access to class public data and verify values"""
 
         import cppyy, sys
@@ -222,7 +235,7 @@
 
         c.destruct()
 
-    def test4_class_data_write_access(self):
+    def test06_class_data_write_access(self):
         """Test write access to class public data and verify values"""
 
         import cppyy, sys
@@ -286,7 +299,7 @@
 
         c.destruct()
 
-    def test5_range_access(self):
+    def test07_range_access(self):
         """Test the ranges of integer types"""
 
         import cppyy, sys
@@ -302,7 +315,7 @@
 
         c.destruct()
 
-    def test6_type_conversions(self):
+    def test08_type_conversions(self):
         """Test conversions between builtin types"""
 
         import cppyy, sys
diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -1,7 +1,7 @@
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rlib.objectmodel import specialize, instantiate
 from pypy.rlib import rarithmetic, jit
-from pypy.rpython.lltypesystem import rffi
+from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
 
 from pypy.module.cppyy import interp_cppyy
@@ -28,6 +28,12 @@
     def getname(self, space, name):
         return self.name
 
+ at jit.dont_look_inside
+def _opaque_direct_ptradd(ptr, offset):
+    address = rffi.cast(rffi.CCHARP, ptr)
+    return rffi.cast(rffi.VOIDP, lltype.direct_ptradd(address, offset))
+interp_cppyy._direct_ptradd = _opaque_direct_ptradd
+
 class FakeUserDelAction(object):
     def __init__(self, space):
         pass
@@ -141,6 +147,10 @@
             return 7
         f()
         space = FakeSpace()
+        # This test is not that constrained anymore, now that there are left-over
+        # calls (to opaque ptr add (above) and to capi offset (the latter could be
+        # eaten by the JIT, since it is elidable ... )), but it's the best that
+        # can be done for now.
         result = self.meta_interp(f, [], listops=True, backendopt=True, listcomp=True)
-        self.check_loops(call=0, call_release_gil=1)
+        self.check_loops(call=2, call_release_gil=1)
         self.check_loops(getarrayitem_gc_pure=0, everywhere=True)
diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py
--- a/pypy/module/cpyext/eval.py
+++ b/pypy/module/cpyext/eval.py
@@ -1,11 +1,16 @@
 from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
-    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP)
+    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP,
+    cpython_struct)
 from pypy.module.cpyext.pyobject import PyObject, borrow_from
 from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno
 from pypy.module.__builtin__ import compiling
 
+PyCompilerFlags = cpython_struct(
+    "PyCompilerFlags", ())
+PyCompilerFlagsPtr = lltype.Ptr(PyCompilerFlags)
+
 @cpython_api([PyObject, PyObject, PyObject], PyObject)
 def PyEval_CallObjectWithKeywords(space, w_obj, w_arg, w_kwds):
     return space.call(w_obj, w_arg, w_kwds)
@@ -69,7 +74,7 @@
 Py_file_input = 257
 Py_eval_input = 258
 
-def run_string(space, source, filename, start, w_globals, w_locals):
+def compile_string(space, source, filename, start):
     w_source = space.wrap(source)
     start = rffi.cast(lltype.Signed, start)
     if start == Py_file_input:
@@ -80,8 +85,11 @@
         mode = 'single'
     else:
         raise OperationError(space.w_ValueError, space.wrap(
-            "invalid mode parameter for PyRun_String"))
-    w_code = compiling.compile(space, w_source, filename, mode)
+            "invalid mode parameter for compilation"))
+    return compiling.compile(space, w_source, filename, mode)
+
+def run_string(space, source, filename, start, w_globals, w_locals):
+    w_code = compile_string(space, source, filename, start)
     return compiling.eval(space, w_code, w_globals, w_locals)
 
 @cpython_api([CONST_STRING], rffi.INT_real, error=-1)
@@ -140,3 +148,19 @@
         pi[0] = space.getindex_w(w_obj, None)
     return 1
 
+ at cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real, PyCompilerFlagsPtr],
+             PyObject)
+def Py_CompileStringFlags(space, source, filename, start, flags):
+    """Parse and compile the Python source code in str, returning the
+    resulting code object.  The start token is given by start; this
+    can be used to constrain the code which can be compiled and should
+    be Py_eval_input, Py_file_input, or Py_single_input.  The filename
+    specified by filename is used to construct the code object and may
+    appear in tracebacks or SyntaxError exception messages.  This
+    returns NULL if the code cannot be parsed or compiled."""
+    source = rffi.charp2str(source)
+    filename = rffi.charp2str(filename)
+    if flags:
+        raise OperationError(space.w_NotImplementedError, space.wrap(
+                "cpyext Py_CompileStringFlags does not accept flags"))
+    return compile_string(space, source, filename, start)
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -2,9 +2,11 @@
 from pypy.module.cpyext.api import (
     generic_cpy_call, cpython_api, PyObject, CONST_STRING)
 from pypy.module.cpyext.pyobject import borrow_from
-from pypy.rpython.lltypesystem import rffi
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.module import Module
+from pypy.interpreter.pycode import PyCode
+from pypy.module.imp import importing
 
 @cpython_api([PyObject], PyObject)
 def PyImport_Import(space, w_name):
@@ -80,3 +82,44 @@
     w_modulesDict = space.sys.get('modules')
     return borrow_from(None, w_modulesDict)
 
+ at cpython_api([rffi.CCHARP, PyObject], PyObject)
+def PyImport_ExecCodeModule(space, name, w_code):
+    """Given a module name (possibly of the form package.module) and a code
+    object read from a Python bytecode file or obtained from the built-in
+    function compile(), load the module.  Return a new reference to the module
+    object, or NULL with an exception set if an error occurred.  Before Python
+    2.4, the module could still be created in error cases.  Starting with Python
+    2.4, name is removed from sys.modules in error cases, and even if name was
+    already in sys.modules on entry to PyImport_ExecCodeModule().  Leaving
+    incompletely initialized modules in sys.modules is dangerous, as imports of
+    such modules have no way to know that the module object is an unknown (and
+    probably damaged with respect to the module author's intents) state.
+
+    The module's __file__ attribute will be set to the code object's
+    co_filename.
+
+    This function will reload the module if it was already imported.  See
+    PyImport_ReloadModule() for the intended way to reload a module.
+
+    If name points to a dotted name of the form package.module, any package
+    structures not already created will still not be created.
+
+    name is removed from sys.modules in error cases."""
+    return PyImport_ExecCodeModuleEx(space, name, w_code,
+                                     lltype.nullptr(rffi.CCHARP.TO))
+
+
+ at cpython_api([rffi.CCHARP, PyObject, rffi.CCHARP], PyObject)
+def PyImport_ExecCodeModuleEx(space, name, w_code, pathname):
+    """Like PyImport_ExecCodeModule(), but the __file__ attribute of
+    the module object is set to pathname if it is non-NULL."""
+    code = space.interp_w(PyCode, w_code)
+    w_name = space.wrap(rffi.charp2str(name))
+    if pathname:
+        pathname = rffi.charp2str(pathname)
+    else:
+        pathname = code.co_filename
+    w_mod = importing.add_module(space, w_name)
+    space.setattr(w_mod, space.wrap('__file__'), space.wrap(pathname))
+    importing.exec_code_module(space, w_mod, code)
+    return w_mod
diff --git a/pypy/module/cpyext/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h
--- a/pypy/module/cpyext/include/pythonrun.h
+++ b/pypy/module/cpyext/include/pythonrun.h
@@ -13,6 +13,12 @@
 
 #define Py_FrozenFlag 0
 
+typedef struct {
+    int cf_flags;  /* bitmask of CO_xxx flags relevant to future */
+} PyCompilerFlags;
+
+#define Py_CompileString(str, filename, start) Py_CompileStringFlags(str, filename, start, NULL)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/presetup.py b/pypy/module/cpyext/presetup.py
--- a/pypy/module/cpyext/presetup.py
+++ b/pypy/module/cpyext/presetup.py
@@ -42,4 +42,4 @@
 patch_distutils()
 
 del sys.argv[0]
-execfile(sys.argv[0])
+execfile(sys.argv[0], {'__file__': sys.argv[0]})
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -14,6 +14,11 @@
 
 @cpython_api([PyObject], PyObject)
 def PySet_New(space, w_iterable):
+    """Return a new set containing objects returned by the iterable.  The
+    iterable may be NULL to create a new empty set.  Return the new set on
+    success or NULL on failure.  Raise TypeError if iterable is not
+    actually iterable.  The constructor is also useful for copying a set
+    (c=set(s))."""
     if w_iterable is None:
         return space.call_function(space.w_set)
     else:
@@ -21,6 +26,15 @@
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
 def PySet_Add(space, w_s, w_obj):
+    """Add key to a set instance.  Does not apply to frozenset
+    instances.  Return 0 on success or -1 on failure. Raise a TypeError if
+    the key is unhashable. Raise a MemoryError if there is no room to grow.
+    Raise a SystemError if set is an not an instance of set or its
+    subtype.
+
+    Now works with instances of frozenset or its subtypes.
+    Like PyTuple_SetItem() in that it can be used to fill-in the
+    values of brand new frozensets before they are exposed to other code."""
     if not PySet_Check(space, w_s):
         PyErr_BadInternalCall(space)
     space.call_method(w_s, 'add', w_obj)
@@ -28,6 +42,12 @@
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
 def PySet_Discard(space, w_s, w_obj):
+    """Return 1 if found and removed, 0 if not found (no action taken), and -1 if an
+    error is encountered.  Does not raise KeyError for missing keys.  Raise a
+    TypeError if the key is unhashable.  Unlike the Python discard()
+    method, this function does not automatically convert unhashable sets into
+    temporary frozensets. Raise PyExc_SystemError if set is an not an
+    instance of set or its subtype."""
     if not PySet_Check(space, w_s):
         PyErr_BadInternalCall(space)
     space.call_method(w_s, 'discard', w_obj)
@@ -36,11 +56,25 @@
 
 @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
 def PySet_GET_SIZE(space, w_s):
+    """Macro form of PySet_Size() without error checking."""
     return space.int_w(space.len(w_s))
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PySet_Size(space, ref):
+    """Return the length of a set or frozenset object. Equivalent to
+    len(anyset).  Raises a PyExc_SystemError if anyset is not a set, frozenset,
+    or an instance of a subtype."""
     if not PySet_Check(space, ref):
         raise OperationError(space.w_TypeError,
                              space.wrap("expected set object"))
     return PySet_GET_SIZE(space, ref)
+
+ at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
+def PySet_Contains(space, w_obj, w_key):
+    """Return 1 if found, 0 if not found, and -1 if an error is encountered.  Unlike
+    the Python __contains__() method, this function does not automatically
+    convert unhashable sets into temporary frozensets.  Raise a TypeError if
+    the key is unhashable. Raise PyExc_SystemError if anyset is not a
+    set, frozenset, or an instance of a subtype."""
+    w_res = space.contains(w_obj, w_key)
+    return space.int_w(w_res)
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -1048,37 +1048,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, PyObject], PyObject)
-def PyImport_ExecCodeModule(space, name, co):
-    """Given a module name (possibly of the form package.module) and a code
-    object read from a Python bytecode file or obtained from the built-in
-    function compile(), load the module.  Return a new reference to the module
-    object, or NULL with an exception set if an error occurred.  Before Python
-    2.4, the module could still be created in error cases.  Starting with Python
-    2.4, name is removed from sys.modules in error cases, and even if name was
-    already in sys.modules on entry to PyImport_ExecCodeModule().  Leaving
-    incompletely initialized modules in sys.modules is dangerous, as imports of
-    such modules have no way to know that the module object is an unknown (and
-    probably damaged with respect to the module author's intents) state.
-
-    The module's __file__ attribute will be set to the code object's
-    co_filename.
-
-    This function will reload the module if it was already imported.  See
-    PyImport_ReloadModule() for the intended way to reload a module.
-
-    If name points to a dotted name of the form package.module, any package
-    structures not already created will still not be created.
-
-    name is removed from sys.modules in error cases."""
-    raise NotImplementedError
-
- at cpython_api([rffi.CCHARP, PyObject, rffi.CCHARP], PyObject)
-def PyImport_ExecCodeModuleEx(space, name, co, pathname):
-    """Like PyImport_ExecCodeModule(), but the __file__ attribute of
-    the module object is set to pathname if it is non-NULL."""
-    raise NotImplementedError
-
 @cpython_api([], lltype.Signed, error=CANNOT_FAIL)
 def PyImport_GetMagicNumber(space):
     """Return the magic number for Python bytecode files (a.k.a. .pyc and
@@ -1958,12 +1927,6 @@
     raise NotImplementedError
 
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PySet_Check(space, p):
-    """Return true if p is a set object or an instance of a subtype.
-    """
-    raise NotImplementedError
-
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyFrozenSet_Check(space, p):
     """Return true if p is a frozenset object or an instance of a
     subtype.
@@ -1989,15 +1952,6 @@
     raise NotImplementedError
 
 @cpython_api([PyObject], PyObject)
-def PySet_New(space, iterable):
-    """Return a new set containing objects returned by the iterable.  The
-    iterable may be NULL to create a new empty set.  Return the new set on
-    success or NULL on failure.  Raise TypeError if iterable is not
-    actually iterable.  The constructor is also useful for copying a set
-    (c=set(s))."""
-    raise NotImplementedError
-
- at cpython_api([PyObject], PyObject)
 def PyFrozenSet_New(space, iterable):
     """Return a new frozenset containing objects returned by the iterable.
     The iterable may be NULL to create a new empty frozenset.  Return the new
@@ -2009,53 +1963,6 @@
     building-up new frozensets with PySet_Add()."""
     raise NotImplementedError
 
- at cpython_api([PyObject], Py_ssize_t, error=-1)
-def PySet_Size(space, anyset):
-    """Return the length of a set or frozenset object. Equivalent to
-    len(anyset).  Raises a PyExc_SystemError if anyset is not a set, frozenset,
-    or an instance of a subtype.
-
-    This function returned an int. This might require changes in
-    your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
- at cpython_api([PyObject], Py_ssize_t, error=-1)
-def PySet_GET_SIZE(space, anyset):
-    """Macro form of PySet_Size() without error checking."""
-    raise NotImplementedError
-
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PySet_Contains(space, anyset, key):
-    """Return 1 if found, 0 if not found, and -1 if an error is encountered.  Unlike
-    the Python __contains__() method, this function does not automatically
-    convert unhashable sets into temporary frozensets.  Raise a TypeError if
-    the key is unhashable. Raise PyExc_SystemError if anyset is not a
-    set, frozenset, or an instance of a subtype."""
-    raise NotImplementedError
-
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PySet_Add(space, set, key):
-    """Add key to a set instance.  Does not apply to frozenset
-    instances.  Return 0 on success or -1 on failure. Raise a TypeError if
-    the key is unhashable. Raise a MemoryError if there is no room to grow.
-    Raise a SystemError if set is an not an instance of set or its
-    subtype.
-
-    Now works with instances of frozenset or its subtypes.
-    Like PyTuple_SetItem() in that it can be used to fill-in the
-    values of brand new frozensets before they are exposed to other code."""
-    raise NotImplementedError
-
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PySet_Discard(space, set, key):
-    """Return 1 if found and removed, 0 if not found (no action taken), and -1 if an
-    error is encountered.  Does not raise KeyError for missing keys.  Raise a
-    TypeError if the key is unhashable.  Unlike the Python discard()
-    method, this function does not automatically convert unhashable sets into
-    temporary frozensets. Raise PyExc_SystemError if set is an not an
-    instance of set or its subtype."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], PyObject)
 def PySet_Pop(space, set):
     """Return a new reference to an arbitrary object in the set, and removes the
@@ -2224,29 +2131,6 @@
     """Return 1 or 0 depending on whether ch is an alphabetic character."""
     raise NotImplementedError
 
- at cpython_api([Py_UNICODE], Py_UNICODE, error=CANNOT_FAIL)
-def Py_UNICODE_TOTITLE(space, ch):
-    """Return the character ch converted to title case."""
-    raise NotImplementedError
-
- at cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
-def Py_UNICODE_TODECIMAL(space, ch):
-    """Return the character ch converted to a decimal positive integer.  Return
-    -1 if this is not possible.  This macro does not raise exceptions."""
-    raise NotImplementedError
-
- at cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
-def Py_UNICODE_TODIGIT(space, ch):
-    """Return the character ch converted to a single digit integer. Return -1 if
-    this is not possible.  This macro does not raise exceptions."""
-    raise NotImplementedError
-
- at cpython_api([Py_UNICODE], rffi.DOUBLE, error=CANNOT_FAIL)
-def Py_UNICODE_TONUMERIC(space, ch):
-    """Return the character ch converted to a double. Return -1.0 if this is not
-    possible.  This macro does not raise exceptions."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP], PyObject)
 def PyUnicode_FromFormat(space, format):
     """Take a C printf()-style format string and a variable number of
@@ -2732,12 +2616,6 @@
     use the default error handling."""
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject], PyObject)
-def PyUnicode_Join(space, separator, seq):
-    """Join a sequence of strings using the given separator and return the resulting
-    Unicode string."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real], rffi.INT_real, error=-1)
 def PyUnicode_Tailmatch(space, str, substr, start, end, direction):
     """Return 1 if substr matches str*[*start:end] at the given tail end
@@ -2800,12 +2678,6 @@
     Py_NE, Py_LT, and Py_LE."""
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject], PyObject)
-def PyUnicode_Format(space, format, args):
-    """Return a new string object from format and args; this is analogous to
-    format % args.  The args argument must be a tuple."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
 def PyUnicode_Contains(space, container, element):
     """Check whether element is contained in container and return true or false
@@ -2992,23 +2864,6 @@
     returns."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject)
-def Py_CompileString(space, str, filename, start):
-    """This is a simplified interface to Py_CompileStringFlags() below, leaving
-    flags set to NULL."""
-    raise NotImplementedError
-
- at cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real, PyCompilerFlags], PyObject)
-def Py_CompileStringFlags(space, str, filename, start, flags):
-    """Parse and compile the Python source code in str, returning the resulting code
-    object.  The start token is given by start; this can be used to constrain the
-    code which can be compiled and should be Py_eval_input,
-    Py_file_input, or Py_single_input.  The filename specified by
-    filename is used to construct the code object and may appear in tracebacks or
-    SyntaxError exception messages.  This returns NULL if the code cannot
-    be parsed or compiled."""
-    raise NotImplementedError
-
 @cpython_api([PyCodeObject, PyObject, PyObject], PyObject)
 def PyEval_EvalCode(space, co, globals, locals):
     """This is a simplified interface to PyEval_EvalCodeEx(), with just
@@ -3076,11 +2931,3 @@
     None, or NULL, this will return NULL and raise TypeError.
     """
     raise NotImplementedError
-
- at cpython_api([PyObject], PyObject)
-def PyWeakref_GET_OBJECT(space, ref):
-    """Similar to PyWeakref_GetObject(), but implemented as a macro that does no
-    error checking.
-    """
-    borrow_from()
-    raise NotImplementedError
diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -221,4 +221,38 @@
             return args
         assert module.call_func(f) == (None,)
         assert module.call_method("text") == 2
-        
+
+    def test_CompileString_and_Exec(self):
+        module = self.import_extension('foo', [
+            ("compile_string", "METH_NOARGS",
+             """
+                return Py_CompileString(
+                   "f = lambda x: x+5", "someFile", Py_file_input);
+             """),
+            ("exec_code", "METH_O",
+             """
+                return PyImport_ExecCodeModule("cpyext_test_modname", args);
+             """),
+            ("exec_code_ex", "METH_O",
+             """
+                return PyImport_ExecCodeModuleEx("cpyext_test_modname",
+                                                 args, "otherFile");
+             """),
+            ])
+        code = module.compile_string()
+        assert code.co_filename == "someFile"
+        assert code.co_name == "<module>"
+
+        mod = module.exec_code(code)
+        assert mod.__name__ == "cpyext_test_modname"
+        assert mod.__file__ == "someFile"
+        print dir(mod)
+        print mod.__dict__
+        assert mod.f(42) == 47
+
+        mod = module.exec_code_ex(code)
+        assert mod.__name__ == "cpyext_test_modname"
+        assert mod.__file__ == "otherFile"
+        print dir(mod)
+        print mod.__dict__
+        assert mod.f(42) == 47
diff --git a/pypy/module/cpyext/test/test_setobject.py b/pypy/module/cpyext/test/test_setobject.py
--- a/pypy/module/cpyext/test/test_setobject.py
+++ b/pypy/module/cpyext/test/test_setobject.py
@@ -27,3 +27,8 @@
         assert api.PySet_Size(w_set) == 5
         api.PySet_Discard(w_set, space.wrap(6))
         assert api.PySet_Size(w_set) == 4
+
+    def test_set_contains(self, space, api):
+        w_set = api.PySet_New(space.wrap([1,2,3,4]))
+        assert api.PySet_Contains(w_set, space.wrap(1))
+        assert not api.PySet_Contains(w_set, space.wrap(0))
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -219,6 +219,24 @@
         assert api.Py_UNICODE_TOUPPER(u'&#65533;') == u'&#65533;'
         assert api.Py_UNICODE_TOUPPER(u'&#65533;') == u'&#65533;'
 
+    def test_TOTITLE(self, space, api):
+        assert api.Py_UNICODE_TOTITLE(u'/') == u'/'
+        assert api.Py_UNICODE_TOTITLE(u'&#65533;') == u'&#65533;'
+        assert api.Py_UNICODE_TOTITLE(u'&#65533;') == u'&#65533;'
+
+    def test_TODECIMAL(self, space, api):
+        assert api.Py_UNICODE_TODECIMAL(u'6') == 6
+        assert api.Py_UNICODE_TODECIMAL(u'A') == -1
+
+    def test_TODIGIT(self, space, api):
+        assert api.Py_UNICODE_TODIGIT(u'6') == 6
+        assert api.Py_UNICODE_TODIGIT(u'A') == -1
+
+    def test_TONUMERIC(self, space, api):
+        assert api.Py_UNICODE_TONUMERIC(u'6') == 6.0
+        assert api.Py_UNICODE_TONUMERIC(u'A') == -1.0
+        assert api.Py_UNICODE_TONUMERIC(u'\N{VULGAR FRACTION ONE HALF}') == .5
+
     def test_fromobject(self, space, api):
         w_u = space.wrap(u'a')
         assert api.PyUnicode_FromObject(w_u) is w_u
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -122,6 +122,38 @@
     """Return the character ch converted to upper case."""
     return unichr(unicodedb.toupper(ord(ch)))
 
+ at cpython_api([Py_UNICODE], Py_UNICODE, error=CANNOT_FAIL)
+def Py_UNICODE_TOTITLE(space, ch):
+    """Return the character ch converted to title case."""
+    return unichr(unicodedb.totitle(ord(ch)))
+
+ at cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
+def Py_UNICODE_TODECIMAL(space, ch):
+    """Return the character ch converted to a decimal positive integer.  Return
+    -1 if this is not possible.  This macro does not raise exceptions."""
+    try:
+        return unicodedb.decimal(ord(ch))
+    except KeyError:
+        return -1
+
+ at cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
+def Py_UNICODE_TODIGIT(space, ch):
+    """Return the character ch converted to a single digit integer. Return -1 if
+    this is not possible.  This macro does not raise exceptions."""
+    try:
+        return unicodedb.digit(ord(ch))
+    except KeyError:
+        return -1
+
+ at cpython_api([Py_UNICODE], rffi.DOUBLE, error=CANNOT_FAIL)
+def Py_UNICODE_TONUMERIC(space, ch):
+    """Return the character ch converted to a double. Return -1.0 if this is not
+    possible.  This macro does not raise exceptions."""
+    try:
+        return unicodedb.numeric(ord(ch))
+    except KeyError:
+        return -1.0
+
 @cpython_api([PyObject], rffi.CCHARP, error=CANNOT_FAIL)
 def PyUnicode_AS_DATA(space, ref):
     """Return a pointer to the internal buffer of the object. o has to be a
@@ -526,8 +558,12 @@
 
 @cpython_api([PyObject, PyObject], PyObject)
 def PyUnicode_Format(space, w_format, w_args):
+    """Return a new string object from format and args; this is analogous to
+    format % args.  The args argument must be a tuple."""
     return space.mod(w_format, w_args)
 
 @cpython_api([PyObject, PyObject], PyObject)
 def PyUnicode_Join(space, w_sep, w_seq):
+    """Join a sequence of strings using the given separator and return the resulting
+    Unicode string."""
     return space.call_method(w_sep, 'join', w_seq)
diff --git a/pypy/module/cpyext/weakrefobject.py b/pypy/module/cpyext/weakrefobject.py
--- a/pypy/module/cpyext/weakrefobject.py
+++ b/pypy/module/cpyext/weakrefobject.py
@@ -25,6 +25,9 @@
 
 @cpython_api([PyObject], PyObject)
 def PyWeakref_GET_OBJECT(space, w_ref):
+    """Similar to PyWeakref_GetObject(), but implemented as a macro that does no
+    error checking.
+    """
     return borrow_from(w_ref, space.call_function(w_ref))
 
 @cpython_api([PyObject], PyObject)
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -540,6 +540,13 @@
     if pkgdir is not None:
         space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)]))
 
+def add_module(space, w_name):
+    w_mod = check_sys_modules(space, w_name)
+    if w_mod is None:
+        w_mod = space.wrap(Module(space, w_name))
+        space.sys.setmodule(w_mod)
+    return w_mod
+
 def load_c_extension(space, filename, modulename):
     # the next line is mandatory to init cpyext
     space.getbuiltinmodule("cpyext")
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -15,7 +15,7 @@
         if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
                        'imp', 'sys', 'array', '_ffi', 'itertools', 'operator',
                        'posix', '_socket', '_sre', '_lsprof', '_weakref',
-                       '__pypy__', 'cStringIO', 'cppyy']:
+                       '__pypy__', 'cStringIO', '_collections', 'cppyy']:
             return True
         return False
 
diff --git a/pypy/module/pypyjit/test/test_policy.py b/pypy/module/pypyjit/test/test_policy.py
--- a/pypy/module/pypyjit/test/test_policy.py
+++ b/pypy/module/pypyjit/test/test_policy.py
@@ -37,8 +37,10 @@
     assert pypypolicy.look_inside_function(Local.getdict.im_func)
 
 def test_pypy_module():
+    from pypy.module._collections.interp_deque import W_Deque
     from pypy.module._random.interp_random import W_Random
     assert not pypypolicy.look_inside_function(W_Random.random)
+    assert pypypolicy.look_inside_function(W_Deque.length)
     assert not pypypolicy.look_inside_pypy_module('select.interp_epoll')
     assert pypypolicy.look_inside_pypy_module('__builtin__.operation')
     assert pypypolicy.look_inside_pypy_module('__builtin__.abstractinst')
diff --git a/pypy/module/termios/interp_termios.py b/pypy/module/termios/interp_termios.py
--- a/pypy/module/termios/interp_termios.py
+++ b/pypy/module/termios/interp_termios.py
@@ -19,8 +19,9 @@
     w_exception_class = space.fromcache(Cache).w_error
     return wrap_oserror(space, error, w_exception_class=w_exception_class)
 
- at unwrap_spec(fd=int, when=int)
-def tcsetattr(space, fd, when, w_attributes):
+ at unwrap_spec(when=int)
+def tcsetattr(space, w_fd, when, w_attributes):
+    fd = space.c_filedescriptor_w(w_fd)
     w_iflag, w_oflag, w_cflag, w_lflag, w_ispeed, w_ospeed, w_cc = \
              space.unpackiterable(w_attributes, expected_length=7)
     w_builtin = space.getbuiltinmodule('__builtin__')
@@ -40,8 +41,8 @@
     except OSError, e:
         raise convert_error(space, e)
 
- at unwrap_spec(fd=int)
-def tcgetattr(space, fd):
+def tcgetattr(space, w_fd):
+    fd = space.c_filedescriptor_w(w_fd)
     try:
         tup = rtermios.tcgetattr(fd)
     except OSError, e:
@@ -57,29 +58,32 @@
     l_w.append(w_cc)
     return space.newlist(l_w)
 
- at unwrap_spec(fd=int, duration=int)
-def tcsendbreak(space, fd, duration):
+ at unwrap_spec(duration=int)
+def tcsendbreak(space, w_fd, duration):
+    fd = space.c_filedescriptor_w(w_fd)
     try:
         termios.tcsendbreak(fd, duration)
     except OSError, e:
         raise convert_error(space, e)
 
- at unwrap_spec(fd=int)
-def tcdrain(space, fd):
+def tcdrain(space, w_fd):
+    fd = space.c_filedescriptor_w(w_fd)
     try:
         termios.tcdrain(fd)
     except OSError, e:
         raise convert_error(space, e)
 
- at unwrap_spec(fd=int, queue=int)
-def tcflush(space, fd, queue):
+ at unwrap_spec(queue=int)
+def tcflush(space, w_fd, queue):
+    fd = space.c_filedescriptor_w(w_fd)
     try:
         termios.tcflush(fd, queue)
     except OSError, e:
         raise convert_error(space, e)
 
- at unwrap_spec(fd=int, action=int)
-def tcflow(space, fd, action):
+ at unwrap_spec(action=int)
+def tcflow(space, w_fd, action):
+    fd = space.c_filedescriptor_w(w_fd)
     try:
         termios.tcflow(fd, action)
     except OSError, e:
diff --git a/pypy/module/termios/test/test_termios.py b/pypy/module/termios/test/test_termios.py
--- a/pypy/module/termios/test/test_termios.py
+++ b/pypy/module/termios/test/test_termios.py
@@ -62,8 +62,9 @@
 
     def test_tcsetattr(self):
         source = py.code.Source("""
+        import sys
         import termios
-        termios.tcsetattr(0, 1, [16640, 4, 191, 2608, 15, 15, ['\x03', '\x1c', '\x7f', '\x15', '\x04', 0, 1, '\x00', '\x11', '\x13', '\x1a', '\x00', '\x12', '\x0f', '\x17', '\x16', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']])
+        termios.tcsetattr(sys.stdin, 1, [16640, 4, 191, 2608, 15, 15, ['\x03', '\x1c', '\x7f', '\x15', '\x04', 0, 1, '\x00', '\x11', '\x13', '\x1a', '\x00', '\x12', '\x0f', '\x17', '\x16', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']])
         print 'ok!'
         """)
         f = udir.join("test_tcsetattr.py")
diff --git a/pypy/module/thread/test/test_ll_thread.py b/pypy/module/thread/test/test_ll_thread.py
--- a/pypy/module/thread/test/test_ll_thread.py
+++ b/pypy/module/thread/test/test_ll_thread.py
@@ -34,6 +34,10 @@
     use_threads = True
 
     def test_start_new_thread(self):
+        py.test.skip("xxx ideally, investigate why it fails randomly")
+        # xxx but in practice start_new_thread() is also tested by the
+        # next test, and it's a mess to test start_new_thread() without
+        # the proper GIL to protect the GC
         import time
 
         class State:


More information about the pypy-commit mailing list