import os import sys import errno import signal import resource import subprocess from collections import deque def and_(iter_): """Do an and logic condition over the iterable element. :param iterable iter: meat for condition """ for i in iter_: if not i: return False return True def subproc_call(args, stdin=None): """ :param args: arguments for subprocess call :param stdin: stdin data as string """ proc = subprocess.Popen(args, bufsize=4096, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) result, _ = proc.communicate(stdin) if proc.returncode != 0: raise subprocess.CalledProcessError(proc.returncode, 'Error while executing command') return result class SocketBuffer(deque): """Holds bytes in a list. This class don't handle maximum size but instead give help like handling count automatically. """ def __init__(self, max_len=8 * 64 * 1024): deque.__init__(self) self.max_len = max_len self.current_len = 0 def append(self, x): deque.append(self, x) self.current_len += len(x) def appendleft(self, x): deque.appendleft(self, x) self.current_len += len(x) def clear(self): deque.clear(self) self.current_len = 0 def extend(self, iterable): raise NotImplementedError def extendleft(self, iterable): raise NotImplementedError def pop(self): elt = deque.pop(self) self.current_len -= len(elt) return elt def popleft(self): elt = deque.popleft(self) self.current_len -= len(elt) return elt def remove(value): raise NotImplementedError def reverse(self): raise NotImplementedError def rotate(self, n): raise NotImplementedError def is_full(self): return self.current_len >= self.max_len def is_empty(self): return self.current_len == 0 class Singleton(type): """Singleton metaclass.""" def __init__(cls, name, bases, dict): super(Singleton, cls).__init__(cls, bases, dict) cls._instance = None def __call__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super(Singleton, cls).__call__(*args, **kwargs) return cls._instance def close_fds(exclude_fds=None, debug=False): """Close all fds uneeded fds in child when using fork. :param exclude_fds: list of file descriptors that should not be closed (0, 1, 2 must not be set here, see debug) :param bool debug: indicates if std in/out should be left open (usually for debuging purpose) """ # get max fd limit = resource.getrlimit(resource.RLIMIT_NOFILE)[1] if limit == resource.RLIM_INFINITY: max_fd = 2048 else: max_fd = limit if exclude_fds is None: exclude_fds = [] if debug: exclude_fds += [0, 1, 2] # debug for fd in xrange(max_fd, -1, -1): if fd in exclude_fds: continue try: os.close(fd) except OSError as exc: if exc.errno != errno.EBADF: raise # wasn't open if not debug: sys.stdin = open(os.devnull) sys.stdout = open(os.devnull) sys.stderr = open(os.devnull) assert sys.stdin.fileno() == 0 assert sys.stdout.fileno() == 1 assert sys.stderr.fileno() == 2 def set_signal_map(map_): """Set signal map in fork children. :param mapping map_: (signal code, handler)... :returns: old handlers as dict """ previous_handlers = dict() for sig, handler in map_.iteritems(): previous_handlers[sig] = signal.signal(sig, handler) return previous_handlers sig_names = dict((k, v) for v, k in signal.__dict__.iteritems() if v.startswith('SIG')) def num_to_sig(num): """Returns signal name. :param num: signal number """ return sig_names.get(num, 'Unknown signal')