Mini Shell

Direktori : /opt/imh-python/lib/python2.7/site-packages/rads/
Upload File :
Current File : //opt/imh-python/lib/python2.7/site-packages/rads/context.py

"""Context Managers for RADS.

Context managers modify the behavior of an indented block of code
in some way by silently calling __enter__() and __exit__() when you
change indentation. __exit__() will always be called, even if the
indented code raised an exception. For example in fabric, settings
is a context manager:

def function_name():
    with settings(warn_only=True):
        run('some_command')

This part of RADS is very closely tied to rads.decorators.

Python 3.2 introduces contextlib.ContextDecorator which allows
something to behave as both a decorator and a context manager.
Older versions of python need to implement this manually.
rads.implementation.contextdecorator works around that.

Decorators modify the behavior of an entire function. For example
in fabric, with_settings is a decorator:

@with_settings(warn_only=True)
def function_name():
    run('some_command')
"""

import __main__ as main_obj
import time
from rads.implementation.contextdecorator import contextmanager
from rads.exceptions import S_LockError
import socket
try:
    import MySQLdb
    MYSQLDB = True
except ImportError:
    MYSQLDB = False
import hashlib

@contextmanager
def db_cur(_autocommit=False, _yield_conn=False, *args, **kwargs):
    """Yield a database cursor as a context manager. Args are the same
    as with MySQLdb.connect, except for:
    _autocommit(default False) whether to set autocommit
    _yield_conn(default False) whether to yield conn, cur isntead of just cur"""
    if not MYSQLDB:
        raise ImportError('imh-python-mysql is not installed')
    conn = MySQLdb.connect(*args, **kwargs)
    if _autocommit:
        conn.autocommit(True)
    cur = conn.cursor()
    try:
        if _yield_conn:
            yield conn, cur
        else:
            yield cur
    finally:
        cur.close()
        conn.close()

@contextmanager
def s_lock(name=None):
    """Create an abstract UNIX socket which will behave as a "lock" or
    raise socket.error if the "lock" already existed. This can be used
    en lieu of /var/run file pids/locks to determine if an instance of
    said process is already running. This method ensures no file locks
    are left behind if the process terminates prematurely"""
    if name is None:
        # caveat: this will crash if run in an interactive python shell
        name = main_obj.__file__
    lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    try:
        lock_socket.bind('\0%s' % hashlib.sha256(name).hexdigest())
    except socket.error:
        raise S_LockError
    try:
        yield
    finally:
        lock_socket.close()

@contextmanager
def wait_lock(name=None, sleep=0.5, max_sleep=None):
    if name is None:
        # caveat: this will crash if run in an interactive python shell
        name = main_obj.__file__
    slept = 0.0
    while True:
        try:
            with s_lock(name):
                yield
                return
        except S_LockError:
            time.sleep(sleep)
            slept += sleep
            if max_sleep is not None and slept >= max_sleep:
                raise

# rads.decorators inspects this. When adding new context managers to this
# module, please add them to this too.
__rads_context_managers__ = [s_lock, wait_lock]

Zerion Mini Shell 1.0