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