<commit_before>import logging
import inspect

from botstory.ast import stack_utils
from . import parser, callable, forking
from .. import di, matchers
from ..integrations import mocktracker

logger = logging.getLogger(__name__)


@di.desc(reg=False)
class StoryProcessor:
    def __init__(self, parser_instance, library, middlewares=[]):
        self.library = library
        self.middlewares = middlewares
        self.parser_instance = parser_instance
        self.tracker = mocktracker.MockTracker()

    @di.inject()
    def add_tracker(self, tracker):
        logger.debug('add_tracker')
        logger.debug(tracker)
        if not tracker:
            return
        self.tracker = tracker

    async def match_message(self, message):
        """
        because match_message is recursive we split function to
        public match_message and private _match_message

        :param message:
        :return:
        """
        logger.debug('')
        logger.debug('> match_message <')
        logger.debug('')
        logger.debug('  {} '.format(message))
        logger.debug('self.tracker')
        logger.debug(self.tracker)
        self.tracker.new_message(
            user=message and message['user'],
            data=message['data'],
        )

        session = message['session']
        stack = message['session']['stack']

        waiting_for = None

        while not waiting_for or isinstance(waiting_for, callable.EndOfStory):
            compiled_story = None
            validation_result = None
            stack_tail = None

            if len(session['stack']) > 0:
                logger.debug('  check stack')
                logger.debug('  session = {}'.format(session))
                logger.debug('    session.stack = {}'.format(session['stack']))

                # looking for first valid matcher
                while True:
                    if len(session['stack']) == 0:
                        # we have reach the bottom of stack
                        logger.debug('  we have reach the bottom of stack '
                                     'so no once has receive this message')
                        return None
                    stack_tail = session['stack'].pop()
                    logger.debug('stack_tail {}'.format(stack_tail))
                    if not stack_tail['data']:
                        # TODO: we shouldn't get such case
                        # because it shows that we have stack that can't catch incoming message
                        # (?) maybe possible case when it is in a middle of hierarchy
                        # and comes because the top one didn't match message

                        # one case - dangling of last part of story
                        # we don't clear stack after returning from story
                        break
                    validator = matchers.deserialize(stack_tail['data'])
                    logger.debug('validator {}'.format(validator))

                    if getattr(validator, 'new_scope', False):
                        # TODO:
                        # we are start new story line here
                        # so we don't need to check whether we still have tail of story
                        break

                    logger.debug("stack_tail['topic'] {}".format(stack_tail['topic']))
                    logger.debug("session['stack'] {}".format(session['stack']))
                    logger.debug("self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack'])")
                    logger.debug(self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack']))
                    if stack_tail['step'] < len(
                            self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack']).story_line
                    ):
                        # if we haven't reach last step in list of story so we can parse result
                        break

                logger.debug('    after check session.stack = {}'.format(session['stack']))
                logger.debug('      stack_tail = {}'.format(stack_tail))
                if stack_tail and stack_tail['data']:
                    logger.debug('  got it!')
                    validator = matchers.deserialize(stack_tail['data'])
                    validation_result = validator.validate(message)
                    logger.debug('      validation_result {}'.format(validation_result))
                    if not not validation_result:
                        # it seems we find stack item that matches our message
                        compiled_story = self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack'])

            if not compiled_story:
                compiled_story = self.library.get_global_story(message)
                logger.debug('get_global_story {}'.format(compiled_story))
                if not compiled_story:
                    # there is no stories for such message
                    return True
                stack_tail = stack_utils.build_empty_stack_item(compiled_story.topic)

            session['stack'].append(stack_tail)

            received_data = await self.process_next_part_of_story({
                'step': session['stack'][-1]['step'],
                'story': compiled_story,
                'stack': message['session']['stack'],
            }, validation_result)

            waiting_for = await self.process_story(
                message=message,
                compiled_story=received_data['story'],
                session=message['session'],
            )

            if len(stack) == 0:
                break

        return waiting_for<commit_msg>split case for stack=0 in match_message<commit_after>import logging
import inspect

from botstory.ast import stack_utils
from . import parser, callable, forking
from .. import di, matchers
from ..integrations import mocktracker

logger = logging.getLogger(__name__)


@di.desc(reg=False)
class StoryProcessor:
    def __init__(self, parser_instance, library, middlewares=[]):
        self.library = library
        self.middlewares = middlewares
        self.parser_instance = parser_instance
        self.tracker = mocktracker.MockTracker()

    @di.inject()
    def add_tracker(self, tracker):
        logger.debug('add_tracker')
        logger.debug(tracker)
        if not tracker:
            return
        self.tracker = tracker

    async def match_message(self, message):
        """
        because match_message is recursive we split function to
        public match_message and private _match_message

        :param message:
        :return:
        """
        logger.debug('')
        logger.debug('> match_message <')
        logger.debug('')
        logger.debug('  {} '.format(message))
        logger.debug('self.tracker')
        logger.debug(self.tracker)
        self.tracker.new_message(
            user=message and message['user'],
            data=message['data'],
        )

        session = message['session']
        stack = message['session']['stack']

        waiting_for = None

        while not waiting_for or isinstance(waiting_for, callable.EndOfStory):
            compiled_story = None
            validation_result = None

            if len(session['stack']) == 0:
                compiled_story = self.library.get_global_story(message)
                logger.debug('get_global_story {}'.format(compiled_story))
                if not compiled_story:
                    # there is no stories for such message
                    return None
                session['stack'].append(stack_utils.build_empty_stack_item(compiled_story.topic))
            else:
                stack_tail = None
                logger.debug('  check stack')
                logger.debug('  session = {}'.format(session))
                logger.debug('    session.stack = {}'.format(session['stack']))

                # looking for first valid matcher
                while True:
                    if len(session['stack']) == 0:
                        # we have reach the bottom of stack
                        logger.debug('  we have reach the bottom of stack '
                                     'so no once has receive this message')
                        return None
                    stack_tail = session['stack'][-1]
                    logger.debug('stack_tail {}'.format(stack_tail))
                    if not stack_tail['data']:
                        # TODO: we shouldn't get such case
                        # because it shows that we have stack that can't catch incoming message
                        # (?) maybe possible case when it is in a middle of hierarchy
                        # and comes because the top one didn't match message

                        # one case - dangling of last part of story
                        # we don't clear stack after returning from story
                        break
                    validator = matchers.deserialize(stack_tail['data'])
                    logger.debug('validator {}'.format(validator))

                    if getattr(validator, 'new_scope', False):
                        # TODO:
                        # we are start new story line here
                        # so we don't need to check whether we still have tail of story
                        break

                    logger.debug("stack_tail['topic'] {}".format(stack_tail['topic']))
                    logger.debug("session['stack'] {}".format(session['stack']))
                    logger.debug("self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack'])")
                    logger.debug(self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack']))
                    if stack_tail['step'] < len(
                            self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack'][:-1]).story_line
                    ):
                        # if we haven't reach last step in list of story so we can parse result
                        break

                    session['stack'].pop()

                logger.debug('    after check session.stack = {}'.format(session['stack']))
                logger.debug('      stack_tail = {}'.format(stack_tail))
                if stack_tail and stack_tail['data']:
                    logger.debug('  got it!')
                    validator = matchers.deserialize(stack_tail['data'])
                    validation_result = validator.validate(message)
                    logger.debug('      validation_result {}'.format(validation_result))
                    if not not validation_result:
                        # it seems we find stack item that matches our message
                        compiled_story = self.library.get_story_by_topic(stack_tail['topic'], stack=session['stack'][:-1])

            received_data = await self.process_next_part_of_story({
                'step': session['stack'][-1]['step'],
                'story': compiled_story,
                'stack': message['session']['stack'],
            }, validation_result)

            waiting_for = await self.process_story(
                message=message,
                compiled_story=received_data['story'],
                session=message['session'],
            )

            if len(stack) == 0:
                break

        return waiting_for
{'fraction_non_alphanumeric': 0.09671757065121994, 'fraction_numerical': 0.00105318588730911, 'mean_word_length': 1.6661207299953205, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '630287', 'n_tokens_mistral': 2793, 'n_tokens_neox': 2621, 'n_words': 705}