Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r56419:4d1ca3adc5d3
Date: 2012-07-23 20:28 -0700
http://bitbucket.org/pypy/pypy/changeset/4d1ca3adc5d3/
Log: optimized I/O for CINT backend
diff --git a/pypy/module/cppyy/capi/cint_capi.py
b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -140,39 +140,58 @@
# return control back to the original, unpythonized overload
return tree_class.get_overload("Branch").call(w_self, args_w)
+def activate_branch(space, w_branch):
+ w_branches = space.call_method(w_branch, "GetListOfBranches")
+ for i in range(space.int_w(space.call_method(w_branches,
"GetEntriesFast"))):
+ w_b = space.call_method(w_branches, "At", space.wrap(i))
+ activate_branch(space, w_b)
+ space.call_method(w_branch, "SetStatus", space.wrap(1))
+ space.call_method(w_branch, "ResetReadEntry")
+
+@unwrap_spec(args_w='args_w')
+def ttree_getattr(space, w_self, args_w):
+ """Specialized __getattr__ for TTree's that allows switching on/off the
+ reading of individual branchs."""
+
+ from pypy.module.cppyy import interp_cppyy
+ tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self)
+
+ # setup branch as a data member and enable it for reading
+ space = tree.space # holds the class cache in State
+ w_branch = space.call_method(w_self, "GetBranch", args_w[0])
+ w_klassname = space.call_method(w_branch, "GetClassName")
+ klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname))
+ w_obj = klass.construct()
+ #space.call_method(w_branch, "SetStatus", space.wrap(1))
+ activate_branch(space, w_branch)
+ space.call_method(w_branch, "SetObject", w_obj)
+ space.call_method(w_branch, "GetEntry", space.wrap(0))
+ space.setattr(w_self, args_w[0], w_obj)
+ return w_obj
+
class W_TTreeIter(Wrappable):
def __init__(self, space, w_tree):
- self.current = 0
+
+ from pypy.module.cppyy import interp_cppyy
+ tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree)
+ self.tree = tree.get_cppthis(tree.cppclass)
self.w_tree = w_tree
- from pypy.module.cppyy import interp_cppyy
- tree = space.interp_w(interp_cppyy.W_CPPInstance, self.w_tree)
- self.tree = tree.get_cppthis(tree.cppclass)
+
self.getentry = tree.cppclass.get_overload("GetEntry").functions[0]
+ self.current = 0
+ self.maxentry = space.int_w(space.call_method(w_tree,
"GetEntriesFast"))
- # setup data members if this is the first iteration time
- try:
- space.getattr(w_tree, space.wrap("_pythonized"))
- except OperationError:
- self.space = space = tree.space # holds the class cache in
State
- w_branches = space.call_method(w_tree, "GetListOfBranches")
- for i in range(space.int_w(space.call_method(w_branches,
"GetEntriesFast"))):
- w_branch = space.call_method(w_branches, "At", space.wrap(i))
- w_name = space.call_method(w_branch, "GetName")
- w_klassname = space.call_method(w_branch, "GetClassName")
- klass = interp_cppyy.scope_byname(space,
space.str_w(w_klassname))
- w_obj = klass.construct()
- space.call_method(w_branch, "SetObject", w_obj)
- # cache the object and define this tree pythonized
- space.setattr(w_tree, w_name, w_obj)
- space.setattr(w_tree, space.wrap("_pythonized"), space.w_True)
+ space = self.space = tree.space # holds the class cache in
State
+ space.call_method(w_tree, "SetBranchStatus", space.wrap("*"),
space.wrap(0))
def iter_w(self):
return self.space.wrap(self)
def next_w(self):
- w_bytes_read = self.getentry.call(self.tree,
[self.space.wrap(self.current)])
- if not self.space.is_true(w_bytes_read):
+ if self.current == self.maxentry:
raise OperationError(self.space.w_StopIteration, self.space.w_None)
+ # TODO: check bytes read?
+ self.getentry.call(self.tree, [self.space.wrap(self.current)])
self.current += 1
return self.w_tree
@@ -194,8 +213,9 @@
"NOT_RPYTHON"
### TTree
- _pythonizations['ttree_Branch'] = space.wrap(interp2app(ttree_Branch))
- _pythonizations['ttree_iter'] = space.wrap(interp2app(ttree_iter))
+ _pythonizations['ttree_Branch'] = space.wrap(interp2app(ttree_Branch))
+ _pythonizations['ttree_iter'] = space.wrap(interp2app(ttree_iter))
+ _pythonizations['ttree_getattr'] = space.wrap(interp2app(ttree_getattr))
# callback coming in when app-level bound classes have been created
def pythonize(space, name, w_pycppclass):
@@ -209,6 +229,7 @@
space.getattr(w_pycppclass, space.wrap("Branch")))
space.setattr(w_pycppclass, space.wrap("Branch"),
_pythonizations["ttree_Branch"])
space.setattr(w_pycppclass, space.wrap("__iter__"),
_pythonizations["ttree_iter"])
+ space.setattr(w_pycppclass, space.wrap("__getattr__"),
_pythonizations["ttree_getattr"])
elif name[0:8] == "TVectorT": # TVectorT<> template
space.setattr(w_pycppclass, space.wrap("__len__"),
diff --git a/pypy/module/cppyy/test/test_cint.py
b/pypy/module/cppyy/test/test_cint.py
--- a/pypy/module/cppyy/test/test_cint.py
+++ b/pypy/module/cppyy/test/test_cint.py
@@ -132,7 +132,7 @@
import cppyy
return cppyy.load_reflection_info(%r)""" % (iotypes_dct,))
- def test01_write_stdvector( self ):
+ def test01_write_stdvector(self):
"""Test writing of a single branched TTree with an
std::vector<double>"""
from cppyy import gbl # bootstraps, only needed for tests
@@ -168,6 +168,7 @@
i = 0
for event in mytree:
+ assert len(event.mydata) == self.M
for entry in event.mydata:
assert i == int(entry)
i += 1
@@ -209,16 +210,80 @@
f = TFile(self.fname)
mytree = f.Get(self.tname)
+ j = 1
for event in mytree:
i = 0
+ assert len(event.data.get_floats()) == j*self.M
for entry in event.data.get_floats():
assert i == int(entry)
i += 1
+ k = 1
+ assert len(event.data.get_tuples()) == j
for mytuple in event.data.get_tuples():
i = 0
+ assert len(mytuple) == k*self.M
for entry in mytuple:
assert i == int(entry)
i += 1
+ k += 1
+ j += 1
+ assert j-1 == self.N
#
f.Close()
+
+ def test05_branch_activation(self):
+ """Test of automatic branch activation"""
+
+ from cppyy import gbl # bootstraps, only needed for tests
+ from cppyy.gbl import TFile, TTree
+ from cppyy.gbl.std import vector
+
+ L = 5
+
+ # writing
+ f = TFile(self.fname, "RECREATE")
+ mytree = TTree(self.tname, self.title)
+ mytree._python_owns = False
+
+ for i in range(L):
+ v = vector("double")()
+ mytree.Branch("mydata_%d"%i, v.__class__.__name__, v)
+ mytree.__dict__["v_%d"%i] = v
+
+ for i in range(self.N):
+ for k in range(L):
+ v = mytree.__dict__["v_%d"%k]
+ for j in range(self.M):
+ mytree.__dict__["v_%d"%k].push_back(i*self.M+j*L+k)
+ mytree.Fill()
+ for k in range(L):
+ v = mytree.__dict__["v_%d"%k]
+ v.clear()
+ f.Write()
+ f.Close()
+
+ del mytree, f
+ import gc
+ gc.collect()
+
+ # reading
+ f = TFile(self.fname)
+ mytree = f.Get(self.tname)
+
+ # force (initial) disabling of all branches
+ mytree.SetBranchStatus("*",0);
+
+ i = 0
+ for event in mytree:
+ for k in range(L):
+ j = 0
+ data = getattr(mytree, "mydata_%d"%k)
+ assert len(data) == self.M
+ for entry in data:
+ assert entry == i*self.M+j*L+k
+ j += 1
+ assert j == self.M
+ i += 1
+ assert i == self.N
+
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit