Skip to content

Commit d0ee9ee

Browse files
author
Vasileios Karakasis
authored
Merge pull request #1062 from vkarak/feat/sn-print
[feat] Add a `print()` sanity function
2 parents 091b3e3 + d2ffb49 commit d0ee9ee

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

reframe/utility/sanity.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import glob as pyglob
6363
import itertools
6464
import re
65+
import sys
6566

6667
import reframe.utility as util
6768
from reframe.core.deferrable import deferrable, _DeferredExpression
@@ -182,6 +183,36 @@ def min(*args):
182183
return builtins.min(*args)
183184

184185

186+
@deferrable
187+
def print(*objects, sep=' ', end='\n', file=None, flush=False):
188+
'''Replacement for the built-in :func:`print() <python:print>` function.
189+
190+
The only difference is that this function returns the ``objects``, so that
191+
you can use it transparently inside a complex sanity expression. For
192+
example, you could write the following to print the matches returned from
193+
the :func:`extractall()` function:
194+
195+
.. code:: python
196+
197+
self.sanity_patterns = sn.assert_eq(
198+
sn.count(sn.print(sn.extract_all(...))), 10
199+
)
200+
201+
If ``file`` is None, :func:`print` will print its arguments to the
202+
standard output. Unlike the builtin :func:`print() <python:print>`
203+
function, we don't bind the ``file`` argument to :attr:`sys.stdout` by
204+
default. This would capture :attr:`sys.stdout` at the time this function
205+
is defined and would prevent it from seeing changes to :attr:`sys.stdout`,
206+
such as redirects, in the future.
207+
'''
208+
209+
if file is None:
210+
file = sys.stdout
211+
212+
builtins.print(*objects, sep=sep, end=end, file=file, flush=flush)
213+
return objects
214+
215+
185216
@deferrable
186217
def reversed(seq):
187218
'''Replacement for the built-in

unittests/test_sanity_functions.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
import contextlib
2+
import io
13
import itertools
24
import os
5+
import sys
36
import unittest
7+
48
from tempfile import NamedTemporaryFile
59

10+
611
import reframe.utility.sanity as sn
712
from reframe.core.exceptions import SanityError
813
from unittests.fixtures import TEST_RESOURCES_CHECKS
@@ -124,6 +129,42 @@ def test_min(self):
124129
l.append(0)
125130
self.assertEqual(0, sn.min(dl))
126131

132+
def test_print_stdout(self):
133+
stdout = io.StringIO()
134+
with contextlib.redirect_stdout(stdout):
135+
x, y = sn.evaluate(sn.print(1, sn.defer(2)))
136+
137+
assert stdout.getvalue() == '1 2\n'
138+
assert x == 1
139+
assert y == 2
140+
141+
def test_print_stderr(self):
142+
stderr = io.StringIO()
143+
with contextlib.redirect_stderr(stderr):
144+
x, y = sn.evaluate(sn.print(1, sn.defer(2), file=sys.stderr))
145+
146+
assert stderr.getvalue() == '1 2\n'
147+
assert x == 1
148+
assert y == 2
149+
150+
def test_print_separator(self):
151+
stdout = io.StringIO()
152+
with contextlib.redirect_stdout(stdout):
153+
x, y = sn.evaluate(sn.print(1, sn.defer(2), sep='|'))
154+
155+
assert stdout.getvalue() == '1|2\n'
156+
assert x == 1
157+
assert y == 2
158+
159+
def test_print_end(self):
160+
stdout = io.StringIO()
161+
with contextlib.redirect_stdout(stdout):
162+
x, y = sn.evaluate(sn.print(1, sn.defer(2), end=''))
163+
164+
assert stdout.getvalue() == '1 2'
165+
assert x == 1
166+
assert y == 2
167+
127168
def test_reversed(self):
128169
l = [1, 2, 3]
129170
dr = sn.reversed(l)

0 commit comments

Comments
 (0)