Skip to content
Snippets Groups Projects
Unverified Commit b61d5924 authored by Piotr Maślanka's avatar Piotr Maślanka Committed by GitHub
Browse files

Merge pull request #27 from piotrmaslanka/develop

v2.0.22
parents d64c3686 430f6a0e
No related branches found
Tags v2.0.22
No related merge requests found
## v2.0.22rc4
* fixes #14
## v2.0.22rc3
* fixes #15
......
# coding=UTF-8
__version__ = '2.0.22rc3'
__version__ = '2.0.22'
......@@ -15,6 +15,7 @@ from .typecheck import typed, Callable, Sequence, \
from .structures import TimeBasedHeap, Heap, typednamedtuple, OmniHashableMixin
from .singleton import Singleton
__all__ = [
'typednamedtuple', 'OmniHashableMixin'
'TimeBasedHeap', 'Heap', 'CallableGroup',
......
......@@ -18,7 +18,7 @@ def silence_excs(*exc_types):
Can be either a decorator or a context manager
"""
return rethrow_as(*[(t, None) for t in exc_types])
return rethrow_as(exc_types, None)
class rethrow_as(object):
......@@ -39,17 +39,24 @@ class rethrow_as(object):
rethrow_as(NameError, ValueError)
If the second value is a None, exception will be silenced.
:param exception_preprocessor: other callable/1 to use instead od repr.
Should return a text
"""
# You can also provide just two exceptions
if len(pairs) == 2 and not isinstance(pairs[1], (tuple, list)) \
and all(issubclass(p, BaseException) for p in pairs):
self.mapping = {pairs[0]: pairs[1]}
else:
self.mapping = dict(pairs)
try:
a, b = pairs # throws ValueError
op = issubclass(b, BaseException) # throws TypeError
except TypeError:
op = b is None
except ValueError:
op = False
if op:
pairs = [pairs]
self.mapping = list(pairs)
self.exception_preprocessor = kwargs.get('exception_preprocessor', repr)
def __call__(self, fun):
......@@ -64,12 +71,10 @@ class rethrow_as(object):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type not in self.mapping:
return
fate = self.mapping[exc_type]
if fate is None: # mask it
return True
else:
raise fate(self.exception_preprocessor(exc_val))
if exc_type is not None:
for from_, to in self.mapping:
if issubclass(exc_type, from_):
if to is None:
return True
else:
raise to(self.exception_preprocessor(exc_val))
......@@ -12,7 +12,7 @@ __all__ = [
if six.PY3:
# Taken from https://wiki.python.org/moin/PythonDecoratorLibrary
def Singleton(cls):
def singleton(cls):
"""
Make a singleton out of decorated class.
......@@ -59,10 +59,13 @@ else:
# taken from https://pypi.python.org/pypi/singleton-decorator/1.0.0
def Singleton(cls):
def singleton(cls):
"""
A singleton decorator. Returns a wrapper objects. A call on that object
returns a single instance object of decorated class. Use the __wrapped__
attribute to access decorated class directly in unit tests.
"""
return _SingletonWrapper(cls)
Singleton = singleton
# coding=UTF-8
from __future__ import print_function, absolute_import, division
import six
__all__ = [
......@@ -8,6 +9,7 @@ __all__ = [
from .basics import *
def _typeinfo_to_tuple_of_types(typeinfo, operator=type):
if typeinfo == 'self':
return None
......@@ -26,55 +28,51 @@ def _typeinfo_to_tuple_of_types(typeinfo, operator=type):
def istype(var, type_):
retv = False
if type_ is None or type_ == 'self':
return True
retv = True
elif type(type_) == tuple:
return any(istype(var, subtype) for subtype in type_)
try:
if type_ in (Callable, Iterable, Sequence, Mapping):
raise TypeError()
if isinstance(var, type_):
return True
retv = any(istype(var, subtype) for subtype in type_)
except TypeError as e: # must be a typing.* annotation
elif type_ in (Callable, Iterable, Sequence, Mapping):
if type_ == Callable:
return hasattr(var, '__call__')
retv = hasattr(var, '__call__')
elif type_ == Iterable:
return hasattr(var, '__iter__')
retv = hasattr(var, '__iter__')
elif type_ == Sequence:
return hasattr(var, '__iter__') and hasattr(var, '__getattr__') and hasattr(var,
retv = hasattr(var, '__iter__') and hasattr(var, '__getattr__') and hasattr(var,
'__len__')
elif type_ == Mapping:
return hasattr(var, '__getitem__')
return type(var) == type_
retv = hasattr(var, '__getitem__')
else:
try:
if isinstance(var, type_):
retv = True
except TypeError: # must be a typing.* annotation
retv = type(var) == type_
return False
return retv
def _do_if_not_type(var, type_, fun='default'):
if type_ in ((type(None),),) and (fun == 'default'):
return None
retv = None
if type_ in (None, (None,), 'self'):
return var
elif type_ in (None, (None,), 'self'):
retv = var
if not istype(var, type_):
elif not istype(var, type_):
if fun == 'default':
if type_[0] == type(None):
return None
else:
return type_[0](var)
q = fun()
if isinstance(q, Exception):
raise q
return q
retv = None if type_[0] == type(None) else type_[0](var)
else:
q = fun()
if isinstance(q, Exception):
raise q
retv = q
else:
return var
retv = var
return retv
......@@ -4,7 +4,7 @@ import functools
import warnings
import six
from .core_typecheck import *
from .corechk import *
from .basics import *
__all__ = [
......
......@@ -8,7 +8,7 @@ setup(keywords=['ha', 'high availability', 'scalable', 'scalability', 'server'],
install_requires=[
"six",
"monotonic",
"typing"
"typing",
],
tests_require=[
"nose", "mock", "coverage"
......
......@@ -53,3 +53,23 @@ class TestStuff(unittest.TestCase):
self.assertRaises(WTFException1, lambda: provide(NameError))
self.assertRaises(WTFException2, lambda: provide(TypeError))
def test_issue_14a(self):
@rethrow_as(*(((NameError, ValueError), TypeError), ))
def ro(p):
raise p()
self.assertRaises(TypeError, lambda: ro(NameError))
self.assertRaises(TypeError, lambda: ro(ValueError))
self.assertRaises(RuntimeError, lambda: ro(RuntimeError))
def test_issue_14b(self):
@rethrow_as((NameError, ValueError), TypeError)
def ro(p):
raise p()
self.assertRaises(TypeError, lambda: ro(NameError))
self.assertRaises(TypeError, lambda: ro(ValueError))
self.assertRaises(RuntimeError, lambda: ro(RuntimeError))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment