class DelegatingContextManager(ContextManager):
    '''
    Object which delegates its context manager interface to another object.

    You set the delegatee context manager as `self.delegatee_context_manager`,
    and whenever someone tries to use the current object as a context manager,
    the `__enter__` and `__exit__` methods of the delegatee object will be
    called. No other methods of the delegatee will be used.

    This is useful when you are tempted to inherit from some context manager
    class, but you don't to inherit all the other methods that it defines.
    '''

    delegatee_context_manager = None
    '''
    The context manager whose `__enter__` and `__exit__` method will be used.

    You may implement this as either an instance attribute or a property.
    '''

    __enter__ = misc_tools.ProxyProperty(
        '.delegatee_context_manager.__enter__'
    )
    __exit__ = misc_tools.ProxyProperty(
        '.delegatee_context_manager.__exit__'
    )
示例#2
0
class TestCase(unittest.TestCase, context_management.ContextManager):
    setUp = misc_tools.ProxyProperty('.setup')
    tearDown = misc_tools.ProxyProperty('.tear_down')
    def manage_context(self):
        yield self

    def setup(self):
        return self.__enter__()
    def tear_down(self):
        # todo: Should probably do something with exception-swallowing here to
        # abide with the context manager protocol, but I don't need it yet.
        return self.__exit__(*sys.exc_info())
示例#3
0
class HasIdentity(object):
    '''
    An object that has a persistent identity.
    
    When you make deepcopies of this object using `DontCopyPersistent()`, the
    new copies will have the same "identity" as the original object:
    
        >>> class A(HasIdentity):
        ...     pass
        >>> a0 = A()
        >>> a1 = copy.deepcopy(a0, DontCopyPersistent)
        >>> a0.has_same_identity_as(a1)
        True
        >>> a0 & a1 # Shortcut for `has_same_identity_as`
        True
        
    (`DontCopyPersistent` is available as
    `python_toolbox.persistent.DontCopyPersistent`)
    '''
    def __init__(self):
        self.__identity = CrossProcessPersistent()
        '''The object's persistent identity.'''

    def has_same_identity_as(self, other):
        '''Does `other` have the same identity as us?'''
        if not isinstance(other, HasIdentity):
            return NotImplemented
        return self.__identity.has_same_uuid_as(other.__identity)

    __and__ = has_same_identity_as

    personality = misc_tools.ProxyProperty(
        '._HasIdentity__identity.personality',
        doc='''Personality containing a human name and two colors.''')
示例#4
0
class _OrderedDictDelegator(Ordered, _BaseDictDelegator):
    '''
    An `OrderedDict`-like object.
    
    It has its `OrderedDict` functionality delegated to `self._dict` which is
    an actual `OrderedDict`.
    '''
    _dict_type = OrderedDict
    index = misc_tools.ProxyProperty(
        '._dict.index', doc='Get the index number of a key in this dict.')
    move_to_end = misc_tools.ProxyProperty(
        '._dict.move_to_end',
        doc='Move a key to the end (or start by passing `last=False`.)')
    sort = misc_tools.ProxyProperty(
        '._dict.sort',
        doc='Sort the keys in this dict. (With optional `key` function.)')
示例#5
0
class _OrderedBagMixin(Ordered):
    '''
    Mixin for a bag that's ordered.
    
    Items will be ordered according to insertion order. In every interface
    where items from this bag are iterated on, they will be returned by their
    order.
    '''
    __reversed__ = lambda self: reversed(self._dict)

    def __eq__(self, other):
        '''
        Is this bag equal to `other`?
        
        Order *does* count, so if `other` has a different order, the result
        will be `False`.
        '''
        if type(self) != type(other):
            return False
        for item, other_item in itertools.zip_longest(self.items(),
                                                      other.items()):
            if item != other_item:
                return False
        else:
            return True

    index = misc_tools.ProxyProperty(
        '._dict.index', doc='Get the index number of a key in the bag.')
示例#6
0
class OrderedBag(_OrderedBagMixin, _MutableBagMixin, _OrderedDictDelegator):
    '''
    An ordered bag that counts items.
    
    This is a ordered mapping between items and their count:
    
        >>> OrderedBag('aaabcbc')
        OrderedBag((('a', 3), ('b', 2), ('c', 2)))
    
    It can be created from either an iterable like above, or from a `dict`. 
    
    This class provides a lot of methods that `collections.Counter` doesn't;
    among them are a plethora of arithmetic operations (both between bags and
    bags and between bags and integers), comparison methods between bags, and
    more. This class is also more restricted than `collections.Counter`; only
    positive integers may be used as counts (zeros are weeded out), so we don't
    need to deal with all the complications of non-numerical counts.

    Also, unlike `collections.Counter`, items are ordered by insertion order.
    (Simliarly to `collections.OrderedDict`.)
    '''
    def popitem(self, last=True):
        '''
        Pop an item from this bag, returning `(key, count)` and removing it.
        
        By default, the item will be popped from the end. Pass `last=False` to
        pop from the start.
        '''        
        return self._dict.popitem(last=last)
    move_to_end = misc_tools.ProxyProperty(
        '._dict.move_to_end',
        doc='Move a key to the end (or start by passing `last=False`.)'
    )
    sort = misc_tools.ProxyProperty(
        '._dict.sort',
        doc='Sort the keys in this bag. (With optional `key` function.)'
    )
    
    @property
    def reversed(self):
        '''Get a version of this `OrderedBag` with key order reversed.'''
        return type(self)(self._dict_type(reversed(tuple(self.items()))))
示例#7
0
class Freezer(context_management.DelegatingContextManager):
    '''
    A freezer is used as a context manager to "freeze" and "thaw" an object.

    Different kinds of objects have different concepts of "freezing" and
    "thawing": A GUI widget could be graphically frozen, preventing the OS from
    drawing any changes to it, and then when its thawed have all the changes
    drawn at once. As another example, an ORM could be frozen to have it not
    write to the database while a suite it being executed, and then have it
    write all the data at once when thawed.

    This class only implements the abstract behavior of a freezer: It is a
    reentrant context manager which has handlers for freezing and thawing, and
    its level of frozenness can be checked by accessing the attribute
    `.frozen`. It's up to subclasses to override `freeze_handler` and
    `thaw_handler` to do whatever they should do on freeze and thaw. Note that
    you can override either of these methods to be a no-op, sometimes even both
    methods, and still have a useful freezer by checking the property `.frozen`
    in the logic of the parent object.
    '''

    delegatee_context_manager = caching.CachedProperty(DelegateeContextManager)
    '''The context manager which implements our `__enter__` and `__exit__`.'''


    frozen = misc_tools.ProxyProperty(
        '.delegatee_context_manager.depth'
    )
    '''
    An integer specifying the freezer's level of frozenness.

    If the freezer is not frozen, it's `0`. When it's frozen, it becomes `1`,
    and then every time the freezer is used as a context manager the `frozen`
    level increases. When reduced to `0` again the freezer is said to have
    thawed.

    This can be conveniently used as a boolean, i.e. `if my_freezer.frozen:`.
    '''

    def freeze_handler(self):
        '''Do something when the object gets frozen.'''

    def thaw_handler(self):
        '''Do something when the object gets thawed.'''
class DelegateeContextManager(context_management.ContextManager):
    '''Inner context manager used internally by `Freezer`.'''
    def __init__(self, freezer):
        '''
        Construct the `DelegateeContextManager`.
        
        `freezer` is the freezer to which we belong.
        '''
        self.freezer = freezer
        '''The freezer to which we belong.'''

    def __enter__(self):
        '''Call the freezer's freeze handler.'''
        return self.freezer.freeze_handler()

    def __exit__(self, exc_type, exc_value, exc_traceback):
        '''Call the freezer's thaw handler.'''
        return self.freezer.thaw_handler()

    depth = misc_tools.ProxyProperty('.__wrapped__.depth')