Skip to content

Commit

Permalink
Merge pull request #140 from botstory/hotfix/broken-tests
Browse files Browse the repository at this point in the history
Hotfix/broken tests
  • Loading branch information
hyzhak committed Feb 20, 2017
2 parents 6c2966e + f359e39 commit cf31524
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 159 deletions.
14 changes: 12 additions & 2 deletions botstory/ast/callable.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ async def startpoint(self, *args, **kwargs):

# we are going deeper so prepare one more item in stack
logger.debug(' action: extend stack by +1')
session['stack'].append(stack_utils.build_empty_stack_item(self.ast_node.topic))
session = {
**session,
'stack': session['stack'] + [stack_utils.build_empty_stack_item(self.ast_node.topic)],
}

ctx = story_context.StoryContext(message={
'session': session,
# TODO: should get user from context
Expand All @@ -60,9 +64,15 @@ async def startpoint(self, *args, **kwargs):
ctx = await self.processor.process_story(ctx)
ctx = story_context.reducers.scope_out(ctx)

logger.debug('# result of callable')
logger.debug(ctx)

if isinstance(ctx.waiting_for, EndOfStory):
return ctx.waiting_for.data
return ctx.waiting_for

# because we would like to return to stories from caller
# we should return our context to callee
return ctx


class CallableStoriesAPI:
Expand Down
10 changes: 3 additions & 7 deletions botstory/ast/callable_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ async def store_arguments(ctx):
await story.say(res, user=ctx['user'])
trigger_2.passed()

await meet_ava_story(session=talk.session, user=talk.user)
ctx = await meet_ava_story(session=talk.session, user=talk.user)
talk.init_by_ctx(ctx)

await talk.pure_text('Eugene')
await talk.pure_text('13')
Expand Down Expand Up @@ -159,29 +160,24 @@ async def test_call_story_from_another_callable():
def one_story():
@story.part()
def so_1(ctx):
logger.debug('[!] def so_1(ctx)')
pass

@story.part()
async def so_2(ctx):
logger.debug('[!] def so_2(ctx)')
await another_story(session=ctx['session'], user=ctx['user'])

@story.part()
def so_3(ctx):
logger.debug('[!] def so_3(ctx)')
trigger_2.passed()

@story.callable()
def another_story():
@story.part()
def has(cxt):
logger.debug('[!] def has(cxt):')
pass

@story.part()
def so(ctx):
logger.debug('[!] def so(cxt):')
trigger_1.passed()
return callable.EndOfStory()

Expand Down Expand Up @@ -252,7 +248,7 @@ def tail_recursion(ctx):
def enter_to_the_saloon():
@story.part()
async def start_a_game(ctx):
return await flip_a_coin(user=user, session=ctx['session'])
return await flip_a_coin(user=ctx['user'], session=ctx['session'])

@story.part()
def game_over(ctx):
Expand Down
5 changes: 4 additions & 1 deletion botstory/ast/forking.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ def get_child_by_validation_result(self, validation_result):
case_stories = self.match_children('default_case', True)

if len(case_stories) == 0:
logger.debug(' do not have any fork here')
logger.debug('#######################################')
logger.debug('# [!] do not have any fork here')
logger.debug('# context = {}'.format(self))
logger.debug('# validation_result = {}'.format(validation_result))
return None

return case_stories[0]
Expand Down
9 changes: 5 additions & 4 deletions botstory/ast/forking_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ def next_room_2(ctx):


@pytest.mark.asyncio
@pytest.mark.skip('not implemented yet')
async def test_simplify_syntax_wait_for_any_text():
left_trigger = SimpleTrigger()
right_trigger = SimpleTrigger()
Expand Down Expand Up @@ -334,6 +335,7 @@ def right_room_passed(ctx):


@pytest.mark.asyncio
@pytest.mark.skip('not implemented yet')
async def test_simplify_syntax_for_case_matching():
left_trigger = SimpleTrigger()
right_trigger = SimpleTrigger()
Expand Down Expand Up @@ -367,6 +369,7 @@ def right_room_passed(ctx):


@pytest.mark.asyncio
@pytest.mark.skip('not implemented yet')
async def test_simplify_syntax_case_matches_previous_returned_value():
left_trigger = SimpleTrigger()
right_trigger = SimpleTrigger()
Expand Down Expand Up @@ -398,8 +401,8 @@ def right_room_passed(ctx):
assert right_trigger.is_triggered


# TODO: simplify syntax
@pytest.mark.asyncio
@pytest.mark.skip('test warn message here')
async def test_warn_on_incorrect_syntax_user_forgot_add_switch_value():
left_trigger = SimpleTrigger()
right_trigger = SimpleTrigger()
Expand All @@ -416,14 +419,12 @@ def enter(ctx):
# return 'right'
pass

# TODO: !!!!!!!!!!!
@story.case('left')
def left_room():
@story.part()
def left_room_passed(ctx):
return left_trigger.passed()

# TODO: !!!!!!!!!!!
@story.case('right')
def right_room():
@story.part()
Expand Down Expand Up @@ -573,7 +574,7 @@ def store_end(ctx):
def room_2():
@story.part()
async def meet_ogr(ctx):
return await cast_the_magic(user=ctx['user'], session=session)
return await cast_the_magic(user=ctx['user'], session=ctx['session'])

@story.part()
def store_end(ctx):
Expand Down
76 changes: 33 additions & 43 deletions botstory/ast/loop_test.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,45 @@
import pytest

import botstory
from botstory.utils import answer, build_fake_session, build_fake_user, SimpleTrigger
from botstory.utils import answer, SimpleTrigger

story = None


def teardown_function(function):
story.clear()


@pytest.mark.skip
@pytest.mark.asyncio
@pytest.mark.skip
async def test_jump_in_a_loop():
global story
story = botstory.Story()

user = build_fake_user()
session = build_fake_session()

trigger_show_global_help = SimpleTrigger()
trigger_show_local_help = SimpleTrigger()

@story.on('?')
def global_help_story():
@story.part()
def show_global_help(ctx):
trigger_show_global_help.passed()

@story.on('start job')
def one_job():
@story.part()
def show_do_job(ctx):
pass

@story.loop()
def job_scope():
@story.on('?')
def local_help_story():
@story.part()
def show_local_help():
trigger_show_local_help.passed()

@story.on('work')
def job_story():
@story.part()
def do_some_job(ctx):
pass

await answer.pure_text('start job', session, user, story)
await answer.pure_text('?', session, user, story)
with answer.Talk() as talk:
story = talk.story

@story.on('?')
def global_help_story():
@story.part()
def show_global_help(ctx):
trigger_show_global_help.passed()

@story.on('start job')
def one_job():
@story.part()
def show_do_job(ctx):
pass

@story.loop()
def job_scope():
@story.on('?')
def local_help_story():
@story.part()
def show_local_help():
trigger_show_local_help.passed()

@story.on('work')
def job_story():
@story.part()
def do_some_job(ctx):
pass

await talk.pure_text('start job')
await talk.pure_text('?')

assert trigger_show_global_help.is_triggered is not True
assert trigger_show_local_help.is_triggered is True
42 changes: 26 additions & 16 deletions botstory/ast/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,32 @@ async def process_story(self, ctx):

# integrate over parts of story
last_story_part = None
for story_part_ctx in story_context.reducers.iterate_storyline(ctx):
logger.debug('# in a loop')
logger.debug(story_part_ctx)

self.tracker.story(story_part_ctx)

if story_part_ctx.has_child_story():
story_part_ctx = story_context.reducers.scope_in(story_part_ctx)
story_part_ctx = await self.process_story(story_part_ctx)
story_part_ctx = story_context.reducers.scope_out(story_part_ctx)
else:
story_part_ctx = await story_context.reducers.execute(story_part_ctx)

if story_part_ctx.is_waiting_for_input():
return story_part_ctx
last_story_part = story_part_ctx
storyline = story_context.reducers.iterate_storyline(ctx)
story_part_ctx = next(storyline)

# loop thought storyline
# we can't use for here because we should send update context
# back to iterator
while True:
try:
logger.debug('# in a loop')
logger.debug(story_part_ctx)

self.tracker.story(story_part_ctx)

if story_part_ctx.has_child_story():
story_part_ctx = story_context.reducers.scope_in(story_part_ctx)
story_part_ctx = await self.process_story(story_part_ctx)
story_part_ctx = story_context.reducers.scope_out(story_part_ctx)
else:
story_part_ctx = await story_context.reducers.execute(story_part_ctx)

if story_part_ctx.is_waiting_for_input():
return story_part_ctx
last_story_part = story_part_ctx
story_part_ctx = storyline.send(story_part_ctx)
except StopIteration:
break

if last_story_part is None:
raise Exception('story line is empty')
Expand Down
11 changes: 9 additions & 2 deletions botstory/ast/story_context/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@

import json
import logging
import uuid

logger = logging.getLogger(__name__)


class StoryContext:
def __init__(self, message, library, waiting_for=None):
def __init__(self, message, library, waiting_for=None, parent_uid=None):
self.uid = str(uuid.uuid4())
self.parent_uid = parent_uid
self.library = library
self.message = message
self.waiting_for = waiting_for

def clone(self):
return StoryContext(self.message,
self.library,
self.waiting_for)
self.waiting_for,
parent_uid=self.uid,
)

def compiled_story(self):
if self.is_empty_stack():
Expand Down Expand Up @@ -92,6 +97,8 @@ def stack_tail(self):

def to_json(self):
return {
'uid': self.uid,
'parent_uid': self.parent_uid,
'message': self.message,
'waiting_for': str(self.waiting_for),
}
Expand Down

0 comments on commit cf31524

Please sign in to comment.