def test_ignore_invalid_triggers(self):
     a_state = State('A')
     transitions = [['a_to_b', 'A', 'B']]
     # Exception is triggered by default
     b_state = State('B')
     m1 = Machine(None, states=[a_state, b_state], transitions=transitions,
                  initial='B')
     with self.assertRaises(MachineError):
         m1.a_to_b()
     # Exception is suppressed, so this passes
     b_state = State('B', ignore_invalid_triggers=True)
     m2 = Machine(None, states=[a_state, b_state], transitions=transitions,
                  initial='B')
     m2.a_to_b()
     # Set for some states but not others
     new_states = ['C', 'D']
     m1.add_states(new_states, ignore_invalid_triggers=True)
     m1.to_D()
     m1.a_to_b()  # passes because exception suppressed for D
     m1.to_B()
     with self.assertRaises(MachineError):
         m1.a_to_b()
     # Set at machine level
     m3 = Machine(None, states=[a_state, b_state], transitions=transitions,
                  initial='B', ignore_invalid_triggers=True)
     m3.a_to_b()
 def test_ignore_invalid_triggers(self):
     a_state = State('A')
     transitions = [['a_to_b', 'A', 'B']]
     # Exception is triggered by default
     b_state = State('B')
     m1 = Machine(None, states=[a_state, b_state], transitions=transitions,
                  initial='B')
     with self.assertRaises(MachineError):
         m1.a_to_b()
     # Exception is suppressed, so this passes
     b_state = State('B', ignore_invalid_triggers=True)
     m2 = Machine(None, states=[a_state, b_state], transitions=transitions,
                  initial='B')
     m2.a_to_b()
     # Set for some states but not others
     new_states = ['C', 'D']
     m1.add_states(new_states, ignore_invalid_triggers=True)
     m1.to_D()
     m1.a_to_b()  # passes because exception suppressed for D
     m1.to_B()
     with self.assertRaises(MachineError):
         m1.a_to_b()
     # Set at machine level
     m3 = Machine(None, states=[a_state, b_state], transitions=transitions,
                  initial='B', ignore_invalid_triggers=True)
     m3.a_to_b()
def parse(fl, pat, states=states, transitions=transitions, log=True):
    """parses file
    The transitions and states for the machine are defined above"""
    if log == True:
        fn = os.path.join('/Users/rikhoekstra/surfdrive/rsg/ocr/',
                          'rsg_parser.log')
        logging.basicConfig(filename=fn, filemode='w', level=logging.INFO)
        logging.getLogger('transitions').setLevel(logging.INFO)
    page = fl.read()
    fl.close()

    model = ProcessingModel(page, p2=pat)
    machine = Machine(
        model=model,
        transitions=transitions,
        initial='start',
    )
    states = states
    machine.add_states(states, ignore_invalid_triggers=True)
    try:
        model.d_page()
        model.divide()
        while model.has_next_element():
            model.check_date()
            model.check_resolution()
            model.check_footnote()
            model.check_cont_resolution()
            model.handle_el()
#        import pdb; pdb.set_trace()
        model.finalize()
        model.end_index()

    except IndexError:
        pass
    model.done_processing()
    return model
Exemple #4
0
class Robot(object):
    """docstring for Robot"""

    # todo 把thread变成一个属性 每次start重新实例化一个thread
    def __init__(self, username, password, japan_server=False):
        super(Robot, self).__init__()
        parser = argparse.ArgumentParser("config")
        parser.add_argument("--debug",
                            help="enable debug model",
                            action="store_true")
        args = parser.parse_args()
        self.DEBUG = args.debug
        self.set_logger(username, japan_server)
        self.ze = zemulator.ZjsnEmulator()
        self.ze.username = username
        self.ze.password = password
        if japan_server:
            self.ze.api.location = self.ze.api.JAPAN
        self.ze.login()
        self.thread = None

        self.dock = Dock(self.ze)
        self.explore = self.dock.explore_mod

        self.campaign = Campaign(self.ze)
        states = [self.dock] + [m.state for m in [self.explore, self.campaign]]
        self.missions = {}

        self.machine = Machine(model=self,
                               states=states,
                               initial='init',
                               auto_transitions=False)
        self.command = 'run'

        self.add_mission(DailyTask(self.ze))
        # kill_fish
        self.kill_fish = Mission_6_1_A(self.ze)
        self.daily_kill_fish = DailyKillFish(self.ze)
        self.build_mission = HolyBuild(self.ze)

        self.add_mission(self.kill_fish)

        if self.ze.version < self.ze.KEY_VERSION:
            self.set_missions()
            self.machine.add_transition(trigger='go_out',
                                        prepare=[self.explore._prepare],
                                        source='init',
                                        dest=self.explore.mission_name)
            self.machine.add_transition(trigger='go_out',
                                        source=self.explore.mission_name,
                                        dest=self.explore.mission_name,
                                        conditions=[self.campaign.prepare],
                                        after=[self.campaign.start])
            self.machine.add_transition(trigger='go_out',
                                        source=self.explore.mission_name,
                                        dest='init',
                                        conditions=[self.explore.get_explore])
        else:
            self.machine.add_transition(trigger='go_out',
                                        source="init",
                                        dest="init",
                                        conditions=[self.campaign.prepare],
                                        after=[self.campaign.start])

            self.add_mission(self.build_mission)
            self.set_missions()
            self.add_mission(self.daily_kill_fish)
            self.machine.add_transition(trigger='go_out',
                                        conditions=[self.dock.wait],
                                        source='init',
                                        dest="init")
        # self.machine.add_transition(trigger='go_back', source='*', dest='init')

    def add_mission(self, mission: Mission):
        if mission.mission_name not in self.missions:
            self.missions[mission.mission_name] = mission
        else:
            raise ValueError("mission name {} is already used".format(
                mission.mission_name))
        self.machine.add_states(mission.state)
        self.machine.add_transition(**mission.trigger)
        self.machine.add_transition(**mission.back_trigger)

    def set_missions(self):
        pass

    def go_out(self):
        # dummy trigger method, implemented by transitions module
        pass

    def set_logger(self, username, is_japan):
        if is_japan:
            suffix = "_japan"
        else:
            suffix = ""
        log_formatter = logging.Formatter(
            '%(asctime)s: %(levelname)s: %(name)s: %(message)s')
        if os.name == 'nt' or self.DEBUG:
            stream_handler = logging.StreamHandler()
            stream_handler.setFormatter(log_formatter)
            logging.getLogger('transitions').addHandler(stream_handler)
            logging.getLogger('transitions').setLevel(logging.INFO)
            _logger.addHandler(stream_handler)

        file_handler = handlers.TimedRotatingFileHandler(
            '{}.log'.format(username + suffix),
            when='midnight',
            backupCount=3,
            encoding='utf8')
        file_handler.setFormatter(log_formatter)
        _logger.addHandler(file_handler)

        _logger.setLevel(logging.DEBUG)

    def working_loop(self):
        while self.command != 'stop':
            try:
                if not self.is_sleep():
                    self.go_out()
                    time.sleep(2)
                else:
                    time.sleep(600)
            except zemulator.ZjsnError as zerror:
                if zerror.eid == -101:
                    self.ze.login()
                    self.state = 'init'
                elif zerror.eid in [-9997, -9995, -9994]:
                    _logger.info(
                        "login on another device, input anything to continue")
                    wait_thread = threading.Thread(target=input)
                    wait_thread.start()
                    wait_thread.join(timeout=7200)
                    self.ze.login()
                    self.state = 'init'
                else:
                    raise zerror
            except ConnectionError:
                while self.command != 'stop':
                    _logger.error("Connection error")
                    time.sleep(600)
                    try:
                        self.ze.login()
                        self.state = 'init'
                        break
                    except ConnectionError:
                        pass

    def is_sleep(self) -> bool:
        # sleep in 0:00 to 6:00

        if os.name == 'nt':
            return False

        if self.ze.now.replace(
                hour=0, minute=0) < self.ze.now < self.ze.now.replace(hour=6):
            return True
        else:
            return False

    def run(self):
        last_error_time = 0
        error_count = 0
        while 1:
            try:
                # check dock, equipment, tasks before any transitions
                self.dock.check()
                self.working_loop()
            except Exception as e:
                # reset error count everyday
                if last_error_time - time.time() > 24 * 60 * 60:
                    error_count = 0
                last_error_time = time.time()
                error_count += 1
                _logger.exception(e)
                if self.DEBUG or error_count > 3:
                    raise e
                else:
                    self.ze.login()
                # disable mission where this error occurs
                if self.state in self.missions:
                    current_mission = self.missions[self.state]
                    current_mission.enable = False
                    _logger.error("{} is disabled".format(current_mission))
                    # init state
                    self.state = 'init'
                time.sleep(10)

    def start(self):
        if os.name == 'nt' or self.DEBUG:
            self.run()
        else:
            self.thread = threading.Thread(target=self.run, daemon=True)
            self.thread.start()
            return self.thread
Exemple #5
0
def build_machine(infile, target, config, tagging_info=None, notify=None):
    videoprocessor = VideoProcessor(infile,
                                    target,
                                    config,
                                    tagging_info=tagging_info,
                                    notify=notify)
    machine = Machine(model=videoprocessor, initial='initialised')

    states = [
        'initialised',
        State(name='processed'),
        State(name='tagged'),
        State(name='postprocessed'),
        State(name='refreshed'),
        State(name='deployed'),
        State(name='deleted'),
        State(name='finished')
    ]

    machine.add_states(states)

    machine.add_transition(trigger='process',
                           source='initialised',
                           dest='processed',
                           before='do_process')

    machine.add_transition(trigger='tag',
                           source='processed',
                           dest='tagged',
                           conditions=['conversion_success', 'has_tag_info'],
                           before='do_tag')

    machine.add_transition(trigger='postprocess',
                           source=['tagged', 'processed'],
                           dest='postprocessed',
                           conditions=['conversion_success'],
                           before='do_postprocess')

    machine.add_transition(trigger='deploy',
                           source=['processed', 'tagged', 'postprocessed'],
                           dest='deployed',
                           conditions='conversion_success',
                           before='do_deploy')

    machine.add_transition(trigger='delete',
                           source=['postprocessed', 'deployed'],
                           dest='deleted',
                           conditions=['has_delete'],
                           before='do_delete')

    machine.add_transition(
        trigger='refresh',
        source=['processed', 'tagged', 'deployed', 'deleted'],
        conditions=['has_refresher'],
        dest='refreshed',
        before='do_refresh')

    machine.add_transition(trigger='finish',
                           source=[
                               'processed', 'tagged', 'postprocessed',
                               'refreshed', 'deployed', 'deleted'
                           ],
                           dest='finished')

    return videoprocessor
                  states=states,
                  transitions=transitions,
                  initial='liquid')

# States: 状态机的核心
# 初始化和修改状态的几种方式:
#   通过字符串
#   直接使用 State 对象
#   使用一个字典
from transitions import State
states = [
    State(name='solid'),  # 通过State创建对象
    'liquid',  # 通过字符串
    {
        'name': 'gas'
    },  # 通过字典
]
machine = Machine(lump, states)

# 也可以通过 add_states 来添加状态
machine = Machine(lump)
solid = State('solid')
liquid = State('liquid')
gas = State('gas')
machine.add_states([solid, liquid, gas])
# 状态机的状态,应该只初始化一次,不能改动,除非重新创建

# Callbacks
# 一个状态在进入和退出都可以调用回调, 可以在初始化添加或者之后添加
machine.add_transition()
Exemple #7
0
class BotBuilder:
    def __init__(self, isVerbose):
        if isVerbose:
            logging.basicConfig(level=logging.DEBUG)
        else:
            logging.basicConfig(level=logging.INFO)

        self.statesCounter = 0
        self.currentState = self.statesCounter
        self.beginState = self.currentState

        self.bbot = OurBot()
        self.machine = Machine(model=self.bbot,
                               initial=self.convertStateIdToName(
                                   self.beginState),
                               auto_transitions=False)

        self.machine.add_states(State(name=self.getCurrentState()))
        self.labelToStateMap = {}
        self.stateIdToContent = {}
        self.returnStack = []
        logger.debug("Initialized BotBuilder with node:" +
                     str(self.bbot.state))

    def botSays(self, botString):
        setattr(self.bbot, "on_enter_" + self.getCurrentState(),
                types.MethodType(lambda x: print(botString), self.bbot))
        self.machine.add_transition("advance",
                                    source=self.getCurrentState(),
                                    dest=self.convertStateIdToName(
                                        self.getNextStateId()))
        logger.debug("Tagging state " + self.getCurrentState() +
                     " as bot says state")

        self.advanceState(botString)
        logger.debug("Creating fallthrough state " + self.getCurrentState())

    def singleOptionUserResponse(self, response):
        self.machine.add_transition(response,
                                    source=self.getCurrentState(),
                                    dest=self.convertStateIdToName(
                                        self.getNextStateId()))
        self.advanceState(response)

    def twoOptionUserResponse(self, ifTransitionName, ifTransitionFunction,
                              elseTransitionName, elseTransitionFunction):

        currentState = self.getCurrentState()
        ifState = self.createNewState(ifTransitionName)
        elseState = self.createNewState(elseTransitionName)
        mergeState = self.createNewState("merge-block")

        logger.debug("Added if state " + self.convertStateIdToName(ifState))
        self.setCurrentState(ifState)
        self.pushReturnStack()
        ifTransitionFunction()
        self.machine.add_transition(
            ifTransitionName,
            source=self.convertStateIdToName(currentState),
            dest=self.convertStateIdToName(ifState))
        if self.popReturnStack():
            self.machine.add_transition(
                "advance",
                source=self.getCurrentState(),
                dest=self.convertStateIdToName(mergeState))

        logger.debug("Added else state " +
                     self.convertStateIdToName(elseState))
        self.setCurrentState(elseState)
        self.pushReturnStack()
        elseTransitionFunction()
        self.machine.add_transition(
            elseTransitionName,
            source=self.convertStateIdToName(currentState),
            dest=self.convertStateIdToName(elseState))

        if self.popReturnStack():
            self.machine.add_transition(
                "advance",
                source=self.getCurrentState(),
                dest=self.convertStateIdToName(mergeState))

        logger.debug("Added merge state " +
                     self.convertStateIdToName(mergeState))
        self.setCurrentState(mergeState)

    def gotoNode(self, nodeLabel):
        if len(self.returnStack) > 0:
            self.returnStack[-1] = False

        if not nodeLabel in self.labelToStateMap:
            self.labelToStateMap[nodeLabel] = self.createNewState(nodeLabel)
            logger.debug("Creating branch to node " + self.getCurrentState())

        self.machine.add_transition("advance",
                                    source=self.getCurrentState(),
                                    dest=self.convertStateIdToName(
                                        self.labelToStateMap[nodeLabel]))

        self.setCurrentState(self.labelToStateMap[nodeLabel])

    def getCurrentState(self):
        return self.convertStateIdToName(self.getCurrentStateId())

    def getCurrentStateId(self):
        return self.currentState

    def convertStateIdToName(self, identity):
        return str(identity)

    def createNewState(self, textStr):
        self.statesCounter = self.getNextStateId()
        logger.debug("Created state " +
                     self.convertStateIdToName(self.statesCounter))
        self.machine.add_states(
            State(name=self.convertStateIdToName(self.statesCounter)))
        self.stateIdToContent[self.convertStateIdToName(
            self.statesCounter)] = textStr
        return self.statesCounter

    def getNextStateId(self):
        return self.statesCounter + 1

    def advanceState(self, textStr):
        self.setCurrentState(self.createNewState(textStr))

    def setCurrentState(self, state):
        self.currentState = state

    def plotStateMachine(self, name):
        self.bbot.get_graph().draw(name, prog='dot')

    def getBeginState(self):
        return self.convertStateIdToName(self.beginState)

    def getMachine(self):
        return self.machine

    def getModel(self):
        return self.bbot

    def pushReturnStack(self):
        self.returnStack.append(True)

    def popReturnStack(self):
        value = self.returnStack[-1]
        self.returnStack.pop()
        return value

    def getStateContent(self, stateId):
        return self.stateIdToContent.get(self.convertStateIdToName(stateId))