ATLAS Offline Software
silence.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4 
5 
6 from contextlib import contextmanager, nested
7 from threading import Thread
8 
9 from tempfile import mkdtemp
10 from os.path import join as pjoin
11 from os import (dup, fdopen, open as osopen, O_NONBLOCK, O_RDONLY, remove,
12  rmdir, mkfifo)
13 from fcntl import fcntl, F_GETFL, F_SETFL
14 from select import select
15 from sys import stdout, stderr
16 
17 from ctypes import PyDLL, CDLL, c_void_p, c_char_p, py_object
18 
19 pyapi = PyDLL(None)
20 this_exe = CDLL(None)
21 
22 def make_fn(what, res, *args):
23  what.restype = res
24  what.argtypes = args
25  return what
26 
27 FILE_p = c_void_p
28 
29 PyFile_AsFile = make_fn(pyapi.PyFile_AsFile, FILE_p, py_object)
30 freopen = make_fn(this_exe.freopen, FILE_p, c_char_p, c_char_p, FILE_p)
31 
32 @contextmanager
33 def fifo():
34  """
35  Create a fifo in a temporary place.
36  """
37  tmpdir = mkdtemp()
38  filename = pjoin(tmpdir, 'myfifo')
39  try:
40  mkfifo(filename)
41  except OSError as e:
42  print("Failed to create FIFO: %s" % e, file=stderr)
43  raise
44  else:
45  try:
46  yield filename
47  finally:
48  remove(filename)
49  rmdir(tmpdir)
50 
51 def set_blocking(fd):
52  """
53  Set FD to be blocking
54  """
55  flags = fcntl(fd, F_GETFL)
56  if flags & O_NONBLOCK:
57  flags ^= O_NONBLOCK
58  fcntl(fd, F_SETFL, flags)
59 
60 def reader_thread_func(filename, filter_, real_stdout, filt_content):
61  """
62  Sit there, reading lines from the pipe `filename`, sending those for which
63  `filter_()` returns False to `real_stdout`
64  """
65  with fdopen(osopen(filename, O_NONBLOCK | O_RDONLY)) as fd:
66  while True:
67  rlist, _, _ = select([fd], [], [])
68 
69  line = fd.readline()
70  if not line:
71  break
72 
73  elif filter_(line):
74  filt_content.write(line)
75  else:
76  real_stdout.write(line)
77 
78 @contextmanager
80  """
81  Operate a read_thread_func in another thread. Block with statement exit
82  until the function completes.
83  """
84  reader_thread = Thread(target=reader_thread_func, args=args)
85  reader_thread.start()
86  try:
87  yield
88  finally:
89  reader_thread.join()
90 
91 @contextmanager
92 def silence(filter_=lambda line: True, file_=stdout):
93  """
94  Prevent lines matching `filter_` ending up on `file_` (defaults to stdout)
95  """
96  if not filter_:
97  yield
98  return
99 
100  import io
101  file = io.IOBase
102  if not isinstance(file_, file):
103  # Unable to filter because it's not a file instance.
104  yield
105  return
106 
107  saved_stdout = dup(file_.fileno())
108  stdout_file = PyFile_AsFile(file_)
109 
110  from io import StringIO
111  filt_content = StringIO()
112 
113  with nested(fdopen(saved_stdout, "w"), fifo()) as (real_stdout, filename):
114  try:
115  tfr = threaded_file_reader(filename, filter_,
116  real_stdout, filt_content)
117  with tfr:
118  # Redirect stdout to pipe
119  freopen(filename, "w", stdout_file)
120  try:
121  yield filt_content
122  finally:
123  # Redirect stdout back to it's original place
124  freopen("/dev/fd/%i" % saved_stdout, "w", stdout_file)
125 
126  except Exception:
127  print("Hit an exception. Filtered content:")
128  print(filt_content.getvalue())
129  raise
130 
131 @contextmanager
132 def silence_sout_serr(filter_):
133  from sys import stdout, stderr
134  with nested(silence(filter_, stdout), silence(filter_, stderr)) as (so, se):
135  yield so, se
136 
137 def test():
138 
139  def filter_hello(line):
140  if line.startswith("Data source lookup using"):
141  return True
142 
143  print("Before with block..")
144 
145  with silence(filter_hello):
146  from DQUtils.db import Databases
147  f = Databases.get_folder("DQMFONL")
148  print("Sensible stuff!")
149 
150  print("f =", f)
151 
152  print("I am after the silence block")
153 
155 
156  print("Before silence.")
157  try:
158  with silence() as filt_content:
159  print("Hmm.")
160  raise RuntimeError("Error.")
161  except Exception:
162  pass
163  print("After silence")
164  print("Stuff?", len(filt_content.getvalue()))
165 
166 if __name__ == "__main__":
167  # test()
python.ext.silence.threaded_file_reader
def threaded_file_reader(*args)
Definition: silence.py:79
python.ext.silence.set_blocking
def set_blocking(fd)
Definition: silence.py:51
python.ext.silence.fifo
def fifo()
Definition: silence.py:33
python.ext.silence.freopen
def freopen
Definition: silence.py:30
python.ext.silence.silence_sout_serr
def silence_sout_serr(filter_)
Definition: silence.py:132
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
python.ext.silence.test_with_exception
def test_with_exception()
Definition: silence.py:154
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
python.ext.silence.PyFile_AsFile
def PyFile_AsFile
Definition: silence.py:29
python.ext.silence.silence
def silence(filter_=lambda line:True, file_=stdout)
Definition: silence.py:92
python.ext.silence.test
def test()
Definition: silence.py:137
python.ext.silence.make_fn
def make_fn(what, res, *args)
Definition: silence.py:22
DerivationFramework::ClustersInCone::select
void select(const xAOD::IParticle *particle, const float coneSize, const xAOD::CaloClusterContainer *clusters, std::vector< bool > &mask)
Definition: ClustersInCone.cxx:14
python.ext.silence.reader_thread_func
def reader_thread_func(filename, filter_, real_stdout, filt_content)
Definition: silence.py:60