D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
3
/
cwd
/
opt
/
imh-python
/
lib
/
python2.7
/
site-packages
/
rads
/
Filename :
context.py
back
Copy
"""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]