[config] Implements "Exclusive" context processor allowing to ask for an exclusive usage of a service while in a transformation.

This commit is contained in:
Romain Dorgueil
2017-05-25 11:14:49 +02:00
parent 8abd40cd73
commit 71c47a762b
9 changed files with 139 additions and 61 deletions

View File

@ -1,5 +1,3 @@
import warnings
from bonobo.structs import Bag, Graph, Token
from bonobo.nodes import CsvReader, CsvWriter, FileReader, FileWriter, Filter, JsonReader, JsonWriter, Limit, \
PrettyPrint, Tee, count, identity, noop, pprint

View File

@ -1,13 +1,15 @@
from bonobo.config.configurables import Configurable
from bonobo.config.options import Option, Method
from bonobo.config.processors import ContextProcessor
from bonobo.config.services import Container, Service
from bonobo.config.services import Container, Service, Exclusive
# bonobo.config public programming interface
__all__ = [
'Configurable',
'Container',
'ContextProcessor',
'Option',
'Exclusive',
'Method',
'Option',
'Service',
]

View File

@ -1,5 +1,7 @@
import re
import threading
import types
from contextlib import ContextDecorator
from bonobo.config.options import Option
from bonobo.errors import MissingServiceImplementationError
@ -87,3 +89,40 @@ class Container(dict):
if isinstance(value, types.LambdaType):
value = value(self)
return value
class Exclusive(ContextDecorator):
"""
Decorator and context manager used to require exclusive usage of an object, most probably a service. It's usefull
for example if call order matters on a service implementation (think of an http api that requires a nonce or version
parameter ...).
Usage:
>>> def handler(some_service):
... with Exclusive(some_service):
... some_service.call_1()
... some_service.call_2()
... some_service.call_3()
This will ensure that nobody else is using the same service while in the "with" block, using a lock primitive to
ensure that.
"""
_locks = {}
def __init__(self, wrapped):
self._wrapped = wrapped
def get_lock(self):
_id = id(self._wrapped)
if not _id in Exclusive._locks:
Exclusive._locks[_id] = threading.RLock()
return Exclusive._locks[_id]
def __enter__(self):
self.get_lock().acquire()
return self._wrapped
def __exit__(self, *exc):
self.get_lock().release()