Skip to content
Snippets Groups Projects
utils.py 5.35 KiB
Newer Older
# -*- coding: utf-8 -*-

import os, sys, subprocess
Thibault VINCENT's avatar
Thibault VINCENT committed
from socket import gethostname, gethostbyname
from threading import Lock
from logging import debug

def enum(*sequential, **named):
    '''
    '''
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)


class Enum(dict):
    '''
    Usage example:
    
    $ states = Enum(SLEEPING, CONNECTED="Conn", DISCONNECTED="Disco")
    $ print states.CONNECTED
    1
    $ states.SLEEPING
    0
    $ states.CONNECTED_str
    "Conn"
    $ states.SLEEPING_str
    None
    $ 0 in states
    True
    $ 10 in states
    False
    $ s = "Conn"
    $ if s in states:
    $     val = states[s]
    '''
    def __init__(self, *named, **valued):
        '''
        '''
        # FIXME not memory optimal structures
        self._items_map = {}
        self._items_rmap = {}
        self._items_val = []
        toks = [(name, None) for name in named]
        toks.extend([i for i in valued.iteritems()])
        for key, tok in enumerate(toks):
            self._items_map[tok[0]] = key
            self._items_rmap[key] = tok[0]
            self._items_val.append(tok[1])
    
    def __contains__(self, item):
        '''
        '''
        if isinstance(item, int):
            return item in self._items_rmap
        else:
            return item in self._items_val
    
    def __getitem__(self, key):
        '''
        '''
        if isinstance(key, int):
            return self._items_val[key]
        else:
            for idx, val in enumerate(self._items_val):
                if val == key:
                    return idx
            raise IndexError('object not found in enum')
    
    def __getattr__(self, name):
        '''
        '''
        if name in self._items_map:
            return self._items_map[name]
        else:
            if name[-4:] == '_str':
                n = name[:-4]
                if n in self._items_map:
                    return self._items_val[self._items_map[n]]
        raise AttributeError('not an enum member')

    def get(self, key, default=None):
        '''
        '''
        try:
            return self[key]
        except IndexError as err:
            return default


class RWLock(object):
    '''
    '''
    def __init__(self):
Thibault VINCENT's avatar
Thibault VINCENT committed
        '''
        '''
        self._mutex = Lock()
        self._writemutex = Lock()
        self._readers = 0
        self._writers = 0
        self.read = self._RLock(self)
        self.write = self._WLock(self)
    
    class _Lock(object):
        '''
        '''
        def __init__(self, rwlock):
Thibault VINCENT's avatar
Thibault VINCENT committed
            '''
            '''
            self._parent = rwlock
    
    class _WLock(_Lock):
        '''
        '''
        def __enter__(self):
            '''
            '''
            self.acquire()
        
        def __exit__(self, exc_type, exc_value, traceback):
            '''
            '''
            self.release()
        
        def acquire(self):
Thibault VINCENT's avatar
Thibault VINCENT committed
            '''
            '''
            with self._parent._mutex:
                self._parent._writers += 1
            self._parent._writemutex.acquire()
        
        def release(self):
Thibault VINCENT's avatar
Thibault VINCENT committed
            '''
            '''
            with self._parent._mutex:
                self._parent._writers -= 1
            self._parent._writemutex.release()
    
    class _RLock(_Lock):
        '''
        '''
        def __enter__(self):
            '''
            '''
            self.acquire()
        
        def __exit__(self, exc_type, exc_value, traceback):
            '''
            '''
            self.release()
        
        def acquire(self):
Thibault VINCENT's avatar
Thibault VINCENT committed
            '''
            '''
            self._parent._mutex.acquire()
            if self._parent._writers > 0 or self._parent._readers == 0:
                self._parent._mutex.release()
                self._parent._writemutex.acquire()
                self._parent._mutex.acquire()
            self._parent._readers += 1
            self._parent._mutex.release()
        
        def release(self):
Thibault VINCENT's avatar
Thibault VINCENT committed
            '''
            '''
            self._parent._mutex.acquire()
            self._parent._readers -= 1
            if self._parent._readers == 0:
                self._parent._writemutex.release()
            self._parent._mutex.release()


class Exec(object):
    '''
    '''
    @staticmethod
    def call(cmd, shell=False, input=None, capture_output=True,
                                                            merge_output=True):
        '''
        '''
        if capture_output:
            stdout = subprocess.PIPE
            if merge_output:
                stderr = subprocess.STDOUT
            else:
                stderr = subprocess.PIPE
        else:
            stdout = open(os.devnull, 'w')
            stderr = stdout
        debug('Exec.call: cmd=`%s`', ' '.join(cmd))
        if input is not None:
            stdin = subprocess.PIPE
            debug('Exec.call: input=`%s`', input)
            stdin = None
        proc = subprocess.Popen(cmd, shell=shell, stdout=stdout, stderr=stderr,
                                                                stdin=stdin)
        output = proc.communicate(input=input)
        debug('Exec.call: rc=`%d` out=`%s`', proc.returncode, output)
        return (proc.returncode, output)
    
    @staticmethod
    def silent(cmd, **kwargs):
        kwargs['capture_output'] = False
        return Exec.call(cmd, **kwargs)[0]