Skip to content

Commit 55a88b1

Browse files
committed
- avoid hashing altogether (and revert hashability changes)
- add a handy `catch` function for error handling of specific types
1 parent 0aafa05 commit 55a88b1

7 files changed

Lines changed: 28 additions & 23 deletions

File tree

effect/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from __future__ import absolute_import
1111

12-
from ._base import Effect, perform, NoPerformerFoundError
12+
from ._base import Effect, perform, NoPerformerFoundError, catch
1313
from ._sync import (
1414
NotSynchronousError,
1515
sync_perform,
@@ -28,4 +28,5 @@
2828
"Constant", "Error", "FirstError", "Func",
2929
"base_dispatcher",
3030
"TypeDispatcher", "ComposedDispatcher",
31+
"catch",
3132
]

effect/_base.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
from characteristic import attributes
99

10+
import six
11+
1012
from ._continuation import trampoline
1113

1214

@@ -26,7 +28,7 @@ def __init__(self, intent, callbacks=None):
2628
"""
2729
self.intent = intent
2830
if callbacks is None:
29-
callbacks = ()
31+
callbacks = []
3032
self.callbacks = callbacks
3133

3234
def on(self, success=None, error=None):
@@ -44,7 +46,7 @@ def on(self, success=None, error=None):
4446
:obj:`Effect` will be passed to the next callback.
4547
"""
4648
return Effect(self.intent,
47-
callbacks=self.callbacks + ((success, error),))
49+
callbacks=self.callbacks + [(success, error)])
4850

4951

5052
class _Box(object):
@@ -149,3 +151,20 @@ def _perform(bouncer, effect):
149151
_run_callbacks(bouncer, effect.callbacks, (True, e))
150152

151153
trampoline(_perform, effect)
154+
155+
156+
def catch(exc_type, callable):
157+
"""
158+
A helper for handling errors of a specific type.
159+
160+
eff.on(error=catch(SpecificException,
161+
lambda exc_info: "got an error!"))
162+
163+
If any exception other than a ``SpecificException`` is thrown, it will be
164+
ignored by this handler and propogate further down the chain of callbacks.
165+
"""
166+
def catcher(exc_info):
167+
if isinstance(exc_info[1], exc_type):
168+
return callable(exc_info)
169+
six.reraise(*exc_info)
170+
return catcher

effect/_intents.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def __init__(self, effects):
4545
"""
4646
:param effects: Effects which should be performed in parallel.
4747
"""
48-
self.effects = tuple(effects)
48+
self.effects = effects
4949

5050

5151
def parallel(effects):

effect/test_base.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,3 @@ def get_stack(_):
288288
perform(func_dispatcher, eff)
289289
boxes[0].succeed('foo')
290290
self.assertEqual(calls[0], calls[1])
291-
292-
293-
class HashTests(TestCase):
294-
"""Tests for hashing of effects."""
295-
296-
def test_hashable(self):
297-
"""
298-
Effects are hashable, despite the fact that the callbacks are stored as
299-
a list.
300-
"""
301-
hash(Effect(None))

effect/test_intents.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
Constant, perform_constant,
1111
Error, perform_error,
1212
Func, perform_func,
13-
parallel,
1413
FirstError)
1514

1615

@@ -59,7 +58,3 @@ def test_first_error_str(self):
5958
self.assertEqual(
6059
str(fe),
6160
'(index=150) ValueError: foo')
62-
63-
def test_hashable(self):
64-
"""ParallelIntents are hashable."""
65-
hash(parallel([Effect(None), Effect(None)]))

effect/test_testing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def test_non_test_intent(self):
164164
eff = ESConstant("foo").on(success=lambda r: bare_effect)
165165
result_eff = resolve_stubs(base_dispatcher, eff)
166166
self.assertIs(result_eff.intent, bare_effect.intent)
167-
self.assertEqual(result_eff.callbacks, ())
167+
self.assertEqual(result_eff.callbacks, [])
168168

169169
def test_type_error(self):
170170
"""

effect/testing.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,6 @@ def __init__(self, mapping):
190190
self.mapping = mapping
191191

192192
def __call__(self, intent):
193-
if intent in self.mapping:
194-
return sync_performer(lambda d, i: self.mapping[intent])
193+
for k, v in self.mapping.iteritems():
194+
if k == intent:
195+
return sync_performer(lambda d, i: v)

0 commit comments

Comments
 (0)