[pypy-commit] pypy py3k: merge default (ea86924e88fb)
pjenvey
noreply at buildbot.pypy.org
Fri Apr 25 01:59:38 CEST 2014
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r70952:e0ce5503a026
Date: 2014-04-24 16:58 -0700
http://bitbucket.org/pypy/pypy/changeset/e0ce5503a026/
Log: merge default (ea86924e88fb)
diff --git a/lib-python/2.7/test/test_itertools.py b/lib-python/2.7/test/test_itertools.py
--- a/lib-python/2.7/test/test_itertools.py
+++ b/lib-python/2.7/test/test_itertools.py
@@ -139,7 +139,6 @@
@test_support.impl_detail("tuple reuse is specific to CPython")
def test_combinations_tuple_reuse(self):
- # Test implementation detail: tuple re-use
self.assertEqual(len(set(map(id, combinations('abcde', 3)))), 1)
self.assertNotEqual(len(set(map(id, list(combinations('abcde', 3))))), 1)
@@ -211,7 +210,6 @@
@test_support.impl_detail("tuple reuse is specific to CPython")
def test_combinations_with_replacement_tuple_reuse(self):
- # Test implementation detail: tuple re-use
cwr = combinations_with_replacement
self.assertEqual(len(set(map(id, cwr('abcde', 3)))), 1)
self.assertNotEqual(len(set(map(id, list(cwr('abcde', 3))))), 1)
@@ -278,7 +276,6 @@
@test_support.impl_detail("tuple reuse is specific to CPython")
def test_permutations_tuple_reuse(self):
- # Test implementation detail: tuple re-use
self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1)
self.assertNotEqual(len(set(map(id, list(permutations('abcde', 3))))), 1)
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -560,6 +560,12 @@
Fixing these bootstrap problems is on the TODO list.
The global namespace is ``cppyy.gbl``.
+* **NULL**: Is represented as ``cppyy.gbl.nullptr``.
+ In C++11, the keyword ``nullptr`` is used to represent ``NULL``.
+ For clarity of intent, it is recommended to use this instead of ``None``
+ (or the integer ``0``, which can serve in some cases), as ``None`` is better
+ understood as ``void`` in C++.
+
* **operator conversions**: If defined in the C++ class and a python
equivalent exists (i.e. all builtin integer and floating point types, as well
as ``bool``), it will map onto that python conversion.
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -66,58 +66,26 @@
Reflex
======
-This method is still experimental. It adds the `cppyy`_ module.
-The method works by using the `Reflex package`_ to provide reflection
-information of the C++ code, which is then used to automatically generate
-bindings at runtime.
-From a python standpoint, there is no difference between generating bindings
-at runtime, or having them "statically" generated and available in scripts
-or compiled into extension modules: python classes and functions are always
-runtime structures, created when a script or module loads.
+The builtin `cppyy`_ module uses reflection information, provided by
+`Reflex`_ (which needs to be `installed separately`_), of C/C++ code to
+automatically generate bindings at runtime.
+In Python, classes and functions are always runtime structures, so when they
+are generated matters not for performance.
However, if the backend itself is capable of dynamic behavior, it is a much
-better functional match to python, allowing tighter integration and more
-natural language mappings.
-Full details are `available here`_.
+better functional match, allowing tighter integration and more natural
+language mappings.
+
+The `cppyy`_ module is written in RPython, thus PyPy's JIT is able to remove
+most cross-language call overhead.
+
+`Full details`_ are `available here`_.
.. _`cppyy`: cppyy.html
-.. _`reflex-support`: cppyy.html
-.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex
+.. _`installed separately`: http://cern.ch/wlav/reflex-2013-08-14.tar.bz2
+.. _`Reflex`: http://root.cern.ch/drupal/content/reflex
+.. _`Full details`: cppyy.html
.. _`available here`: cppyy.html
-Pros
-----
-
-The cppyy module is written in RPython, which makes it possible to keep the
-code execution visible to the JIT all the way to the actual point of call into
-C++, thus allowing for a very fast interface.
-Reflex is currently in use in large software environments in High Energy
-Physics (HEP), across many different projects and packages, and its use can be
-virtually completely automated in a production environment.
-One of its uses in HEP is in providing language bindings for CPython.
-Thus, it is possible to use Reflex to have bound code work on both CPython and
-on PyPy.
-In the medium-term, Reflex will be replaced by `cling`_, which is based on
-`llvm`_.
-This will affect the backend only; the python-side interface is expected to
-remain the same, except that cling adds a lot of dynamic behavior to C++,
-enabling further language integration.
-
-.. _`cling`: http://root.cern.ch/drupal/content/cling
-.. _`llvm`: http://llvm.org/
-
-Cons
-----
-
-C++ is a large language, and cppyy is not yet feature-complete.
-Still, the experience gained in developing the equivalent bindings for CPython
-means that adding missing features is a simple matter of engineering, not a
-question of research.
-The module is written so that currently missing features should do no harm if
-you don't use them, if you do need a particular feature, it may be necessary
-to work around it in python or with a C++ helper function.
-Although Reflex works on various platforms, the bindings with PyPy have only
-been tested on Linux.
-
RPython Mixed Modules
=====================
diff --git a/pypy/module/cppyy/src/dummy_backend.cxx b/pypy/module/cppyy/src/dummy_backend.cxx
--- a/pypy/module/cppyy/src/dummy_backend.cxx
+++ b/pypy/module/cppyy/src/dummy_backend.cxx
@@ -38,6 +38,24 @@
typedef std::map<cppyy_scope_t, Cppyy_PseudoClassInfo> Scopes_t;
static Scopes_t s_scopes;
+class PseudoExample01 {
+public:
+ PseudoExample01() : m_somedata(-99) {}
+ PseudoExample01(int a) : m_somedata(a) {}
+ PseudoExample01(const PseudoExample01& e) : m_somedata(e.m_somedata) {}
+ PseudoExample01& operator=(const PseudoExample01& e) {
+ if (this != &e) m_somedata = e.m_somedata;
+ return *this;
+ }
+ virtual ~PseudoExample01() {}
+
+public:
+ int m_somedata;
+};
+
+static int example01_last_static_method = 0;
+static int example01_last_constructor = 0;
+
struct Cppyy_InitPseudoReflectionInfo {
Cppyy_InitPseudoReflectionInfo() {
// class example01 --
@@ -46,27 +64,62 @@
std::vector<Cppyy_PseudoMethodInfo> methods;
- // static double staticAddToDouble(double a);
+ // ( 0) static double staticAddToDouble(double a)
std::vector<std::string> argtypes;
argtypes.push_back("double");
methods.push_back(Cppyy_PseudoMethodInfo("staticAddToDouble", argtypes, "double"));
- // static int staticAddOneToInt(int a);
- // static int staticAddOneToInt(int a, int b);
+ // ( 1) static int staticAddOneToInt(int a)
+ // ( 2) static int staticAddOneToInt(int a, int b)
argtypes.clear();
argtypes.push_back("int");
methods.push_back(Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int"));
argtypes.push_back("int");
methods.push_back(Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int"));
- // static int staticAtoi(const char* str);
+ // ( 3) static int staticAtoi(const char* str)
argtypes.clear();
argtypes.push_back("const char*");
methods.push_back(Cppyy_PseudoMethodInfo("staticAtoi", argtypes, "int"));
- // static char* staticStrcpy(const char* strin);
+ // ( 4) static char* staticStrcpy(const char* strin)
methods.push_back(Cppyy_PseudoMethodInfo("staticStrcpy", argtypes, "char*"));
+ // ( 5) static void staticSetPayload(payload* p, double d)
+ // ( 6) static payload* staticCyclePayload(payload* p, double d)
+ // ( 7) static payload staticCopyCyclePayload(payload* p, double d)
+ argtypes.clear();
+ argtypes.push_back("payload*");
+ argtypes.push_back("double");
+ methods.push_back(Cppyy_PseudoMethodInfo("staticSetPayload", argtypes, "void"));
+ methods.push_back(Cppyy_PseudoMethodInfo("staticCyclePayload", argtypes, "payload*"));
+ methods.push_back(Cppyy_PseudoMethodInfo("staticCopyCyclePayload", argtypes, "payload"));
+
+ // ( 8) static int getCount()
+ // ( 9) static void setCount(int)
+ argtypes.clear();
+ methods.push_back(Cppyy_PseudoMethodInfo("getCount", argtypes, "int"));
+ argtypes.push_back("int");
+ methods.push_back(Cppyy_PseudoMethodInfo("setCount", argtypes, "void"));
+
+ // cut-off is used in cppyy_is_static
+ example01_last_static_method = methods.size();
+
+ // (10) example01()
+ // (11) example01(int a)
+ argtypes.clear();
+ methods.push_back(Cppyy_PseudoMethodInfo("example01", argtypes, "constructor"));
+ argtypes.push_back("int");
+ methods.push_back(Cppyy_PseudoMethodInfo("example01", argtypes, "constructor"));
+
+ // cut-off is used in cppyy_is_constructor
+ example01_last_constructor = methods.size();
+
+ // (12) double addDataToDouble(double a)
+ argtypes.clear();
+ argtypes.push_back("double");
+ methods.push_back(Cppyy_PseudoMethodInfo("addDataToDouble", argtypes, "double"));
+
Cppyy_PseudoClassInfo info(methods);
s_scopes[(cppyy_scope_t)s_scope_id] = info;
// -- class example01
@@ -98,47 +151,69 @@
}
+/* memory management ------------------------------------------------------ */
+void cppyy_destruct(cppyy_type_t handle, cppyy_object_t self) {
+ if (handle == s_handles["example01"])
+ delete (PseudoExample01*)self;
+}
+
+
/* method/function dispatching -------------------------------------------- */
-template<typename T>
-static inline T cppyy_call_T(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- T result = T();
+int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ int result = 0;
switch ((long)method) {
- case 0: // double staticAddToDouble(double)
- assert(!self && nargs == 1);
- result = ((CPPYY_G__value*)args)[0].obj.d + 0.01;
- break;
- case 1: // int staticAddOneToInt(int)
+ case 1: // static int staticAddOneToInt(int)
assert(!self && nargs == 1);
result = ((CPPYY_G__value*)args)[0].obj.in + 1;
break;
- case 2: // int staticAddOneToInt(int, int)
+ case 2: // static int staticAddOneToInt(int, int)
assert(!self && nargs == 2);
result = ((CPPYY_G__value*)args)[0].obj.in + ((CPPYY_G__value*)args)[1].obj.in + 1;
break;
- case 3: // int staticAtoi(const char* str)
+ case 3: // static int staticAtoi(const char* str)
assert(!self && nargs == 1);
result = ::atoi((const char*)(*(long*)&((CPPYY_G__value*)args)[0]));
break;
+ case 8: // static int getCount()
+ assert(!self && nargs == 0);
+ // can't actually call this method (would need to resolve example01::count), but
+ // other than the memory tests, most tests just check for 0 at the end
+ result = 0;
+ break;
default:
+ assert(!"method unknown in cppyy_call_i");
break;
}
return result;
}
-int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- return cppyy_call_T<int>(method, self, nargs, args);
-}
-
long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- // char* staticStrcpy(const char* strin)
- const char* strin = (const char*)(*(long*)&((CPPYY_G__value*)args)[0]);
- char* strout = (char*)malloc(::strlen(strin)+1);
- ::strcpy(strout, strin);
- return (long)strout;
+ if ((long)method == 4) { // static char* staticStrcpy(const char* strin)
+ const char* strin = (const char*)(*(long*)&((CPPYY_G__value*)args)[0]);
+ char* strout = (char*)malloc(::strlen(strin)+1);
+ ::strcpy(strout, strin);
+ return (long)strout;
+ }
+ assert(!"method unknown in cppyy_call_l");
+ return 0;
}
double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- return cppyy_call_T<double>(method, self, nargs, args);
+ double result = 0.;
+ switch ((long)method) {
+ case 0: // static double staticAddToDouble(double)
+ assert(!self && nargs == 1);
+ result = ((CPPYY_G__value*)args)[0].obj.d + 0.01;
+ break;
+ case 12: // double addDataToDouble(double a)
+ assert(self && nargs == 1);
+ result = ((PseudoExample01*)self)->m_somedata + ((CPPYY_G__value*)args)[0].obj.d;
+ break;
+ default:
+ assert(!"method unknown in cppyy_call_d");
+ break;
+ }
+ return result;
}
char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
@@ -149,10 +224,31 @@
return strout;
}
+cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t handle, int nargs, void* args) {
+ void* result = 0;
+ if (handle == s_handles["example01"]) {
+ switch ((long)method) {
+ case 10:
+ assert(nargs == 0);
+ result = new PseudoExample01;
+ break;
+ case 11:
+ assert(nargs == 1);
+ result = new PseudoExample01(((CPPYY_G__value*)args)[0].obj.in);
+ break;
+ default:
+ assert(!"method unknown in cppyy_constructor");
+ break;
+ }
+ }
+ return (cppyy_object_t)result;
+}
+
cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
return (cppyy_methptrgetter_t)0;
}
+
/* handling of function argument buffer ----------------------------------- */
void* cppyy_allocate_function_args(size_t nargs) {
CPPYY_G__value* args = (CPPYY_G__value*)malloc(nargs*sizeof(CPPYY_G__value));
@@ -200,7 +296,11 @@
}
int cppyy_has_complex_hierarchy(cppyy_type_t /* handle */) {
- return 1;
+ return 0;
+}
+
+int cppyy_num_bases(cppyy_type_t /*handle*/) {
+ return 0;
}
@@ -252,11 +352,16 @@
/* method properties ----------------------------------------------------- */
-int cppyy_is_constructor(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
+int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t method_index) {
+ if (handle == s_handles["example01"])
+ return example01_last_static_method <= method_index
+ && method_index < example01_last_constructor;
return 0;
}
-int cppyy_is_staticmethod(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
+int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t method_index) {
+ if (handle == s_handles["example01"])
+ return method_index < example01_last_static_method ? 1 : 0;
return 1;
}
diff --git a/pypy/module/cppyy/test/conftest.py b/pypy/module/cppyy/test/conftest.py
--- a/pypy/module/cppyy/test/conftest.py
+++ b/pypy/module/cppyy/test/conftest.py
@@ -7,11 +7,12 @@
if 'dummy' in lcapi.reflection_library:
# run only tests that are covered by the dummy backend and tests
# that do not rely on reflex
- if not item.location[0] in ['test_helper.py', 'test_cppyy.py']:
+ if not ('test_helper.py' in item.location[0] or \
+ 'test_cppyy.py' in item.location[0]):
py.test.skip("genreflex is not installed")
import re
- if item.location[0] == 'test_cppyy.py' and \
- not re.search("test0[1-3]", item.location[2]):
+ if 'test_cppyy.py' in item.location[0] and \
+ not re.search("test0[1-36]", item.location[2]):
py.test.skip("genreflex is not installed")
def pytest_configure(config):
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -330,21 +330,8 @@
def invalid_typecode(space, u, tc):
- # %r not supported in rpython
- #u.raise_exc('invalid typecode in unmarshal: %r' % tc)
- c = ord(tc)
- if c < 16:
- s = '\\x0%x' % c
- elif c < 32 or c > 126:
- s = '\\x%x' % c
- elif tc == '\\':
- s = r'\\'
- else:
- s = tc
- q = "'"
- if s[0] == "'":
- q = '"'
- u.raise_exc('invalid typecode in unmarshal: ' + q + s + q)
+ u.raise_exc("bad marshal data (unknown type code)")
+
def register(codes, func):
"""NOT_RPYTHON"""
diff --git a/pypy/module/marshal/test/test_marshal.py b/pypy/module/marshal/test/test_marshal.py
--- a/pypy/module/marshal/test/test_marshal.py
+++ b/pypy/module/marshal/test/test_marshal.py
@@ -15,11 +15,14 @@
print(repr(s))
x = marshal.loads(s)
assert x == case and type(x) is type(case)
- f = BytesIO()
- marshal.dump(case, f)
- f.seek(0)
- x = marshal.load(f)
- assert x == case and type(x) is type(case)
+
+ import sys
+ if '__pypy__' in sys.builtin_module_names:
+ f = StringIO.StringIO()
+ marshal.dump(case, f)
+ f.seek(0)
+ x = marshal.load(f)
+ assert x == case and type(x) is type(case)
return x
def test_None(self):
@@ -190,8 +193,8 @@
def test_bad_typecode(self):
import marshal
- exc = raises(ValueError, marshal.loads, b'\x01')
- assert r"'\x01'" in str(exc.value)
+ exc = raises(ValueError, marshal.loads, chr(1))
+ assert str(exc.value) == "bad marshal data (unknown type code)"
def test_bad_data(self):
import marshal
More information about the pypy-commit
mailing list