Exemple #1
0
def test_mutator_exceptions():
    handled = False

    def base_plan():
        yield Msg('foo')
        yield Msg('bar')

    def failing_plan():
        nonlocal handled
        handled = False
        yield Msg('pre')
        try:
            yield Msg('FAIL')
        except EchoException:
            handled = True
            raise

    def test_mutator(msg):
        if msg.command == 'bar':
            return (failing_plan(), single_message_gen(Msg('foo')))
        return None, None

    # check generator exit behavior
    plan = plan_mutator(base_plan(), test_mutator)
    next(plan)
    plan.close()

    # check exception fall through
    plan = plan_mutator(base_plan(), test_mutator)
    with pytest.raises(EchoException):
        EchoRE(plan, debug=True)
    assert handled
Exemple #2
0
def test_exception_in_pre_with_tail():
    class SnowFlake(Exception):
        ...

    def bad_pre():
        yield Msg('pre_bad', None)
        raise SnowFlake('this one')

    def good_post():
        yield Msg('good_post', None)

    def test_mutator(msg):
        if msg.command == 'TARGET':
            return bad_pre(), good_post()

        return None, None

    def testing_plan():
        yield Msg('a', None)
        yield Msg('b', None)
        try:
            yield Msg('TARGET', None)
        except SnowFlake:
            pass
        yield Msg('b', None)
        yield Msg('a', None)

    plan = plan_mutator(testing_plan(), test_mutator)
    msgs = EchoRE(plan, debug=True)
    _verify_msg_seq(msgs,
                    m_len=5,
                    cmd_sq=['a', 'b', 'pre_bad', 'b', 'a'],
                    args_sq=[()] * 5,
                    kwargs_sq=[{}] * 5)
Exemple #3
0
def test_plan_mutator_returns():
    def testing_plan():
        yield Msg('a', None)
        yield Msg('TARGET', None)
        yield Msg('b', None)

        return 'foobar'

    def outer_plan(pln):
        ret = (yield from pln)
        assert ret == 'foobar'
        return ret

    def tail_plan():
        yield Msg('A', None)
        return 'baz'

    def test_mutator(msg):
        def pre_plan():
            yield Msg('pre', None)
            yield msg

        if msg.command == 'TARGET':
            return pre_plan(), tail_plan()

        return None, None

    plan = plan_mutator(testing_plan(), test_mutator)
    msgs = EchoRE(plan)
    _verify_msg_seq(msgs,
                    m_len=5,
                    cmd_sq=['a', 'pre', 'TARGET', 'A', 'b'],
                    args_sq=[()] * 5,
                    kwargs_sq=[{}] * 5)
Exemple #4
0
def test_simple_mutator():
    _mut_active = True
    pre_count = 3
    post_count = 5
    pre_cmd = 'pre'
    post_cmd = 'post'

    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=pre_count, command=pre_cmd),
                           single_message_gen(msg)),
                    echo_plan(num=post_count, command=post_cmd))
        return None, None

    num = 5
    cmd = 'echo'
    plan = plan_mutator(echo_plan(command=cmd, num=num), test_mutator)
    msgs = EchoRE(plan)
    total = num + pre_count + post_count
    cmd_sq = ([pre_cmd] * pre_count + [cmd] + [post_cmd] * post_count + [cmd] *
              (num - 1))
    _verify_msg_seq(msgs,
                    m_len=total,
                    cmd_sq=cmd_sq,
                    args_sq=[()] * total,
                    kwargs_sq=[{}] * total)
Exemple #5
0
def test_plan_mutator_exception_propogation():
    class ExpectedException(Exception):
        pass

    num = 5
    cmd1 = 'echo1'
    cmd2 = 'echo2'

    def bad_tail():
        yield Msg('one_tail', None)
        raise ExpectedException('this is a test')

    def sarfing_plan():
        try:
            yield from echo_plan(command=cmd1, num=num)
        except ExpectedException:
            print('CAUGHT IT')

    _mut_active = True

    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=2, command=cmd2),
                           single_message_gen(msg)), bad_tail())
        return None, None

    plan = plan_mutator(sarfing_plan(), test_mutator)
    EchoRE(plan, debug=True)
Exemple #6
0
def test_plan_mutator_exception_propogation():
    class ExpectedException(Exception):
        pass

    num = 5
    cmd1 = "echo1"
    cmd2 = "echo2"

    def bad_tail():
        yield Msg("one_tail", None)
        raise ExpectedException("this is a test")

    def sarfing_plan():
        try:
            yield from echo_plan(command=cmd1, num=num)
        except ExpectedException:
            print("CAUGHT IT")

    _mut_active = True

    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=2, command=cmd2), single_message_gen(msg)), bad_tail())
        return None, None

    plan = plan_mutator(sarfing_plan(), test_mutator)
    EchoRE(plan, debug=True)
Exemple #7
0
def test_simple_mutator():
    _mut_active = True
    pre_count = 3
    post_count = 5
    pre_cmd = "pre"
    post_cmd = "post"

    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (
                pchain(echo_plan(num=pre_count, command=pre_cmd), single_message_gen(msg)),
                echo_plan(num=post_count, command=post_cmd),
            )
        return None, None

    num = 5
    cmd = "echo"
    plan = plan_mutator(echo_plan(command=cmd, num=num), test_mutator)
    msgs = EchoRE(plan)
    total = num + pre_count + post_count
    cmd_sq = [pre_cmd] * pre_count + [cmd] + [post_cmd] * post_count + [cmd] * (num - 1)
    _verify_msg_seq(msgs, m_len=total, cmd_sq=cmd_sq, args_sq=[()] * total, kwargs_sq=[{}] * total)
Exemple #8
0
def test_base_excetpion():
    class SnowFlake(Exception):
        ...

    def null_mutator(msg):
        return None, None

    def test_plan():
        yield Msg('a', None)
        raise SnowFlake('this one')

    pln = plan_mutator(test_plan(), null_mutator)

    try:
        EchoRE(pln)
    except SnowFlake as ex:
        assert ex.args[0] == 'this one'
Exemple #9
0
def configure_count_time_wrapper(plan, time):
    """
    Preprocessor that sets all devices with a `count_time` to the same time.

    The original setting is stashed and restored at the end.

    Parameters
    ----------
    plan : iterable or iterator
        a generator, list, or similar containing `Msg` objects
    time : float or None
        If None, the plan passes through unchanged.

    Yields
    ------
    msg : Msg
        messages from plan, with 'set' messages inserted
    """
    devices_seen = set()
    original_times = {}

    def insert_set(msg):
        obj = msg.obj
        if obj is not None and obj not in devices_seen:
            devices_seen.add(obj)
            if hasattr(obj, 'count_time'):
                # TODO Do this with a 'read' Msg once reads can be
                # marked as belonging to a different event stream (or no
                # event stream.
                original_times[obj] = obj.count_time.get()
                # TODO do this with configure
                return pchain(mv(obj.count_time, time),
                              single_gen(msg)), None
        return None, None

    def reset():
        for obj, time in original_times.items():
            yield from mv(obj.count_time, time)

    if time is None:
        # no-op
        return (yield from plan)
    else:
        return (yield from finalize_wrapper(plan_mutator(plan, insert_set),
                                            reset()))
Exemple #10
0
def test_insert_after():
    def target():
        yield Msg('a', None)
        ret = yield Msg('TARGET', None)
        yield Msg('b', None)
        assert ret is not None
        assert ret.command == 'TARGET'
        return ret

    def insert_after(msg):
        if msg.command == 'TARGET':

            def post():
                yield Msg('post', None)

            return None, post()
        else:
            return None, None

    ret = EchoRE(plan_mutator(target(), insert_after))
Exemple #11
0
def periodic_dark(plan):
    """
    a plan wrapper that takes a plan and inserts `take_dark`

    The `take_dark` plan is inserted on the fly before the beginning of
    any new run after a period of time defined by `glbl.dk_window` has passed.
    """
    need_dark = True

    def insert_take_dark(msg):
        now = time.time()
        nonlocal need_dark
        qualified_dark_uid = _validate_dark(expire_time=glbl.dk_window)
        # FIXME: should we do "or" or "and"?
        if (not need_dark) and (not qualified_dark_uid):
            need_dark = True
        if need_dark \
                and (not qualified_dark_uid) \
                and msg.command == 'open_run' \
                and ('dark_frame' not in msg.kwargs):
            # We are about to start a new 'run' (e.g., a count or a scan).
            # Insert a dark frame run first.
            need_dark = False
            # Annoying detail: the detector was probably already staged.
            # Unstage it (if it wasn't staged, nothing will happen) and
            # then take_dark() and then re-stage it. 
            return bp.pchain(bp.unstage(glbl.area_det),
                             take_dark(),
                             bp.stage(glbl.area_det),
                             bp.single_gen(msg),
                             bp.abs_set(glbl.shutter, 60, wait=True)), None
        elif msg.command == 'open_run' and 'dark_frame' not in msg.kwargs:
            return bp.pchain(bp.single_gen(msg),
                             bp.abs_set(glbl.shutter, 60, wait=True)), None
        else:
            # do nothing if (not need_dark)
            return None, None

    return (yield from bp.plan_mutator(plan, insert_take_dark))
Exemple #12
0
def periodic_dark(plan):
    """
    a plan wrapper that takes a plan and inserts `take_dark`

    The `take_dark` plan is inserted on the fly before the beginning of
    any new run after a period of time defined by `glbl.dk_window` has passed.
    """
    need_dark = True

    def insert_take_dark(msg):
        now = time.time()
        nonlocal need_dark
        qualified_dark_uid = _validate_dark(expire_time=glbl.dk_window)
        # FIXME: should we do "or" or "and"?
        if (not need_dark) and (not qualified_dark_uid):
            need_dark = True
        if need_dark \
                and (not qualified_dark_uid) \
                and msg.command == 'open_run' \
                and ('dark_frame' not in msg.kwargs):
            # We are about to start a new 'run' (e.g., a count or a scan).
            # Insert a dark frame run first.
            need_dark = False
            # Annoying detail: the detector was probably already staged.
            # Unstage it (if it wasn't staged, nothing will happen) and
            # then take_dark() and then re-stage it.
            return bp.pchain(bp.unstage(glbl.area_det), take_dark(),
                             bp.stage(glbl.area_det), bp.single_gen(msg),
                             bp.abs_set(glbl.shutter, 60, wait=True)), None
        elif msg.command == 'open_run' and 'dark_frame' not in msg.kwargs:
            return bp.pchain(bp.single_gen(msg),
                             bp.abs_set(glbl.shutter, 60, wait=True)), None
        else:
            # do nothing if (not need_dark)
            return None, None

    return (yield from bp.plan_mutator(plan, insert_take_dark))
Exemple #13
0
def test_insert_before():
    def target():
        yield Msg('a', None)
        ret = yield Msg('TARGET', None)
        yield Msg('b', None)
        assert ret.command == 'TARGET'
        return ret
        return ret

    def insert_before(msg):
        if msg.command == 'TARGET':

            def pre():
                yield Msg('pre', None)
                ret = yield msg
                assert ret is not None
                assert ret.command == 'TARGET'
                return ret

            return pre(), None
        else:
            return None, None

    ret = EchoRE(plan_mutator(target(), insert_before))