Skip to content
This repository was archived by the owner on Jan 7, 2023. It is now read-only.

Commit 69179c7

Browse files
authored
Merge pull request #335 from ndawe/master
Silence cling error in tests and some clarification in docs
2 parents b717b19 + b81d80e commit 69179c7

File tree

4 files changed

+89
-16
lines changed

4 files changed

+89
-16
lines changed

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
include MANIFEST.in
12
recursive-include root_numpy *.root *.h *.cpp *.pyx *.pxi
23
recursive-include examples *.py
34
include *.py
45
include README.rst
56
include LICENSE
7+
global-exclude *.pyc *.pyo *.pyd

root_numpy/_tree.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,20 @@ def root2array(filenames,
153153
``length``. This truncation is after any object selection performed
154154
with the ``object_selection`` argument.
155155
selection : str, optional (default=None)
156-
Only include entries fulfilling this condition.
156+
Only include entries fulfilling this condition. If the condition
157+
evaluates to multiple values per tree entry (e.g. conditions on array
158+
branches) then an entry will be included if the condition evaluates to
159+
true for at least one array element.
157160
object_selection : dict, optional (default=None)
158161
A dictionary mapping selection strings to branch names or lists of
159-
branch names. Only elements passing the selection strings will be
162+
branch names. Only array elements passing the selection strings will be
160163
included in the output array per entry in the tree. The branches
161-
specified must be variable-length array-type branches.
164+
specified must be variable-length array-type branches and the length of
165+
the selection and branches it acts on must match for each tree entry.
166+
For example ``object_selection={'a > 0': ['a', 'b']}`` will include all
167+
elements of 'a' and corresponding elements of 'b' where 'a > 0' for
168+
each tree entry. 'a' and 'b' must have the same length in every tree
169+
entry.
162170
start, stop, step: int, optional (default=None)
163171
The meaning of the ``start``, ``stop`` and ``step`` parameters is the
164172
same as for Python slices. If a range is supplied (by setting some of
@@ -313,12 +321,20 @@ def tree2array(tree,
313321
``length``. This truncation is after any object selection performed
314322
with the ``object_selection`` argument.
315323
selection : str, optional (default=None)
316-
Only include entries fulfilling this condition.
324+
Only include entries fulfilling this condition. If the condition
325+
evaluates to multiple values per tree entry (e.g. conditions on array
326+
branches) then an entry will be included if the condition evaluates to
327+
true for at least one array element.
317328
object_selection : dict, optional (default=None)
318329
A dictionary mapping selection strings to branch names or lists of
319-
branch names. Only elements passing the selection strings will be
330+
branch names. Only array elements passing the selection strings will be
320331
included in the output array per entry in the tree. The branches
321-
specified must be variable-length array-type branches.
332+
specified must be variable-length array-type branches and the length of
333+
the selection and branches it acts on must match for each tree entry.
334+
For example ``object_selection={'a > 0': ['a', 'b']}`` will include all
335+
elements of 'a' and corresponding elements of 'b' where 'a > 0' for
336+
each tree entry. 'a' and 'b' must have the same length in every tree
337+
entry.
322338
start, stop, step: int, optional (default=None)
323339
The meaning of the ``start``, ``stop`` and ``step`` parameters is the
324340
same as for Python slices. If a range is supplied (by setting some of

root_numpy/tests/__init__.py

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,82 @@
11
import os
2+
import sys
23
import warnings
34
import ROOT
4-
import root_numpy as rnp
55
from numpy.random import RandomState
6+
import tempfile
7+
from contextlib import contextmanager
8+
import root_numpy as rnp
9+
from root_numpy.testdata import get_filepath
10+
import threading
11+
12+
LOCK = threading.RLock()
613

714
ROOT.gErrorIgnoreLevel = ROOT.kFatal
815
warnings.filterwarnings('ignore', category=DeprecationWarning)
916
warnings.filterwarnings('ignore', category=rnp.RootNumpyUnconvertibleWarning)
1017
RNG = RandomState(42)
1118

12-
from root_numpy.testdata import get_filepath
1319

1420
def load(data):
1521
if isinstance(data, list):
1622
return [get_filepath(x) for x in data]
1723
return get_filepath(data)
1824

19-
import tempfile
20-
from contextlib import contextmanager
2125

2226
@contextmanager
2327
def temp():
2428
tmp_fd, tmp_path = tempfile.mkstemp(suffix='.root')
2529
tmp_root = ROOT.TFile.Open(tmp_path, 'recreate')
26-
yield tmp_root
27-
tmp_root.Close()
28-
os.close(tmp_fd)
29-
os.remove(tmp_path)
30+
try:
31+
yield tmp_root
32+
finally:
33+
tmp_root.Close()
34+
os.close(tmp_fd)
35+
os.remove(tmp_path)
36+
37+
38+
@contextmanager
39+
def silence_sout():
40+
LOCK.acquire()
41+
sys.__stdout__.flush()
42+
origstdout = sys.__stdout__
43+
oldstdout_fno = os.dup(sys.__stdout__.fileno())
44+
devnull = os.open(os.devnull, os.O_WRONLY)
45+
newstdout = os.dup(1)
46+
os.dup2(devnull, 1)
47+
os.close(devnull)
48+
sys.__stdout__ = os.fdopen(newstdout, 'w')
49+
try:
50+
yield
51+
finally:
52+
sys.__stdout__ = origstdout
53+
sys.__stdout__.flush()
54+
os.dup2(oldstdout_fno, 1)
55+
LOCK.release()
56+
57+
58+
@contextmanager
59+
def silence_serr():
60+
LOCK.acquire()
61+
sys.__stderr__.flush()
62+
origstderr = sys.__stderr__
63+
oldstderr_fno = os.dup(sys.__stderr__.fileno())
64+
devnull = os.open(os.devnull, os.O_WRONLY)
65+
newstderr = os.dup(2)
66+
os.dup2(devnull, 2)
67+
os.close(devnull)
68+
sys.__stderr__ = os.fdopen(newstderr, 'w')
69+
try:
70+
yield
71+
finally:
72+
sys.__stderr__ = origstderr
73+
sys.__stderr__.flush()
74+
os.dup2(oldstderr_fno, 2)
75+
LOCK.release()
76+
77+
78+
@contextmanager
79+
def silence():
80+
with silence_sout():
81+
with silence_serr():
82+
yield

root_numpy/tests/test_evaluate.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import root_numpy as rnp
33
from numpy.testing import assert_array_equal
44
from nose.tools import assert_raises
5-
from . import RNG
5+
from . import RNG, silence_serr
66

77

88
def test_evaluate_func():
@@ -39,7 +39,9 @@ def test_evaluate_func():
3939
assert_raises(ValueError, rnp.evaluate, f3, arr_1d)
4040
assert_raises(ValueError, rnp.evaluate, f3, arr_2d)
4141

42-
assert_raises(ValueError, rnp.evaluate, "f", arr_1d)
42+
with silence_serr(): # silence cling error
43+
assert_raises(ValueError, rnp.evaluate, "f", arr_1d)
44+
4345
assert_raises(ValueError, rnp.evaluate, "x*y", arr_1d)
4446
assert_raises(ValueError, rnp.evaluate, "x", arr_2d)
4547
assert_raises(ValueError, rnp.evaluate, "x*y", arr_3d)

0 commit comments

Comments
 (0)