1212
1313import attr
1414
15- from ._base import Effect , guard , _Box , NoPerformerFoundError
15+ from ._base import Effect , guard , _Box , NoPerformerFoundError , raise_
1616from ._sync import NotSynchronousError , sync_perform , sync_performer
1717from ._intents import Constant , Error , Func , ParallelEffects , base_dispatcher
1818
3030 'ESConstant' , 'ESError' , 'ESFunc' ,
3131 'resolve_stubs' ,
3232 'resolve_stub' ,
33+ 'const' ,
34+ 'conste' ,
35+ 'intent_func' ,
3336]
3437
3538
@@ -465,7 +468,6 @@ def consume(self):
465468
466469def noop (intent ):
467470 """
468-
469471 Return None. This is just a handy way to make your intent sequences (as
470472 used by :func:`perform_sequence`) more concise when the effects you're
471473 expecting in a test don't return a result (and are instead only performed
@@ -478,3 +480,62 @@ def noop(intent):
478480
479481 """
480482 return None
483+
484+
485+ def const (value ):
486+ """
487+ Return function that takes an argument but always return given `value`.
488+ Useful when creating sequence used by :func:`perform_sequence`. For example,
489+
490+ >>> dt = datetime(1970, 1, 1)
491+ >>> seq = [(Func(datetime.now), const(dt))]
492+
493+ :param value: This will be returned when called by returned function
494+ :return: ``callable`` that takes an arg and always returns ``value``
495+ """
496+ return lambda intent : value
497+
498+
499+ def conste (excp ):
500+ """
501+ Like :func:`const` but takes and exception and returns function that raises
502+ the exception
503+
504+ :param excp: Exception that will be raised
505+ :type: :obj:`Exception`
506+ :return: ``callable`` that will raise given exception
507+ """
508+ return lambda intent : raise_ (excp )
509+
510+
511+ def intent_func (fname ):
512+ """
513+ Return function that returns Effect of tuple of fname and its args. Useful
514+ in writing tests that expect intent based on args. For example, if you are
515+ testing following function::
516+
517+ @do
518+ def code_under_test(arg1, arg2, eff_returning_func=eff_returning_func):
519+ r = yield Effect(MyIntent('a'))
520+ r2 = yield eff_returning_func(arg1, arg2)
521+ yield do_return((r, r2))
522+
523+ you will need to know the intents which ``eff_returning_func`` generates
524+ to test this using :func:`perform_sequence`. You can avoid that by doing::
525+
526+ def test_code():
527+ test_eff_func = intent_func("erf")
528+ seq = [
529+ (MyIntent('a'), const('result1')),
530+ (("erf", 'a1', 'a2'), const('result2'))
531+ ]
532+ eff = code_under_test('a1', 'a2', eff_returning_func=test_eff_func)
533+ assert perform_sequence(seq, eff) == ('result1', 'result2')
534+
535+ Here, the ``seq`` ensures that ``eff_returning_func`` is called with arguments
536+ ``a1`` and ``a2``.
537+
538+ :param str fname: First member of intent tuple returned
539+ :return: ``callable`` with multiple positional arguments
540+ """
541+ return lambda * a : Effect ((fname ,) + a )
0 commit comments