Ejemplo n.º 1
0
 def test_property_initial(self):
     states = ['A', 'B', 'C', 'D']
     # Define with list of dictionaries
     transitions = [
         {'trigger': 'walk', 'source': 'A', 'dest': 'B'},
         {'trigger': 'run', 'source': 'B', 'dest': 'C'},
         {'trigger': 'sprint', 'source': 'C', 'dest': 'D'}
     ]
     m = Machine(states=states, transitions=transitions, initial='A')
     self.assertEquals(m.initial, 'A')
     m = Machine(states=states, transitions=transitions, initial='C')
     self.assertEquals(m.initial, 'C')
     m = Machine(states=states, transitions=transitions)
     self.assertEquals(m.initial, 'initial')
Ejemplo n.º 2
0
 def test_use_machine_as_model(self):
     states = ['A', 'B', 'C', 'D']
     m = Machine(states=states, initial='A')
     m.add_transition('move', 'A', 'B')
     m.add_transition('move_to_C', 'B', 'C')
     m.move()
     self.assertEquals(m.state, 'B')
Ejemplo n.º 3
0
    def __init__(self, datasource, criteria, kind):

        self.datasource = datasource
        self.criteria = criteria
        self.kind = kind

        self.maxcount = 50
        self.hits = -1

        self.querycount = 0

        self.machine = Machine(model=self, states=QueryDateRangeNarrower.states, initial='asleep')

        self.machine.add_transition('start', '*',     'init', after='work')
        self.machine.add_transition('check', '*',     'finished', conditions=['is_ready'])
        self.machine.add_transition('step',  'init',  'finished', conditions='is_century_out_of_bounds')
        self.machine.add_transition('step',  'init',  'whole',  after=['runquery', 'check'])
        self.machine.add_transition('step',  'whole', 'init',  conditions='no_hits', after='range_next_century')


        if self.kind == self.OLDEST:
            self.date_from = Arrow.fromdatetime(datetime.datetime(1800, 01, 01))
            self.date_to   = Arrow.fromdatetime(datetime.datetime(1899, 12, 31))
            self.factor    = +1

            self.machine.add_transition('step',  'whole', 'left',  unless='is_ready', after=['range_whole_left', 'runquery', 'check'])
            self.machine.add_transition('step',  'left',  'right', conditions='no_hits', after=['range_left_right', 'runquery', 'check'])
            self.machine.add_transition('step',  'left',  'whole', unless='is_ready', after=['range_shrink'])
            self.machine.add_transition('step',  'right', 'whole', unless='is_ready', after=['range_shrink'])

        elif self.kind == self.NEWEST:
            self.date_from = Arrow.fromdatetime(datetime.datetime(2000, 01, 01))
            self.date_to   = Arrow.utcnow()
            self.date_to   += relativedelta(months=12-self.date_to.month, days=31-self.date_to.day)
            self.factor    = -1

            self.machine.add_transition('step',  'whole', 'right',  unless='is_ready', after=['range_whole_right', 'runquery', 'check'])
            self.machine.add_transition('step',  'right',  'left', conditions='no_hits', after=['range_right_left', 'runquery', 'check'])
            self.machine.add_transition('step',  'right',  'whole', unless='is_ready', after=['range_shrink'])
            self.machine.add_transition('step',  'left', 'whole', unless='is_ready', after=['range_shrink'])

        else:
            raise ValueError('kind must be self.OLDEST or self.NEWEST')

        self.delta = (self.date_to - self.date_from) / 2
Ejemplo n.º 4
0
 def test_transition_definitions(self):
     states = ['A', 'B', 'C', 'D']
     # Define with list of dictionaries
     transitions = [
         {'trigger': 'walk', 'source': 'A', 'dest': 'B'},
         {'trigger': 'run', 'source': 'B', 'dest': 'C'},
         {'trigger': 'sprint', 'source': 'C', 'dest': 'D'}
     ]
     m = Machine(states=states, transitions=transitions, initial='A')
     m.walk()
     self.assertEquals(m.state, 'B')
     # Define with list of lists
     transitions = [
         ['walk', 'A', 'B'],
         ['run', 'B', 'C'],
         ['sprint', 'C', 'D']
     ]
     m = Machine(states=states, transitions=transitions, initial='A')
     m.to_C()
     m.sprint()
     self.assertEquals(m.state, 'D')
Ejemplo n.º 5
0
    def test_generic_callbacks(self):

        m = Machine(None, states=['A', 'B'], before_state_change='before_state_change',
            after_state_change='after_state_change', send_event=True, initial='A', auto_transitions=True)

        m.before_state_change = MagicMock()
        m.after_state_change = MagicMock()

        m.to_B()
        self.assertTrue(m.before_state_change.called)
        self.assertTrue(m.after_state_change.called)
Ejemplo n.º 6
0
 def test_send_event_data(self):
     states = ['A', 'B', 'C', 'D']
     s = Stuff()
     # First pass positional and keyword args directly to the callback
     m = Machine(model=s, states=states, initial='A', send_event=False)
     m.add_transition(
         trigger='advance', source='A', dest='B', before='set_message')
     s.advance(message='Hallo. My name is Inigo Montoya.')
     self.assertTrue(s.message.startswith('Hallo.'))
     # Now wrap arguments in an EventData instance
     m.send_event = True
     m.add_transition(
         trigger='advance', source='B', dest='C', before='extract_message')
     s.advance(message='You killed my father. Prepare to die.')
     self.assertTrue(s.message.startswith('You'))
Ejemplo n.º 7
0
 def test_init_machine_with_hella_arguments(self):
     states = [
         State('State1'),
         'State2',
         {
             'name': 'State3',
             'on_enter': 'hello_world'
         }
     ]
     transitions = [
         {'trigger': 'advance',
             'source': 'State2',
             'dest': 'State3'
          }
     ]
     s = Stuff()
     Machine(
         model=s, states=states, transitions=transitions, initial='State2')
     s.advance()
     self.assertEquals(s.message, 'Hello World!')
Ejemplo n.º 8
0
class QueryDateRangeNarrower(object):

    states = ['init', 'whole', 'left', 'right', 'finished', 'asleep']
    OLDEST = 1
    NEWEST = 2

    def __init__(self, datasource, criteria, kind):

        self.datasource = datasource
        self.criteria = criteria
        self.kind = kind

        self.maxcount = 50
        self.hits = -1

        self.querycount = 0

        self.machine = Machine(model=self,
                               states=QueryDateRangeNarrower.states,
                               initial='asleep')

        self.machine.add_transition('start', '*', 'init', after='work')
        self.machine.add_transition('check',
                                    '*',
                                    'finished',
                                    conditions=['is_ready'])
        self.machine.add_transition('step',
                                    'init',
                                    'finished',
                                    conditions='is_century_out_of_bounds')
        self.machine.add_transition('step',
                                    'init',
                                    'whole',
                                    after=['runquery', 'check'])
        self.machine.add_transition('step',
                                    'whole',
                                    'init',
                                    conditions='no_hits',
                                    after='range_next_century')

        if self.kind == self.OLDEST:
            self.date_from = Arrow.fromdatetime(
                datetime.datetime(1800, 0o1, 0o1))
            self.date_to = Arrow.fromdatetime(datetime.datetime(1899, 12, 31))
            self.factor = +1

            self.machine.add_transition(
                'step',
                'whole',
                'left',
                unless='is_ready',
                after=['range_whole_left', 'runquery', 'check'])
            self.machine.add_transition(
                'step',
                'left',
                'right',
                conditions='no_hits',
                after=['range_left_right', 'runquery', 'check'])
            self.machine.add_transition('step',
                                        'left',
                                        'whole',
                                        unless='is_ready',
                                        after=['range_shrink'])
            self.machine.add_transition('step',
                                        'right',
                                        'whole',
                                        unless='is_ready',
                                        after=['range_shrink'])

        elif self.kind == self.NEWEST:
            self.date_from = Arrow.fromdatetime(
                datetime.datetime(2000, 0o1, 0o1))
            self.date_to = Arrow.utcnow()
            self.date_to += relativedelta(months=12 - self.date_to.month,
                                          days=31 - self.date_to.day)
            self.factor = -1

            self.machine.add_transition(
                'step',
                'whole',
                'right',
                unless='is_ready',
                after=['range_whole_right', 'runquery', 'check'])
            self.machine.add_transition(
                'step',
                'right',
                'left',
                conditions='no_hits',
                after=['range_right_left', 'runquery', 'check'])
            self.machine.add_transition('step',
                                        'right',
                                        'whole',
                                        unless='is_ready',
                                        after=['range_shrink'])
            self.machine.add_transition('step',
                                        'left',
                                        'whole',
                                        unless='is_ready',
                                        after=['range_shrink'])

        else:
            raise ValueError('kind must be self.OLDEST or self.NEWEST')

        self.delta = (self.date_to - self.date_from) / 2

    def runquery(self):
        criteria = self.criteria.copy()
        criteria['pubdate'] = 'within {date_from},{date_to}'.format(
            date_from=self.date_from.format('YYYY-MM-DD'),
            date_to=self.date_to.format('YYYY-MM-DD'))

        query = make_expression_filter({
            'datasource': self.datasource,
            'format': 'comfort',
            'criteria': criteria,
        })['expression']

        if self.datasource == 'ops':
            self.response, self.hits = query_ops(query, limit=self.maxcount)

        elif self.datasource == 'depatisnet':
            self.response, self.hits = query_depatisnet(query,
                                                        limit=self.maxcount)

        elif self.datasource == 'sip':
            self.response, self.hits = query_sip(query, limit=self.maxcount)

        else:
            raise ValueError('Data source "{0}" not implemented'.format(
                self.datasource))

        self.querycount += 1

    def no_hits(self):
        return self.hits == 0

    def is_ready(self):
        return self.hits > 0 and self.hits <= self.maxcount

    # for "oldest" searches
    def range_whole_left(self):
        self.date_to -= self.delta

    def range_left_right(self):
        self.date_from += self.delta
        self.date_to += self.delta

    # for "newest" searches
    def range_whole_right(self):
        self.date_from += self.delta

    def range_right_left(self):
        self.date_from -= self.delta
        self.date_to -= self.delta

    def range_shrink(self):
        self.delta /= 2

    def range_next_century(self):

        century = self.date_from.year / 100
        century += self.factor

        year_begin = century * 100 + 00
        year_end = century * 100 + 99

        self.date_from += relativedelta(years=year_begin - self.date_from.year,
                                        months=-self.date_from.month + 1,
                                        days=-self.date_from.day + 1)
        self.date_to += relativedelta(years=year_end - self.date_to.year,
                                      months=12 - self.date_to.month,
                                      days=31 - self.date_to.day)

    def is_century_out_of_bounds(self):
        return self.date_from.year > Arrow.utcnow(
        ).year or self.date_to.year < 1800

    def work(self):
        debug = False
        while True:
            if debug:
                print('-' * 42)
                print('state:', self.state)
                print('delta:', self.delta)
                print('querycount:', self.querycount)
            if self.state == 'finished' or self.querycount > 15:
                break
            self.step()
Ejemplo n.º 9
0
    def __init__(self, states, initial='A'):

        self.state = None

        Machine.__init__(self, states=states, initial=initial)
Ejemplo n.º 10
0
 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()
Ejemplo n.º 11
0
    def test_ordered_transitions(self):
        states = ['beginning', 'middle', 'end']
        m = Machine(None, states)
        m.add_ordered_transitions()
        self.assertEquals(m.state, 'initial')
        m.next_state()
        self.assertEquals(m.state, 'beginning')
        m.next_state()
        m.next_state()
        self.assertEquals(m.state, 'end')
        m.next_state()
        self.assertEquals(m.state, 'initial')

        # Include initial state in loop
        m = Machine(None, states)
        m.add_ordered_transitions(loop_includes_initial=False)
        m.to_end()
        m.next_state()
        self.assertEquals(m.state, 'beginning')

        # Test user-determined sequence and trigger name
        m = Machine(None, states, initial='beginning')
        m.add_ordered_transitions(['end', 'beginning'], trigger='advance')
        m.advance()
        self.assertEquals(m.state, 'end')
        m.advance()
        self.assertEquals(m.state, 'beginning')

        # Via init argument
        m = Machine(
            None, states, initial='beginning', ordered_transitions=True)
        m.next_state()
        self.assertEquals(m.state, 'middle')
Ejemplo n.º 12
0
 def test_auto_transitions(self):
     states = ['A', {'name': 'B'}, State(name='C')]
     m = Machine(None, states, initial='A', auto_transitions=True)
     m.to_B()
     self.assertEquals(m.state, 'B')
     m.to_C()
     self.assertEquals(m.state, 'C')
     m.to_A()
     self.assertEquals(m.state, 'A')
     # Should fail if auto transitions is off...
     m = Machine(None, states, initial='A', auto_transitions=False)
     with self.assertRaises(TypeError):
         m.to_C()
Ejemplo n.º 13
0
    def __init__(self):

        self.state = None

        states = ['A', 'B', 'C', 'D', 'E', 'F']
        self.machine = Machine(self, states=states, initial='A')