[pypy-commit] pypy unicode-utf8: merged default into branch

mattip pypy.commits at gmail.com
Mon Jul 2 00:13:06 EDT 2018


Author: Matti Picus <matti.picus at gmail.com>
Branch: unicode-utf8
Changeset: r94801:f32c591c9e7f
Date: 2018-07-01 22:45 -0500
http://bitbucket.org/pypy/pypy/changeset/f32c591c9e7f/

Log:	merged default into branch

diff --git a/pypy/doc/sandbox.rst b/pypy/doc/sandbox.rst
--- a/pypy/doc/sandbox.rst
+++ b/pypy/doc/sandbox.rst
@@ -3,6 +3,11 @@
 PyPy's sandboxing features
 ==========================
 
+.. warning:: This is not actively maintained. You will likely have to fix
+   some issues yourself, or otherwise play around on your own. We provide
+   this documentation for historical reasions, it will not translate or
+   run on the latest PyPy code base.
+
 Introduction
 ------------
 
diff --git a/pypy/interpreter/pyparser/automata.py b/pypy/interpreter/pyparser/automata.py
--- a/pypy/interpreter/pyparser/automata.py
+++ b/pypy/interpreter/pyparser/automata.py
@@ -23,6 +23,10 @@
 
 ERROR_STATE = chr(255)
 
+# NB: all non-ascii bytes (>= 128) will be turned into 128
+NON_ASCII = chr(128)
+
+
 class DFA:
     # ____________________________________________________________
     def __init__(self, states, accepts, start = 0):
@@ -36,7 +40,10 @@
             for key in state:
                 if key == DEFAULT:
                     continue
-                maximum = max(ord(key), maximum)
+                ordkey = ord(key)
+                if ordkey > 128:
+                    raise ValueError("DFA does not support matching of specific non-ASCII character %r. Use NON_ASCII instead" % key)
+                maximum = max(ordkey, maximum)
         self.max_char = maximum + 1
 
         defaults = []
@@ -72,6 +79,8 @@
         i = pos
         for i in range(pos, len(inVec)):
             item = inVec[i]
+            if ord(item) > 0x80:
+                item = NON_ASCII
             accept = self.accepts[crntState]
             crntState = self._next_state(item, crntState)
             if crntState != ERROR_STATE:
@@ -103,6 +112,8 @@
         i = pos
         for i in range(pos, len(inVec)):
             item = inVec[i]
+            if ord(item) > 0x80:
+                item = NON_ASCII
             accept = self.accepts[crntState]
             if accept:
                 return i
diff --git a/pypy/interpreter/pyparser/test/test_automata.py b/pypy/interpreter/pyparser/test/test_automata.py
--- a/pypy/interpreter/pyparser/test/test_automata.py
+++ b/pypy/interpreter/pyparser/test/test_automata.py
@@ -1,4 +1,7 @@
-from pypy.interpreter.pyparser.automata import DFA, NonGreedyDFA, DEFAULT
+# coding: utf-8
+import pytest
+
+from pypy.interpreter.pyparser.automata import DFA, NonGreedyDFA, DEFAULT, NON_ASCII
 
 def test_states():
     d = DFA([{"\x00": 1}, {"\x01": 0}], [False, True])
@@ -27,3 +30,18 @@
     d = NonGreedyDFA([{"a": 1}, {DEFAULT: 0}], [False, True])
     assert d.recognize("a,a?ab") == 1
     assert d.recognize("c") == -1
+
+def test_nonascii():
+    d = DFA([{"a": 1}, {NON_ASCII: 1}], [False, True])
+    input = u"aüüüü".encode("utf-8")
+    assert d.recognize(input) == len(input)
+    assert d.recognize("c") == -1
+    assert d.recognize("ü") == -1
+
+    d = NonGreedyDFA([{NON_ASCII: 0, "b": 1}, {"b": 0}], [False, True])
+    input = u"üübbbb".encode("utf-8")
+    assert d.recognize(input) == len(u"üüb".encode("utf-8"))
+    assert d.recognize("c") == -1
+
+    pytest.raises(ValueError, DFA, [{"\x81": 2}], [True])
+
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -455,6 +455,8 @@
         assert repr(B().f).startswith("<bound method B.f of <")
         assert repr(A().f).endswith(">>")
 
+        assert repr(type(A.f)) == repr(type(A().f)) == "<type 'instancemethod'>"
+
 
     def test_method_call(self):
         class C(object):
diff --git a/pypy/interpreter/test/test_raise.py b/pypy/interpreter/test/test_raise.py
--- a/pypy/interpreter/test/test_raise.py
+++ b/pypy/interpreter/test/test_raise.py
@@ -280,3 +280,15 @@
             def __new__(cls, *args):
                 return object()
         raises(TypeError, "raise MyException")
+
+    def test_with_exit_True(self):
+        class X:
+            def __enter__(self):
+                pass
+            def __exit__(self, *args):
+                return True
+        def g():
+            with X():
+                return 42
+            assert False, "unreachable"
+        assert g() == 42
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -688,7 +688,7 @@
 Function.typedef.acceptable_as_base_class = False
 
 Method.typedef = TypeDef(
-    "method",
+    "instancemethod",
     __doc__ = """instancemethod(function, instance, class)
 
 Create an instance method object.""",
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
@@ -706,7 +706,7 @@
                     "no overload found matching %s", self.signature)
 
 
-class SmartPointerConverter(TypeConverter):
+class SmartPtrConverter(TypeConverter):
     _immutable_fields = ['typecode', 'smartdecl', 'rawdecl', 'deref']
     typecode    = 'V'
 
@@ -753,7 +753,7 @@
         return interp_cppyy.wrap_cppinstance(space, address,
             self.rawdecl, smartdecl=self.smartdecl, deref=self.deref, do_cast=False)
 
-class SmartPointerPtrConverter(SmartPointerConverter):
+class SmartPtrPtrConverter(SmartPtrConverter):
     typecode    = 'o'
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
@@ -763,7 +763,7 @@
         self._is_abstract(space)
 
 
-class SmartPointerRefConverter(SmartPointerPtrConverter):
+class SmartPtrRefConverter(SmartPtrPtrConverter):
     typecode    = 'V'
 
 
@@ -804,6 +804,12 @@
     compound = helper.compound(name)
     clean_name = capi.c_resolve_name(space, helper.clean_type(name))
     try:
+        return _converters[clean_name+compound](space, default)
+    except KeyError:
+        pass
+
+    # arrays
+    try:
         # array_index may be negative to indicate no size or no size found
         array_size = helper.array_size(_name)     # uses original arg
         # TODO: using clean_name here drops const (e.g. const char[] will
@@ -823,11 +829,11 @@
         check_smart = capi.c_smartptr_info(space, clean_name)
         if check_smart[0]:
             if compound == '':
-                return SmartPointerConverter(space, clsdecl, check_smart[1], check_smart[2])
+                return SmartPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
             elif compound == '*':
-                return SmartPointerPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
+                return SmartPtrPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
             elif compound == '&':
-                return SmartPointerRefConverter(space, clsdecl, check_smart[1], check_smart[2])
+                return SmartPtrRefConverter(space, clsdecl, check_smart[1], check_smart[2])
             # fall through: can still return smart pointer in non-smart way
 
         # type check for the benefit of the annotator
diff --git a/pypy/module/_cppyy/executor.py b/pypy/module/_cppyy/executor.py
--- a/pypy/module/_cppyy/executor.py
+++ b/pypy/module/_cppyy/executor.py
@@ -26,7 +26,7 @@
 
 NULL = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
 
-class FunctionExecutor(object):
+class Executor(object):
     def __init__(self, space, extra):
         pass
 
@@ -43,7 +43,7 @@
         raise FastCallNotPossible
 
 
-class PtrTypeExecutor(FunctionExecutor):
+class PtrTypeExecutor(Executor):
     _immutable_fields_ = ['typecode']
     typecode = 'P'
 
@@ -63,7 +63,7 @@
         return W_ArrayInstance(space, shape, sys.maxint/shape.size, ptrval)
 
 
-class VoidExecutor(FunctionExecutor):
+class VoidExecutor(Executor):
     def cffi_type(self, space):
         state = space.fromcache(ffitypes.State)
         return state.c_void
@@ -96,7 +96,7 @@
     _mixin_ = True
 
     def __init__(self, space, extra):
-        FunctionExecutor.__init__(self, space, extra)
+        Executor.__init__(self, space, extra)
         self.do_assign = False
         self.item = rffi.cast(self.c_type, 0)
 
@@ -124,7 +124,7 @@
             rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
 
 
-class CStringExecutor(FunctionExecutor):
+class CStringExecutor(Executor):
     def execute(self, space, cppmethod, cppthis, num_args, args):
         lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
         ccpresult = rffi.cast(rffi.CCHARP, lresult)
@@ -134,7 +134,7 @@
         return space.newbytes(result)
 
 
-class ConstructorExecutor(FunctionExecutor):
+class ConstructorExecutor(Executor):
     def execute(self, space, cppmethod, cpptype, num_args, args):
         from pypy.module._cppyy import interp_cppyy
         newthis = capi.c_constructor(space, cppmethod, cpptype, num_args, args)
@@ -142,12 +142,12 @@
         return space.newlong(rffi.cast(rffi.LONG, newthis))   # really want ptrdiff_t here
 
 
-class InstanceExecutor(FunctionExecutor):
+class InstanceExecutor(Executor):
     # For return of a C++ instance by pointer: MyClass* func()
     _immutable_fields_ = ['clsdecl']
 
     def __init__(self, space, clsdecl):
-        FunctionExecutor.__init__(self, space, clsdecl)
+        Executor.__init__(self, space, clsdecl)
         self.clsdecl = clsdecl
 
     def _wrap_result(self, space, obj):
@@ -338,7 +338,7 @@
         return _executors['void*'](space, None)  # allow at least passing of the pointer
 
     # currently used until proper lazy instantiation available in interp_cppyy
-    return FunctionExecutor(space, None)
+    return Executor(space, None)
  
 
 _executors["void"]                = VoidExecutor
@@ -374,10 +374,10 @@
     )
 
     for c_type, stub, names in type_info:
-        class BasicExecutor(ffitypes.typeid(c_type), NumericExecutorMixin, FunctionExecutor):
+        class BasicExecutor(ffitypes.typeid(c_type), NumericExecutorMixin, Executor):
             _immutable_ = True
             c_stubcall  = staticmethod(stub)
-        class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, FunctionExecutor):
+        class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, Executor):
             def cffi_type(self, space):
                 state = space.fromcache(ffitypes.State)
                 return state.c_voidp
diff --git a/pypy/module/_cppyy/ffitypes.py b/pypy/module/_cppyy/ffitypes.py
--- a/pypy/module/_cppyy/ffitypes.py
+++ b/pypy/module/_cppyy/ffitypes.py
@@ -119,7 +119,7 @@
                 value = space.bytes_w(w_value)
             if len(value) != 1:
                 raise oefmt(space.w_ValueError,
-                            "usigned char expected, got string of size %d", len(value))
+                            "unsigned char expected, got string of size %d", len(value))
 
         value = rffi.cast(rffi.CHAR, value[0])
         return value     # turn it into a "char" to the annotator
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
@@ -672,24 +672,33 @@
 
     _mixin_ = True
 
-    def construct_template_args(self, w_args):
+    def construct_template_args(self, w_tpArgs, args_w = None):
         space = self.space
         tmpl_args = ''
-        for i in range(space.len_w(w_args)):
-            w_obj = space.getitem(w_args, space.newint(i))
-            if space.isinstance_w(w_obj, space.w_text):
-                s = space.text_w(w_obj)      # string describing type
-            elif space.isinstance_w(w_obj, space.w_type):
+        for i in range(space.len_w(w_tpArgs)):
+            w_tp = space.getitem(w_tpArgs, space.newint(i))
+            if space.isinstance_w(w_tp, space.w_text):
+                s = space.text_w(w_tp)      # string describing type
+            elif space.isinstance_w(w_tp, space.w_type):
                 try:
                     # cppyy bound types
-                    name = space.getattr(w_obj, space.newtext('__cppname__'))
+                    s = space.text_w(space.getattr(w_tp, space.newtext('__cppname__')))
+                    if args_w:
+                        # try to specialize the type match for the given object
+                        cppinstance = self.space.interp_w(W_CPPInstance, args_w[i])
+                        if cppinstance.flags & INSTANCE_FLAGS_IS_RVALUE:
+                            sugar = "&&"
+                        elif cppinstance.flags & INSTANCE_FLAGS_IS_REF:
+                            sugar = "*"
+                        else:
+                            sugar = "&"
+                        s += sugar
                 except OperationError:
                     # generic python types
-                    name = space.getattr(w_obj, space.newtext('__name__'))
-                s = space.text_w(name)
+                    s = space.text_w(space.getattr(w_tp, space.newtext('__name__')))
             else:
                 # builtin types etc.
-                s = space.text_w(space.str(w_obj))
+                s = space.text_w(space.str(w_tp))
             # map python types -> C++ types
             if s == 'str': s = 'std::string'
             if i != 0: tmpl_args += ', '
@@ -712,23 +721,31 @@
             cppol = W_CPPOverload(space, self.scope, funcs[:], self.flags)
         return cppol
 
-    def instantiation_from_args(self, name, args_w):
+    def instantiate_and_call(self, name, args_w):
         # try to match with run-time instantiations
         for cppol in self.master.overloads.values():
             try:
-                cppol.descr_get(self.w_this, []).call(args_w)
+                return cppol.descr_get(self.w_this, []).call(args_w)
             except Exception:
                 pass    # completely ignore for now; have to see whether errors become confusing
 
         # if all failed, then try to deduce from argument types
         w_types = self.space.newtuple([self.space.type(obj_w) for obj_w in args_w])
-        proto = self.construct_template_args(w_types)
+        proto = self.construct_template_args(w_types, args_w)
         method = self.find_method_template(name, proto)
 
         # only cache result if the name retains the full template
-        if len(method.functions) == 1:
-            fullname = capi.c_method_full_name(self.space, method.functions[0].cppmethod)
-            if 0 <= fullname.rfind('>'):
+        fullname = capi.c_method_full_name(self.space, method.functions[0].cppmethod)
+        if 0 <= fullname.rfind('>'):
+            try:
+                existing = self.master.overloads[fullname]
+                allf = existing.functions + method.functions
+                if isinstance(existing, W_CPPStaticOverload):
+                    cppol = W_CPPStaticOverload(self.space, self.scope, allf, self.flags)
+                else:
+                    cppol = W_CPPOverload(self.space, self.scope, allf, self.flags)
+                self.master.overloads[fullname] = cppol
+            except KeyError:
                 self.master.overloads[fullname] = method
 
         return method.descr_get(self.w_this, []).call(args_w)
@@ -747,9 +764,12 @@
             method = self.master.overloads[fullname]
         except KeyError:
             method = self.find_method_template(fullname)
-
-        # cache result (name is always full templated name)
-        self.master.overloads[fullname] = method
+            # cache result (name is always full templated name)
+            self.master.overloads[fullname] = method
+            # also cache on "official" name (may include default template arguments)
+            c_fullname = capi.c_method_full_name(self.space, method.functions[0].cppmethod)
+            if c_fullname != fullname:
+                self.master.overloads[c_fullname] = method
 
         return method.descr_get(self.w_this, [])
 
@@ -774,6 +794,7 @@
             return self  # unbound, so no new instance needed
         cppol = W_CPPTemplateOverload(self.space, self.name, self.scope, self.functions, self.flags)
         cppol.w_this = w_cppinstance
+        cppol.master = self.master
         return cppol     # bound
 
     @unwrap_spec(args_w='args_w')
@@ -787,7 +808,7 @@
         except Exception:
             pass
 
-        return self.instantiation_from_args(self.name, args_w)
+        return self.instantiate_and_call(self.name, args_w)
 
     @unwrap_spec(args_w='args_w')
     def getitem(self, args_w):
@@ -842,7 +863,7 @@
             pass
 
         # try new instantiation
-        return self.instantiation_from_args(self.name, args_w)
+        return self.instantiate_and_call(self.name, args_w)
 
     @unwrap_spec(args_w='args_w')
     def getitem(self, args_w):
diff --git a/pypy/module/_cppyy/pythonify.py b/pypy/module/_cppyy/pythonify.py
--- a/pypy/module/_cppyy/pythonify.py
+++ b/pypy/module/_cppyy/pythonify.py
@@ -408,16 +408,22 @@
 
     # map push_back -> __iadd__ (generally true for STL)
     if 'push_back' in pyclass.__dict__ and not '__iadd__' in pyclass.__dict__:
-        def __iadd__(self, ll):
-            [self.push_back(x) for x in ll]
-            return self
-        pyclass.__iadd__ = __iadd__
+        if 'reserve' in pyclass.__dict__:
+            def iadd(self, ll):
+                self.reserve(len(ll))
+                for x in ll: self.push_back(x)
+                return self
+        else:
+            def iadd(self, ll):
+                for x in ll: self.push_back(x)
+                return self
+        pyclass.__iadd__ = iadd
 
     # map begin()/end() protocol to iter protocol on STL(-like) classes, but
     # not on vector, which is pythonized in the capi (interp-level; there is
     # also the fallback on the indexed __getitem__, but that is slower)
-    if not 'vector' in name[:11] and \
-            ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
+# TODO:    if not (0 <= name.find('vector') <= 5):
+    if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
         if _cppyy._scope_byname(name+'::iterator') or \
                 _cppyy._scope_byname(name+'::const_iterator'):
             def __iter__(self):
@@ -430,6 +436,20 @@
             pyclass.__iter__ = __iter__
         # else: rely on numbered iteration
 
+    # add python collection based initializer
+    if 0 <= name.find('vector') <= 5:
+        pyclass.__real_init__ = pyclass.__init__
+        def vector_init(self, *args):
+            if len(args) == 1 and isinstance(args[0], (tuple, list)):
+                ll = args[0]
+                self.__real_init__()
+                self.reserve(len(ll))
+                for item in ll:
+                    self.push_back(item)
+                return
+            return self.__real_init__(*args)
+        pyclass.__init__ = vector_init
+
     # combine __getitem__ and __len__ to make a pythonized __getitem__
     if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
         pyclass._getitem__unchecked = pyclass.__getitem__
@@ -470,7 +490,13 @@
     for p in pythonizors:
         p(pyclass, name)
 
+cppyyIsInitialized = False
 def _post_import_startup():
+    # run only once (function is explicitly called in testing)
+    global cppyyIsInitialized
+    if cppyyIsInitialized:
+        return
+
     # _cppyy should not be loaded at the module level, as that will trigger a
     # call to space.getbuiltinmodule(), which will cause _cppyy to be loaded
     # at pypy-c startup, rather than on the "import _cppyy" statement
@@ -511,6 +537,9 @@
     # install nullptr as a unique reference
     _cppyy.nullptr = _cppyy._get_nullptr()
 
+    # done
+    cppyyIsInitialized = True
+
 
 # user-defined pythonizations interface
 _pythonizations = {'' : list()}
diff --git a/pypy/module/_cppyy/test/templates.h b/pypy/module/_cppyy/test/templates.h
--- a/pypy/module/_cppyy/test/templates.h
+++ b/pypy/module/_cppyy/test/templates.h
@@ -107,7 +107,7 @@
 }
 
 inline std::string tuplify(std::ostringstream& out) {
-    out.seekp(-2, out.cur); out << ')';
+    out << "NULL)";
     return out.str();
 }
 
diff --git a/pypy/module/_cppyy/test/test_templates.py b/pypy/module/_cppyy/test/test_templates.py
--- a/pypy/module/_cppyy/test/test_templates.py
+++ b/pypy/module/_cppyy/test/test_templates.py
@@ -13,7 +13,7 @@
 
     def setup_class(cls):
         cls.w_test_dct  = cls.space.newtext(test_dct)
-        cls.w_datatypes = cls.space.appexec([], """():
+        cls.w_templates = cls.space.appexec([], """():
             import ctypes, _cppyy
             _cppyy._post_import_startup()
             return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
@@ -84,10 +84,11 @@
 
         import _cppyy
 
-        s = _cppyy.gbl.std.ostringstream()
-        #s << '('
-        #_cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap")
-        #assert s.str() == '(1, 4, aap)
+        s = _cppyy.gbl.std.ostringstream('(', _cppyy.gbl.std.ios_base.ate)
+        # Fails; selects void* overload (?!)
+        #s << "("
+        _cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap")
+        assert s.str() == "(1, 4, aap, NULL)"
 
         _cppyy.gbl.gInterpreter.Declare("""
             template<typename... myTypes>
@@ -133,7 +134,7 @@
         Obj2                  = _cppyy.gbl.AttrTesting.Obj2
         select_template_arg   = _cppyy.gbl.AttrTesting.select_template_arg
 
-       #assert select_template_arg[0, Obj1, Obj2].argument == Obj1
+      # assert select_template_arg[0, Obj1, Obj2].argument == Obj1
         assert select_template_arg[1, Obj1, Obj2].argument == Obj2
         raises(TypeError, select_template_arg.__getitem__, 2, Obj1, Obj2)
 
@@ -169,7 +170,7 @@
 
 
       # TODO: the ref_value property is inaccessible (offset == -1)
-      # assert cppyy.gbl.BaseClassWithStatic["size_t"].ref_value == 42
+      # assert _cppyy.gbl.BaseClassWithStatic["size_t"].ref_value == 42
 
         b1 = _cppyy.gbl.DerivedClassUsingStatic["size_t"](  0)
         b2 = _cppyy.gbl.DerivedClassUsingStatic["size_t"](100)
@@ -179,3 +180,62 @@
 
       # assert b2.ref_value == 42
         assert b2.m_value   == 42
+
+
+class AppTestBOOSTANY:
+    spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+    def setup_class(cls):
+        cls.w_test_dct  = cls.space.newtext(test_dct)
+        cls.w_templates = cls.space.appexec([], """():
+            import ctypes, _cppyy
+            _cppyy._post_import_startup()""")
+
+    def test01_any_class(self):
+        """Usage of boost::any"""
+
+        import _cppyy
+
+        if not _cppyy.gbl.gInterpreter.Declare('#include "boost/any.hpp"'):
+            import warnings
+            warnings.warn('skipping boost/any testing')
+            return
+
+        assert _cppyy.gbl.boost
+        assert _cppyy.gbl.boost.any
+
+        std, boost = _cppyy.gbl.std, _cppyy.gbl.boost
+
+        assert std.list[boost.any]
+
+        val = boost.any()
+        # test both by-ref and by rvalue
+        v = std.vector[int]()
+        val.__assign__(v)
+        val.__assign__(std.move(std.vector[int](range(100))))
+
+        _cppyy.gbl.gInterpreter.ProcessLine(
+            "namespace _cppyy_internal { auto* stdvectid = &typeid(std::vector<int>); }")
+
+        assert val.type() == _cppyy.gbl._cppyy_internal.stdvectid
+
+        extract = boost.any_cast[std.vector[int]](val)
+        assert type(extract) is std.vector[int]
+        assert len(extract) == 100
+        extract += range(100)
+        assert len(extract) == 200
+
+        val.__assign__(std.move(extract))   # move forced
+
+        # TODO: we hit boost::any_cast<int>(boost::any* operand) instead
+        # of the reference version which raises
+        boost.any_cast.__useffi__ = False
+        try:
+          # raises(Exception, boost.any_cast[int], val)
+            assert not boost.any_cast[int](val)
+        except Exception:
+          # getting here is good, too ...
+            pass
+
+        extract = boost.any_cast[std.vector[int]](val)
+        assert len(extract) == 200
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -643,7 +643,7 @@
     '_PyTraceMalloc_Track', '_PyTraceMalloc_Untrack', 'PyMem_Malloc',
     'PyObject_Free', 'PyObject_GC_Del', 'PyType_GenericAlloc',
     '_PyObject_New', '_PyObject_NewVar',
-    '_PyObject_GC_New', '_PyObject_GC_NewVar',
+    '_PyObject_GC_Malloc', '_PyObject_GC_New', '_PyObject_GC_NewVar',
     'PyObject_Init', 'PyObject_InitVar', 'PyInt_FromLong',
     'PyTuple_New', '_Py_Dealloc',
 ]
@@ -772,6 +772,9 @@
 # a pointer to PyObject
 PyObjectP = rffi.CArrayPtr(PyObject)
 
+# int *
+INTP_real = rffi.CArrayPtr(rffi.INT_real)
+
 def configure_types():
     for config in (CConfig, CConfig2):
         for name, TYPE in rffi_platform.configure(config).iteritems():
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -383,6 +383,7 @@
 
 PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
 PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
+PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t);
 PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *);
 PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t);
 
diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -1,7 +1,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from pypy.module.cpyext.api import (
     cpython_api, PyObject, build_type_checkers_flags, Py_ssize_t,
-    CONST_STRING, ADDR, CANNOT_FAIL)
+    CONST_STRING, ADDR, CANNOT_FAIL, INTP_real)
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.unicodehelper import wcharpsize2utf8
@@ -113,7 +113,7 @@
     num = space.bigint_w(w_long)
     return num.ulonglongmask()
 
- at cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], lltype.Signed,
+ at cpython_api([PyObject, INTP_real], lltype.Signed,
              error=-1)
 def PyLong_AsLongAndOverflow(space, w_long, overflow_ptr):
     """
@@ -134,7 +134,7 @@
         overflow_ptr[0] = rffi.cast(rffi.INT_real, -1)
     return -1
 
- at cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], rffi.LONGLONG,
+ at cpython_api([PyObject, INTP_real], rffi.LONGLONG,
              error=-1)
 def PyLong_AsLongLongAndOverflow(space, w_long, overflow_ptr):
     """
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -1,7 +1,7 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
     cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
-    PyVarObject, size_t, slot_function,
+    PyVarObject, size_t, slot_function, INTP_real,
     Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
     Py_GE, CONST_STRING, FILEP, fwrite, c_only)
 from pypy.module.cpyext.pyobject import (
@@ -221,14 +221,14 @@
     expression cmp(o1, o2)."""
     return space.int_w(space.cmp(w_o1, w_o2))
 
- at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
+ at cpython_api([PyObject, PyObject, INTP_real], rffi.INT_real, error=-1)
 def PyObject_Cmp(space, w_o1, w_o2, result):
     """Compare the values of o1 and o2 using a routine provided by o1, if one
     exists, otherwise with a routine provided by o2.  The result of the
     comparison is returned in result.  Returns -1 on failure.  This is the
     equivalent of the Python statement result = cmp(o1, o2)."""
     res = space.int_w(space.cmp(w_o1, w_o2))
-    result[0] = rffi.cast(rffi.INT, res)
+    result[0] = rffi.cast(rffi.INT_real, res)
     return 0
 
 @cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
diff --git a/pypy/module/cpyext/pystrtod.py b/pypy/module/cpyext/pystrtod.py
--- a/pypy/module/cpyext/pystrtod.py
+++ b/pypy/module/cpyext/pystrtod.py
@@ -1,6 +1,6 @@
 import errno
 from pypy.interpreter.error import oefmt
-from pypy.module.cpyext.api import cpython_api, CONST_STRING
+from pypy.module.cpyext.api import cpython_api, CONST_STRING, INTP_real
 from pypy.module.cpyext.pyobject import PyObject
 from rpython.rlib import rdtoa
 from rpython.rlib import rfloat
@@ -80,7 +80,7 @@
         if not user_endptr:
             lltype.free(endptr, flavor='raw')
 
- at cpython_api([rffi.DOUBLE, lltype.Char, rffi.INT_real, rffi.INT_real, rffi.INTP], rffi.CCHARP)
+ at cpython_api([rffi.DOUBLE, lltype.Char, rffi.INT_real, rffi.INT_real, INTP_real], rffi.CCHARP)
 def PyOS_double_to_string(space, val, format_code, precision, flags, ptype):
     """Convert a double val to a string using supplied
     format_code, precision, and flags.
@@ -114,7 +114,7 @@
     buffer, rtype = rfloat.double_to_string(val, format_code,
                                             intmask(precision),
                                             intmask(flags))
-    if ptype != lltype.nullptr(rffi.INTP.TO):
-        ptype[0] = rffi.cast(rffi.INT, DOUBLE_TO_STRING_TYPES_MAP[rtype])
+    if ptype != lltype.nullptr(INTP_real.TO):
+        ptype[0] = rffi.cast(rffi.INT_real, DOUBLE_TO_STRING_TYPES_MAP[rtype])
     bufp = rffi.str2charp(buffer)
     return bufp
diff --git a/pypy/module/cpyext/src/object.c b/pypy/module/cpyext/src/object.c
--- a/pypy/module/cpyext/src/object.c
+++ b/pypy/module/cpyext/src/object.c
@@ -60,6 +60,11 @@
     return (PyObject*)_PyObject_NewVar(type, 0);
 }
 
+PyObject * _PyObject_GC_Malloc(size_t size)
+{
+    return (PyObject *)PyObject_Malloc(size);
+}
+
 PyObject * _PyObject_GC_New(PyTypeObject *type)
 {
     return _PyObject_New(type);
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -5,7 +5,7 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.pyobject import get_w_obj_and_decref
 from pypy.module.cpyext.api import (
-    Py_LT, Py_LE, Py_NE, Py_EQ, Py_GE, Py_GT)
+    Py_LT, Py_LE, Py_NE, Py_EQ, Py_GE, Py_GT, INTP_real)
 from pypy.module.cpyext.object import (
     PyObject_IsTrue, PyObject_Not, PyObject_GetAttrString,
     PyObject_DelAttrString, PyObject_GetAttr, PyObject_DelAttr,
@@ -205,7 +205,7 @@
 
     def test_cmp(self, space, api):
         w = space.wrap
-        with lltype.scoped_alloc(rffi.INTP.TO, 1) as ptr:
+        with lltype.scoped_alloc(INTP_real.TO, 1) as ptr:
             assert api.PyObject_Cmp(w(42), w(72), ptr) == 0
             assert ptr[0] == -1
             assert api.PyObject_Cmp(w("a"), w("a"), ptr) == 0
diff --git a/pypy/module/cpyext/test/test_pystrtod.py b/pypy/module/cpyext/test/test_pystrtod.py
--- a/pypy/module/cpyext/test/test_pystrtod.py
+++ b/pypy/module/cpyext/test/test_pystrtod.py
@@ -4,7 +4,7 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rtyper.lltypesystem import lltype
-from pypy.module.cpyext.pystrtod import PyOS_string_to_double
+from pypy.module.cpyext.pystrtod import PyOS_string_to_double, INTP_real
 
 
 class TestPyOS_string_to_double(BaseApiTest):
@@ -90,7 +90,7 @@
 class TestPyOS_double_to_string(BaseApiTest):
 
     def test_format_code(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(150.0, 'e', 1, 0, ptype)
         assert '1.5e+02' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -99,7 +99,7 @@
         lltype.free(ptype, flavor='raw')
 
     def test_precision(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(3.14159269397, 'g', 5, 0, ptype)
         assert '3.1416' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -108,7 +108,7 @@
         lltype.free(ptype, flavor='raw')
 
     def test_flags_sign(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(-3.14, 'g', 3, 1, ptype)
         assert '-3.14' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -117,7 +117,7 @@
         lltype.free(ptype, flavor='raw')
 
     def test_flags_add_dot_0(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(3, 'g', 5, 2, ptype)
         assert '3.0' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -126,7 +126,7 @@
         lltype.free(ptype, flavor='raw')
 
     def test_flags_alt(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(314., 'g', 3, 4, ptype)
         assert '314.' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -135,7 +135,7 @@
         lltype.free(ptype, flavor='raw')
 
     def test_ptype_nan(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(float('nan'), 'g', 3, 4, ptype)
         assert 'nan' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -144,7 +144,7 @@
         lltype.free(ptype, flavor='raw')
 
     def test_ptype_infinity(self, api):
-        ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
         r = api.PyOS_double_to_string(1e200 * 1e200, 'g', 0, 0, ptype)
         assert 'inf' == rffi.charp2str(r)
         type_value = rffi.cast(lltype.Signed, ptype[0])
@@ -153,8 +153,8 @@
         lltype.free(ptype, flavor='raw')
 
     def test_ptype_null(self, api):
-        ptype = lltype.nullptr(rffi.INTP.TO)
+        ptype = lltype.nullptr(INTP_real.TO)
         r = api.PyOS_double_to_string(3.14, 'g', 3, 0, ptype)
         assert '3.14' == rffi.charp2str(r)
-        assert ptype == lltype.nullptr(rffi.INTP.TO)
+        assert ptype == lltype.nullptr(INTP_real.TO)
         rffi.free_charp(r)
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
@@ -4,7 +4,7 @@
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from pypy.module.cpyext.unicodeobject import (
     Py_UNICODE, PyUnicodeObject, new_empty_unicode)
-from pypy.module.cpyext.api import PyObjectP, PyObject
+from pypy.module.cpyext.api import PyObjectP, PyObject, INTP_real
 from pypy.module.cpyext.pyobject import decref, from_ref
 from rpython.rtyper.lltypesystem import rffi, lltype
 import sys, py
@@ -467,8 +467,8 @@
                     value = 1
                 else:
                     value = 0
-                pendian = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
-                pendian[0] = rffi.cast(rffi.INT, value)
+                pendian = lltype.malloc(INTP_real.TO, 1, flavor='raw')
+                pendian[0] = rffi.cast(rffi.INT_real, value)
             else:
                 pendian = None
 
@@ -480,7 +480,7 @@
             rffi.free_charp(strict_charp)
             if pendian:
                 if realendian is not None:
-                    assert rffi.cast(rffi.INT, realendian) == pendian[0]
+                    assert rffi.cast(rffi.INT_real, realendian) == pendian[0]
                 lltype.free(pendian, flavor='raw')
 
         test("\x61\x00\x62\x00\x63\x00\x64\x00", -1)
@@ -503,8 +503,8 @@
                     value = 1
                 else:
                     value = 0
-                pendian = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
-                pendian[0] = rffi.cast(rffi.INT, value)
+                pendian = lltype.malloc(INTP_real.TO, 1, flavor='raw')
+                pendian[0] = rffi.cast(rffi.INT_real, value)
             else:
                 pendian = None
 
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
@@ -9,7 +9,7 @@
 from pypy.module.unicodedata import unicodedb
 from pypy.module.cpyext.api import (
     CANNOT_FAIL, Py_ssize_t, build_type_checkers_flags, cpython_api,
-    bootstrap_function, CONST_STRING,
+    bootstrap_function, CONST_STRING, INTP_real,
     CONST_WSTRING, slot_function, cts, parse_dir)
 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
 from pypy.module.cpyext.pyobject import (
@@ -532,7 +532,7 @@
 if sys.platform == 'win32':
     make_conversion_functions('MBCS', 'mbcs')
 
- at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, rffi.INTP], PyObject)
+ at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, INTP_real], PyObject)
 def PyUnicode_DecodeUTF16(space, s, size, llerrors, pbyteorder):
     """Decode length bytes from a UTF-16 encoded buffer string and return the
     corresponding Unicode object.  errors (if non-NULL) defines the error
@@ -579,10 +579,10 @@
     result, _,  length, byteorder = str_decode_utf_16_helper(
         string, errors, final=True, errorhandler=None, byteorder=byteorder)
     if pbyteorder is not None:
-        pbyteorder[0] = rffi.cast(rffi.INT, byteorder)
+        pbyteorder[0] = rffi.cast(rffi.INT_real, byteorder)
     return space.newutf8(result, length)
 
- at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, rffi.INTP], PyObject)
+ at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, INTP_real], PyObject)
 def PyUnicode_DecodeUTF32(space, s, size, llerrors, pbyteorder):
     """Decode length bytes from a UTF-32 encoded buffer string and
     return the corresponding Unicode object.  errors (if non-NULL)
@@ -631,7 +631,7 @@
     result, _,  length, byteorder = unicodehelper.str_decode_utf_32_helper(
         string, errors, final=True, errorhandler=None, byteorder=byteorder)
     if pbyteorder is not None:
-        pbyteorder[0] = rffi.cast(rffi.INT, byteorder)
+        pbyteorder[0] = rffi.cast(rffi.INT_real, byteorder)
     return space.newutf8(result, length)
 
 @cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP, CONST_STRING],


More information about the pypy-commit mailing list