[pypy-commit] pypy reflex-support: o) more informative dir() method for namespaces
wlav
noreply at buildbot.pypy.org
Sun Jul 1 23:31:03 CEST 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r55888:3c2792308ebf
Date: 2012-06-29 15:51 -0700
http://bitbucket.org/pypy/pypy/changeset/3c2792308ebf/
Log: o) more informative dir() method for namespaces o) allow importing
from namespaces (once loaded)
diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -39,6 +39,20 @@
c_load_dictionary = backend.c_load_dictionary
# name to opaque C++ scope representation ------------------------------------
+_c_num_scopes = rffi.llexternal(
+ "cppyy_num_scopes",
+ [C_SCOPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_num_scopes(cppscope):
+ return _c_num_scopes(cppscope.handle)
+_c_scope_name = rffi.llexternal(
+ "cppyy_scope_name",
+ [C_SCOPE, rffi.INT], rffi.CCHARP,
+ compilation_info = backend.eci)
+def c_scope_name(cppscope, iscope):
+ return charp2str_free(_c_scope_name(cppscope.handle, iscope))
+
_c_resolve_name = rffi.llexternal(
"cppyy_resolve_name",
[rffi.CCHARP], rffi.CCHARP,
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
@@ -15,6 +15,9 @@
typedef void* (*cppyy_methptrgetter_t)(cppyy_object_t);
/* name to opaque C++ scope representation -------------------------------- */
+ int cppyy_num_scopes(cppyy_scope_t parent);
+ char* cppyy_scope_name(cppyy_scope_t parent, int iscope);
+
char* cppyy_resolve_name(const char* cppitem_name);
cppyy_scope_t cppyy_get_scope(const char* scope_name);
cppyy_type_t cppyy_get_template(const char* template_name);
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
@@ -533,6 +533,18 @@
def is_namespace(self):
return self.space.w_True
+ def ns__dir__(self):
+ alldir = []
+ for i in range(capi.c_num_scopes(self)):
+ alldir.append(capi.c_scope_name(self, i))
+ for i in range(capi.c_num_methods(self)):
+ idx = capi.c_method_index_at(self, i)
+ alldir.append(capi.c_method_name(self, idx))
+ for i in range(capi.c_num_datamembers(self)):
+ alldir.append(capi.c_datamember_name(self, i))
+ return self.space.wrap(alldir)
+
+
W_CPPNamespace.typedef = TypeDef(
'CPPNamespace',
get_method_names = interp2app(W_CPPNamespace.get_method_names),
@@ -540,6 +552,7 @@
get_datamember_names = interp2app(W_CPPNamespace.get_datamember_names),
get_datamember = interp2app(W_CPPNamespace.get_datamember, unwrap_spec=['self', str]),
is_namespace = interp2app(W_CPPNamespace.is_namespace),
+ __dir__ = interp2app(W_CPPNamespace.ns__dir__),
)
W_CPPNamespace.typedef.acceptable_as_base_class = False
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
@@ -1,6 +1,6 @@
# NOT_RPYTHON
import cppyy
-import types
+import types, sys
# For now, keep namespaces and classes separate as namespaces are extensible
@@ -15,7 +15,8 @@
raise AttributeError("%s object has no attribute '%s'" % (self, name))
class CppyyNamespaceMeta(CppyyScopeMeta):
- pass
+ def __dir__(cls):
+ return cls._cpp_proxy.__dir__()
class CppyyClass(CppyyScopeMeta):
pass
@@ -124,6 +125,8 @@
setattr(pycppns, dm, pydm)
setattr(metans, dm, pydm)
+ modname = pycppns.__name__.replace('::', '.')
+ sys.modules['cppyy.gbl.'+modname] = pycppns
return pycppns
def _drop_cycles(bases):
@@ -375,9 +378,11 @@
# creation of global functions may cause the creation of classes in the global
# namespace, so gbl must exist at that point to cache them)
gbl = make_cppnamespace(None, "::", None, False) # global C++ namespace
+sys.modules['cppyy.gbl'] = gbl
# mostly for the benefit of the CINT backend, which treats std as special
gbl.std = make_cppnamespace(None, "std", None, False)
+sys.modules['cppyy.gbl.std'] = gbl.std
# user-defined pythonizations interface
_pythonizations = {}
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
@@ -53,6 +53,17 @@
/* name to opaque C++ scope representation -------------------------------- */
+int cppyy_num_scopes(cppyy_scope_t handle) {
+ Reflex::Scope s = scope_from_handle(handle);
+ return s.SubScopeSize();
+}
+
+char* cppyy_scope_name(cppyy_scope_t handle, int iscope) {
+ Reflex::Scope s = scope_from_handle(handle);
+ std::string name = s.SubScopeAt(iscope).Name(Reflex::F);
+ return cppstring_to_cstring(name);
+}
+
char* cppyy_resolve_name(const char* cppitem_name) {
Reflex::Scope s = Reflex::Scope::ByName(cppitem_name);
if (s.IsEnum())
diff --git a/pypy/module/cppyy/test/fragile.h b/pypy/module/cppyy/test/fragile.h
--- a/pypy/module/cppyy/test/fragile.h
+++ b/pypy/module/cppyy/test/fragile.h
@@ -77,4 +77,14 @@
void fglobal(int, double, char);
+namespace nested1 {
+ class A {};
+ namespace nested2 {
+ class A {};
+ namespace nested3 {
+ class A {};
+ } // namespace nested3
+ } // namespace nested2
+} // namespace nested1
+
} // namespace fragile
diff --git a/pypy/module/cppyy/test/fragile.xml b/pypy/module/cppyy/test/fragile.xml
--- a/pypy/module/cppyy/test/fragile.xml
+++ b/pypy/module/cppyy/test/fragile.xml
@@ -1,8 +1,14 @@
<lcgdict>
<namespace name="fragile" />
+ <namespace name="fragile::nested1" />
+ <namespace name="fragile::nested1::nested2" />
+ <namespace name="fragile::nested1::nested2::nested3" />
<class pattern="fragile::[A-Z]" />
+ <class name="fragile::nested1::A" />
+ <class name="fragile::nested1::nested2::A" />
+ <class name="fragile::nested1::nested2::nested3::A" />
<variable name="fragile::gI" />
diff --git a/pypy/module/cppyy/test/test_fragile.py b/pypy/module/cppyy/test/test_fragile.py
--- a/pypy/module/cppyy/test/test_fragile.py
+++ b/pypy/module/cppyy/test/test_fragile.py
@@ -19,7 +19,7 @@
cls.space = space
env = os.environ
cls.w_test_dct = space.wrap(test_dct)
- cls.w_datatypes = cls.space.appexec([], """():
+ cls.w_fragile = cls.space.appexec([], """():
import cppyy
return cppyy.load_reflection_info(%r)""" % (test_dct, ))
@@ -194,3 +194,53 @@
f = fragile.fglobal
assert f.__doc__ == "void fragile::fglobal(int, double, char)"
+
+ def test11_dir(self):
+ """Test __dir__ method"""
+
+ import cppyy
+
+ members = dir(cppyy.gbl.fragile)
+ assert 'A' in members
+ assert 'B' in members
+ assert 'C' in members
+ assert 'D' in members # classes
+
+ assert 'fglobal' in members # function
+ assert 'nested1' in members # namespace
+ assert 'gI'in members # variable
+
+ def test12_imports(self):
+ """Test ability to import from namespace (or fail with ImportError)"""
+
+ import cppyy
+
+ # TODO: namespaces aren't loaded (and thus not added to sys.modules)
+ # with just the from ... import statement; actual use is needed
+ from cppyy.gbl import fragile
+
+ def fail_import():
+ from cppyy.gbl import does_not_exist
+ raises(ImportError, fail_import)
+
+ from cppyy.gbl.fragile import A, B, C, D
+ assert cppyy.gbl.fragile.A is A
+ assert cppyy.gbl.fragile.B is B
+ assert cppyy.gbl.fragile.C is C
+ assert cppyy.gbl.fragile.D is D
+
+ # according to warnings, can't test "import *" ...
+
+ from cppyy.gbl.fragile import nested1
+ assert cppyy.gbl.fragile.nested1 is nested1
+
+ from cppyy.gbl.fragile.nested1 import A, nested2
+ assert cppyy.gbl.fragile.nested1.A is A
+ assert cppyy.gbl.fragile.nested1.nested2 is nested2
+
+ from cppyy.gbl.fragile.nested1.nested2 import A, nested3
+ assert cppyy.gbl.fragile.nested1.nested2.A is A
+ assert cppyy.gbl.fragile.nested1.nested2.nested3 is nested3
+
+ from cppyy.gbl.fragile.nested1.nested2.nested3 import A
+ assert cppyy.gbl.fragile.nested1.nested2.nested3.A is nested3.A
More information about the pypy-commit
mailing list